updating with r7-msf
commit
907983db4a
|
@ -0,0 +1,7 @@
|
||||||
|
--protected
|
||||||
|
--exclude samples/
|
||||||
|
--exclude \.ut\.rb/
|
||||||
|
--exclude \.ts\.rb/
|
||||||
|
--files CONTRIBUTING.md,COPYING,HACKING,LICENSE
|
||||||
|
lib/msf/**/*.rb
|
||||||
|
lib/rex/**/*.rb
|
2
Gemfile
2
Gemfile
|
@ -7,7 +7,7 @@ gem 'activerecord'
|
||||||
# Needed for some admin modules (scrutinizer_add_user.rb)
|
# Needed for some admin modules (scrutinizer_add_user.rb)
|
||||||
gem 'json'
|
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.6.0'
|
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.6.2'
|
||||||
# Needed by msfgui and other rpc components
|
# Needed by msfgui and other rpc components
|
||||||
gem 'msgpack'
|
gem 'msgpack'
|
||||||
# Needed by anemone crawler
|
# Needed by anemone crawler
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/rapid7/metasploit_data_models.git
|
remote: git://github.com/rapid7/metasploit_data_models.git
|
||||||
revision: 0285d6e199f125b33214100dcb0f4eeb12ee765f
|
revision: 67d78f9ce59a74ad9d6e8d3f9e68760ff4d2ec55
|
||||||
tag: 0.6.0
|
tag: 0.6.2
|
||||||
specs:
|
specs:
|
||||||
metasploit_data_models (0.6.0)
|
metasploit_data_models (0.6.2)
|
||||||
activerecord (>= 3.2.10)
|
activerecord (>= 3.2.10)
|
||||||
activesupport
|
activesupport
|
||||||
pg
|
pg
|
||||||
|
|
85
Rakefile
85
Rakefile
|
@ -1,52 +1,49 @@
|
||||||
require 'bundler/setup'
|
require 'bundler/setup'
|
||||||
|
|
||||||
require 'rspec/core/rake_task'
|
require 'metasploit_data_models'
|
||||||
require 'yard'
|
|
||||||
|
|
||||||
RSpec::Core::RakeTask.new(:spec)
|
print_without = false
|
||||||
|
|
||||||
task :default => :spec
|
begin
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
rescue LoadError
|
||||||
|
puts "rspec not in bundle, so can't set up spec tasks. " \
|
||||||
|
"To run specs ensure to install the development and test groups."
|
||||||
|
|
||||||
namespace :yard do
|
print_without = true
|
||||||
yard_files = [
|
else
|
||||||
# Ruby source files first
|
RSpec::Core::RakeTask.new(:spec)
|
||||||
'lib/msf/**/*.rb',
|
|
||||||
'lib/rex/**/*.rb',
|
|
||||||
# Anything after '-' is a normal documentation, not source
|
|
||||||
'-',
|
|
||||||
'COPYING',
|
|
||||||
'HACKING',
|
|
||||||
'LICENSE',
|
|
||||||
'CONTRIBUTING.md',
|
|
||||||
]
|
|
||||||
yard_options = [
|
|
||||||
# include documentation for protected methods for developers extending the code.
|
|
||||||
'--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|
|
task :default => :spec
|
||||||
t.files = yard_files
|
|
||||||
# --no-stats here as 'stats' task called after will print fuller stats
|
|
||||||
t.options = yard_options + ['--no-stats']
|
|
||||||
|
|
||||||
t.after = Proc.new {
|
|
||||||
Rake::Task['yard:stats'].execute
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Shows stats for YARD Documentation including listing undocumented modules, classes, constants, and methods"
|
|
||||||
task :stats => :environment do
|
|
||||||
stats = YARD::CLI::Stats.new
|
|
||||||
yard_arguments = yard_options + ['--compact', '--list-undoc'] + yard_files
|
|
||||||
stats.run(*yard_arguments)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# @todo Figure out how to just clone description from yard:doc
|
begin
|
||||||
desc "Generate YARD documentation"
|
require 'yard'
|
||||||
# allow calling namespace to as a task that goes to default task for namespace
|
rescue LoadError
|
||||||
task :yard => ['yard:doc']
|
puts "yard not in bundle, so can't set up yard tasks. " \
|
||||||
|
"To generate documentation ensure to install the development group."
|
||||||
|
|
||||||
|
print_without = true
|
||||||
|
end
|
||||||
|
|
||||||
|
metasploit_data_models_task_glob = MetasploitDataModels.root.join(
|
||||||
|
'lib',
|
||||||
|
'tasks',
|
||||||
|
'**',
|
||||||
|
'*.rake'
|
||||||
|
).to_s
|
||||||
|
|
||||||
|
# include tasks from metasplioit_data_models, such as `rake yard`.
|
||||||
|
# metasploit-framework specific yard options are in .yardopts
|
||||||
|
Dir.glob(metasploit_data_models_task_glob) do |path|
|
||||||
|
load path
|
||||||
|
end
|
||||||
|
|
||||||
|
if print_without
|
||||||
|
puts "Bundle currently installed " \
|
||||||
|
"'--without #{Bundler.settings.without.join(' ')}'."
|
||||||
|
puts "To clear the without option do `bundle install --without ''` " \
|
||||||
|
"(the --without flag with an empty string) or " \
|
||||||
|
"`rm -rf .bundle` to remove the .bundle/config manually and " \
|
||||||
|
"then `bundle install`"
|
||||||
|
end
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,35 @@
|
||||||
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)
|
12 Feb 13 (tested against msf 16438)
|
||||||
---------
|
---------
|
||||||
- Fixed a corner case preventing the display of removed host labels
|
- Fixed a corner case preventing the display of removed host labels
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
source 'http://rubygems.org'
|
|
||||||
gem 'rails', '3.2.2'
|
|
||||||
gem 'authlogic'
|
|
||||||
gem 'prototype_legacy_helper', '0.0.0', :git => 'git://github.com/jvennix-r7/prototype_legacy_helper.git'
|
|
||||||
gem 'state_machine', '1.1.2'
|
|
||||||
gem 'liquid', '2.3.0'
|
|
||||||
gem 'ice_cube'
|
|
||||||
gem 'acts_as_list'
|
|
||||||
gem 'mime-types', '1.18', :git => "git://github.com/rapid7/mime-types.git"
|
|
||||||
gem 'metasploit_data_models', '0.0.2', :git => "git://github.com/rapid7/metasploit_data_models.git"
|
|
||||||
gem 'robots', '0.10.1'
|
|
||||||
|
|
|
@ -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: 12 Feb 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 {
|
||||||
|
later(lambda({
|
||||||
local('$model $row');
|
local('$model $row');
|
||||||
$model = [$1 getModel];
|
$model = [$a getModel];
|
||||||
[$model clear: size($2) * 2];
|
[$model clear: size($b) * 2];
|
||||||
foreach $row ($2) {
|
foreach $row ($b) {
|
||||||
[$model addEntry: $row];
|
[$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);
|
||||||
|
|
|
@ -583,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?
|
||||||
#
|
#
|
||||||
|
@ -834,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 $DESCRIBE @CLOSEME');
|
global('$frame $tabs $menubar $msfrpc_handle $REMOTE $cortana $MY_ADDRESS $DESCRIBE @CLOSEME @POOL');
|
||||||
|
|
||||||
sub describeHost {
|
sub describeHost {
|
||||||
local('$desc');
|
local('$desc');
|
||||||
|
@ -164,13 +164,14 @@ 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";
|
$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;
|
||||||
|
|
||||||
|
@ -178,6 +179,17 @@ sub _connectToMetasploit {
|
||||||
[$progress close];
|
[$progress close];
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ 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");
|
||||||
|
if ($__frame__ !is $null && [$__frame__ getPreferences] !is $null) {
|
||||||
|
$prefs = [$__frame__ getPreferences];
|
||||||
|
}
|
||||||
|
else {
|
||||||
$prefs = [new Properties];
|
$prefs = [new Properties];
|
||||||
if (-exists $file) {
|
if (-exists $file) {
|
||||||
[$prefs load: [new java.io.FileInputStream: $file]];
|
[$prefs load: [new java.io.FileInputStream: $file]];
|
||||||
|
@ -65,6 +69,11 @@ sub loadPreferences {
|
||||||
[$prefs load: resource("resources/armitage.prop")];
|
[$prefs load: resource("resources/armitage.prop")];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($__frame__ !is $null) {
|
||||||
|
[$__frame__ setPreferences: $prefs];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# parse command line options here.
|
# parse command line options here.
|
||||||
|
|
||||||
global('$yaml_file $yaml_entry');
|
global('$yaml_file $yaml_entry');
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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,20 +231,22 @@ public class ConsoleClient implements Runnable, ActionListener {
|
||||||
lastRead = System.currentTimeMillis();
|
lastRead = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (this.window != null && !this.window.isShowing() && (now - last) < 1500) {
|
||||||
|
/* check if our window is not showing... if not, then we're going to switch to a very reduced
|
||||||
|
read schedule. */
|
||||||
|
}
|
||||||
|
else {
|
||||||
read = readResponse();
|
read = readResponse();
|
||||||
|
|
||||||
if (read == null || "failure".equals( read.get("result") + "" )) {
|
if (read == null || "failure".equals( read.get("result") + "" )) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processRead(read);
|
processRead(read);
|
||||||
|
last = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
if ((System.currentTimeMillis() - lastRead) <= 500) {
|
Thread.sleep(100);
|
||||||
Thread.sleep(10);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Thread.sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (listeners) {
|
synchronized (listeners) {
|
||||||
shouldRead = go_read;
|
shouldRead = go_read;
|
||||||
|
|
|
@ -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,12 +30,17 @@ 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);
|
||||||
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
|
SleepUtils.runCode(f, "laterz", null, argz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
SleepUtils.runCode(f, "laterz", null, argz);
|
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 + ")");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
@ -85,6 +86,22 @@ public abstract class RpcConnectionImpl implements RpcConnection, Async {
|
||||||
|
|
||||||
protected HashMap locks = new HashMap();
|
protected HashMap locks = new HashMap();
|
||||||
protected String address = "";
|
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() {
|
public String getLocalAddress() {
|
||||||
return address;
|
return address;
|
||||||
|
@ -133,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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class MultiFrame extends JFrame implements KeyEventDispatcher {
|
||||||
protected JPanel content;
|
protected JPanel content;
|
||||||
protected CardLayout cards;
|
protected CardLayout cards;
|
||||||
protected LinkedList buttons;
|
protected LinkedList buttons;
|
||||||
|
protected Properties prefs;
|
||||||
|
|
||||||
private static class ArmitageInstance {
|
private static class ArmitageInstance {
|
||||||
public ArmitageApplication app;
|
public ArmitageApplication app;
|
||||||
|
@ -24,6 +25,14 @@ public class MultiFrame extends JFrame implements KeyEventDispatcher {
|
||||||
public RpcConnection client;
|
public RpcConnection client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPreferences(Properties prefs) {
|
||||||
|
this.prefs = prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Properties getPreferences() {
|
||||||
|
return prefs;
|
||||||
|
}
|
||||||
|
|
||||||
public Map getClients() {
|
public Map getClients() {
|
||||||
synchronized (buttons) {
|
synchronized (buttons) {
|
||||||
Map r = new HashMap();
|
Map r = new HashMap();
|
||||||
|
|
|
@ -1,6 +1,35 @@
|
||||||
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)
|
12 Feb 13 (tested against msf 16438)
|
||||||
---------
|
---------
|
||||||
- Fixed a corner case preventing the display of removed host labels
|
- Fixed a corner case preventing the display of removed host labels
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
require 'rails'
|
|
||||||
|
|
||||||
module MetasploitDataModels
|
|
||||||
class Engine < Rails::Engine
|
|
||||||
|
|
||||||
# @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
|
|
||||||
config.generators do |g|
|
|
||||||
g.assets false
|
|
||||||
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
|
||||||
g.helper false
|
|
||||||
g.test_framework :rspec, :fixture => false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
# @note All options not specific to any given rake task should go in the .yardopts file so they are available to both
|
|
||||||
# the below rake tasks and when invoking `yard` from the command line
|
|
||||||
|
|
||||||
require 'yard'
|
|
||||||
require 'yard/rake/yardoc_task'
|
|
||||||
|
|
||||||
namespace :yard do
|
|
||||||
YARD::Rake::YardocTask.new(:doc) do |t|
|
|
||||||
# --no-stats here as 'stats' task called after will print fuller stats
|
|
||||||
t.options = ['--no-stats']
|
|
||||||
|
|
||||||
t.after = Proc.new {
|
|
||||||
Rake::Task['yard:stats'].execute
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Shows stats for YARD Documentation including listing undocumented modules, classes, constants, and methods"
|
|
||||||
task :stats => :environment do
|
|
||||||
stats = YARD::CLI::Stats.new
|
|
||||||
stats.run('--compact', '--list-undoc')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @todo Figure out how to just clone description from yard:doc
|
|
||||||
desc "Generate YARD documentation"
|
|
||||||
# allow calling namespace to as a task that goes to default task for namespace
|
|
||||||
task :yard => ['yard:doc']
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env rake
|
||||||
|
begin
|
||||||
|
require 'bundler/setup'
|
||||||
|
rescue LoadError
|
||||||
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||||
|
end
|
||||||
|
|
||||||
|
print_without = false
|
||||||
|
APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
|
||||||
|
|
||||||
|
begin
|
||||||
|
load 'rails/tasks/engine.rake'
|
||||||
|
rescue LoadError
|
||||||
|
puts "railties not in bundle, so can't load engine tasks."
|
||||||
|
print_without = true
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'rspec/core'
|
||||||
|
rescue LoadError
|
||||||
|
puts "rspec not in bundle, so can't set up spec tasks. " \
|
||||||
|
"To run specs ensure to install the development and test groups."
|
||||||
|
print_without = true
|
||||||
|
else
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
if print_without
|
||||||
|
puts "Bundle currently installed '--without #{Bundler.settings.without.join(' ')}'."
|
||||||
|
puts "To clear the without option do `bundle install --without ''` (the --without flag with an empty string) or " \
|
||||||
|
"`rm -rf .bundle` to remove the .bundle/config manually and then `bundle install`"
|
||||||
|
end
|
|
@ -15,9 +15,8 @@ class Mdm::WebVuln < ActiveRecord::Base
|
||||||
# CONSTANTS
|
# CONSTANTS
|
||||||
#
|
#
|
||||||
|
|
||||||
# A percentage {#confidence} that the vulnerability is real and not a false positive. 0 is not allowed because there
|
# A percentage {#confidence} that the vulnerability is real and not a false positive.
|
||||||
# shouldn't be an {Mdm::WebVuln} record if there is 0% {#confidence} in the the finding.
|
CONFIDENCE_RANGE = 0 .. 100
|
||||||
CONFIDENCE_RANGE = 1 .. 100
|
|
||||||
|
|
||||||
# Default value for {#params}
|
# Default value for {#params}
|
||||||
DEFAULT_PARAMS = []
|
DEFAULT_PARAMS = []
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue