diff --git a/data/armitage/armitage.jar b/data/armitage/armitage.jar index db7e265946..b314c4462f 100755 Binary files a/data/armitage/armitage.jar and b/data/armitage/armitage.jar differ diff --git a/data/armitage/whatsnew.txt b/data/armitage/whatsnew.txt index 013ab97d00..35cc15e96f 100755 --- a/data/armitage/whatsnew.txt +++ b/data/armitage/whatsnew.txt @@ -1,6 +1,18 @@ Armitage Changelog ================== +17 May 12 +--------- +- Fixed bug with loot/download viewer breaking with a font resize. +- Default console font color is now grey. I never noticed that I had + white text on a black background before. That's a lot of contrast. + This is adjustable too through Armitage -> Preferences. +- And... the Armitage console now displays pretty colors. If you don't + like colors, set the console.show_colors.boolean preference to false + through Armitage -> Preferences. +- Fixed a bug preventing input field from getting focus when popping a + console tab using Ctrl+W. + 14 May 12 --------- - Oopserific--dynamic workspace shortcuts were not bound until you diff --git a/external/source/armitage/resources/about.html b/external/source/armitage/resources/about.html index 9cd7e982be..3abdcdba66 100644 --- a/external/source/armitage/resources/about.html +++ b/external/source/armitage/resources/about.html @@ -3,7 +3,7 @@

Armitage 1.44-dev

An attack management tool for Metasploit® -
Release: 14 May 12

+
Release: 17 May 12


Developed by:

diff --git a/external/source/armitage/resources/armitage.prop b/external/source/armitage/resources/armitage.prop index b7578eacec..c6e4294c8d 100644 --- a/external/source/armitage/resources/armitage.prop +++ b/external/source/armitage/resources/armitage.prop @@ -16,7 +16,7 @@ console.page_up.shortcut=pressed PAGE_UP console.highlight.color=\#0000cc console.font_size_plus.shortcut=ctrl pressed EQUALS console.font_size_minus.shortcut=ctrl pressed MINUS -console.foreground.color=\#ffffff +console.foreground.color=\#cccccc console.background.color=\#000000 console.font.font=Monospaced-BOLD-14 graph.arrange_icons_hierarchical.shortcut=ctrl pressed H @@ -39,10 +39,20 @@ armitage.no_msf_banner.boolean=false tab.highlight.color=#0000ff armitage.show_all_commands.boolean=true armitage.application_title.string=Armitage -console.color_0.color=#000000 -console.color_1.color=#ffffff -console.color_2.color=#0000ff -console.color_3.color=#00ff00 -console.color_4.color=#ff0000 -console.color_5.color=#ffff00 -console.color_6.color=#ff00ff +console.color_0.color=\#ffffff +console.color_1.color=\#000000 +console.color_2.color=\#000080 +console.color_3.color=\#009000 +console.color_4.color=\#ff0000 +console.color_5.color=\#800000 +console.color_6.color=\#a000a0 +console.color_7.color=\#ff8000 +console.color_8.color=\#ffff00 +console.color_9.color=\#00ff00 +console.color_10.color=\#009090 +console.color_11.color=\#00ffff +console.color_12.color=\#0000ff +console.color_13.color=\#ff00ff +console.color_14.color=\#808080 +console.color_15.color=\#c0c0c0 +console.show_colors.boolean=true diff --git a/external/source/armitage/resources/eventlog.style b/external/source/armitage/resources/eventlog.style new file mode 100644 index 0000000000..2591bef2a5 --- /dev/null +++ b/external/source/armitage/resources/eventlog.style @@ -0,0 +1,4 @@ +^(..:..:..) \[\*\] (.*) $1 \cA[*]\o $2 +^\[\*\] (.*) \cA[*]\o $1 +^(..:..:..) \* (.*) $1 \c7*\o $2 +^(\w+)> \u$1\o> diff --git a/external/source/armitage/resources/msfconsole.style b/external/source/armitage/resources/msfconsole.style new file mode 100644 index 0000000000..18c7d18fb8 --- /dev/null +++ b/external/source/armitage/resources/msfconsole.style @@ -0,0 +1,11 @@ +^msf> \umsf\u> +^meterpreter > \umeterpreter\u > +^msf > \umsf\u > +^msf (.*?)\((.*?)\) > \umsf\u $1(\c4$2\o) > +^\[\*\] (.*) \cA[*]\o $1 +^\[\+\] (.*) \c9[+]\o $1 +^\[\-\] (.*) \c4[-]\o $1 +^ =\[ (.*) =[\c7 $1 +^(=[=\s]+) \cE$1 +^(\s*-[-\s]+) \cE$1 +^(.*?): (.*) $1\cE:\o $2 diff --git a/external/source/armitage/scripts/collaborate.sl b/external/source/armitage/scripts/collaborate.sl index 2049ac9497..d5958f386c 100644 --- a/external/source/armitage/scripts/collaborate.sl +++ b/external/source/armitage/scripts/collaborate.sl @@ -13,6 +13,7 @@ sub createEventLogTab { if ($client is $null && $console is $null) { $client = [new ConsoleClient: $null, $mclient, "armitage.poll", "armitage.push", $null, "", $null]; $console = [new ActivityConsole: $preferences]; + setupEventStyle($console); logCheck($console, "all", "events"); [$client setWindow: $console]; [$client setEcho: $null]; diff --git a/external/source/armitage/scripts/loot.sl b/external/source/armitage/scripts/loot.sl index babb918862..82a1682ce5 100644 --- a/external/source/armitage/scripts/loot.sl +++ b/external/source/armitage/scripts/loot.sl @@ -76,17 +76,16 @@ sub _postLoot { local('$host $location $name $type $when'); ($host, $location, $name, $type, $when) = $1; - [$2 append: " + [$2 append: "\c9 # # $host $+ : $name -# -", "3", "#00ff00"]; +#\n"]; if ("*binary*" iswm $type) { - [$2 append: "This is a binary file\n", "4", "#ff0000"]; + [$2 append: "\c4This is a binary file\n"]; } else { - [$2 append: getFileContent($location), $null, $null]; + [$2 append: getFileContent($location)]; } } diff --git a/external/source/armitage/scripts/meterpreter.sl b/external/source/armitage/scripts/meterpreter.sl index 3f24158303..af2e3fd056 100644 --- a/external/source/armitage/scripts/meterpreter.sl +++ b/external/source/armitage/scripts/meterpreter.sl @@ -116,6 +116,7 @@ sub createMeterpreterTab { # set up a meterpreter console window $console = [new Console: $preferences]; + setupConsoleStyle($console); logCheck($console, sessionToHost($1), "meterpreter_ $+ $1"); [$console setPopupMenu: lambda(&meterpreterPopup, $session => sessionData($1), $sid => $1)]; diff --git a/external/source/armitage/scripts/util.sl b/external/source/armitage/scripts/util.sl index d22e4f4c5c..1887195a0c 100644 --- a/external/source/armitage/scripts/util.sl +++ b/external/source/armitage/scripts/util.sl @@ -69,10 +69,33 @@ sub cleanText { return tr($1, "\x01\x02", ""); } +sub setupConsoleStyle { + this('$style'); + if ($style is $null) { + local('$handle'); + $handle = [SleepUtils getIOHandle: resource("resources/msfconsole.style"), $null]; + $style = join("\n", readAll($handle)); + closef($handle); + } + [$1 setStyle: $style]; +} + +sub setupEventStyle { + this('$style'); + if ($style is $null) { + local('$handle'); + $handle = [SleepUtils getIOHandle: resource("resources/eventlog.style"), $null]; + $style = join("\n", readAll($handle)); + closef($handle); + } + [$1 setStyle: $style]; +} + sub createDisplayTab { local('$console $host $queue $file'); $queue = [new ConsoleQueue: $client]; $console = [new Console: $preferences]; + setupConsoleStyle($console); [$queue setDisplay: $console]; [new QueueTabCompletion: $console, $queue]; logCheck($console, iff($host, $host, "all"), iff($file, $file, strrep($1, " ", "_"))); @@ -84,6 +107,7 @@ sub createDisplayTab { sub createConsolePanel { local('$console $result $thread $1'); $console = [new Console: $preferences]; + setupConsoleStyle($console); $result = call($client, "console.create"); $thread = [new ConsoleClient: $console, $client, "console.read", "console.write", "console.destroy", $result['id'], $1]; diff --git a/external/source/armitage/src/armitage/ArmitageApplication.java b/external/source/armitage/src/armitage/ArmitageApplication.java index 0c73eec223..5a03bb683f 100644 --- a/external/source/armitage/src/armitage/ArmitageApplication.java +++ b/external/source/armitage/src/armitage/ArmitageApplication.java @@ -165,19 +165,30 @@ public class ArmitageApplication extends JFrame { i.remove(); /* pop goes the tab! */ - JFrame r = new JFrame(t.title); + final JFrame r = new JFrame(t.title); r.setIconImages(getIconImages()); r.setLayout(new BorderLayout()); r.add(t.component, BorderLayout.CENTER); r.pack(); - r.setVisible(true); r.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { if (t.removeListener != null) t.removeListener.actionPerformed(new ActionEvent(ev.getSource(), 0, "close")); } + + public void windowOpened(WindowEvent ev) { + r.setState(JFrame.NORMAL); + t.component.requestFocusInWindow(); + } + + public void windowActivated(WindowEvent ev) { + t.component.requestFocusInWindow(); + } }); + + r.setState(JFrame.ICONIFIED); + r.setVisible(true); } } } diff --git a/external/source/armitage/src/armitage/ArmitageMain.java b/external/source/armitage/src/armitage/ArmitageMain.java index 8dc727987a..71a0a30482 100644 --- a/external/source/armitage/src/armitage/ArmitageMain.java +++ b/external/source/armitage/src/armitage/ArmitageMain.java @@ -6,6 +6,7 @@ import sleep.console.*; import sleep.bridges.*; import sleep.error.*; import sleep.engine.*; +import sleep.parser.ParserConfig; import java.util.*; @@ -79,6 +80,11 @@ public class ArmitageMain implements RuntimeWarningWatcher, Loadable, Function { } public ArmitageMain(String[] args) { + /* tweak the parser to recognize a few useful escapes */ + ParserConfig.installEscapeConstant('c', console.Colors.color + ""); + ParserConfig.installEscapeConstant('o', console.Colors.cancel + ""); + + /* setup a function or two */ Hashtable environment = new Hashtable(); environment.put("&resource", this); diff --git a/external/source/armitage/src/console/Colors.java b/external/source/armitage/src/console/Colors.java new file mode 100644 index 0000000000..8596e730b1 --- /dev/null +++ b/external/source/armitage/src/console/Colors.java @@ -0,0 +1,138 @@ +package console; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.text.*; + +/* a class for managing and parsing colors */ +public class Colors { + public static final char bold = (char)2; + public static final char underline = (char)31; + public static final char color = (char)3; + public static final char cancel = (char)15; + public static final char reverse = (char)22; + + private static final class Fragment { + protected SimpleAttributeSet attr = new SimpleAttributeSet(); + protected StringBuffer text = new StringBuffer(32); + protected Fragment next = null; + + public void advance() { + next = new Fragment(); + next.attr = (SimpleAttributeSet)attr.clone(); + } + } + + protected boolean showcolors = true; + + public Colors(java.util.Properties prefs) { + colorTable = new Color[16]; + colorTable[0] = Color.white; + colorTable[1] = new Color(0, 0, 0); + colorTable[2] = new Color(0, 0, 128); + colorTable[3] = new Color(0, 144, 0); + colorTable[4] = new Color(255, 0, 0); + colorTable[5] = new Color(128, 0, 0); + colorTable[6] = new Color(160, 0, 160); + colorTable[7] = new Color(255, 128, 0); + colorTable[8] = new Color(255, 255, 0); + colorTable[9] = new Color(0, 255, 0); + colorTable[10] = new Color(0, 144, 144); + colorTable[11] = new Color(0, 255, 255); + colorTable[12] = new Color(0, 0, 255); + colorTable[13] = new Color(255, 0, 255); + colorTable[14] = new Color(128, 128, 128); + colorTable[15] = Color.lightGray; + + for (int x = 0; x < 16; x++) { + String temps = prefs.getProperty("console.color_" + x + ".color", null); + //System.err.println("console.color_" + x + ".color=\\#" + Integer.toHexString(colorTable[x].getRGB()).substring(2)); + if (temps != null) { + colorTable[x] = Color.decode(temps); + } + } + + /* do we want to show colors or automatically strip all of them? */ + showcolors = "true".equals(prefs.getProperty("console.show_colors.boolean", "true")); + } + + protected Color colorTable[]; + + /* strip format codes from the text */ + public String strip(String text) { + StringBuffer buffer = new StringBuffer(text.length()); + Fragment f = parse(text); + while (f != null) { + buffer.append(f.text); + f = f.next; + } + return buffer.toString(); + } + + public void append(JTextPane console, String text) { + StyledDocument doc = console.getStyledDocument(); + Fragment f = parse(text); + while (f != null) { + try { + if (f.text.length() > 0) + doc.insertString(doc.getLength(), f.text.toString(), showcolors ? f.attr : null); + } + catch (Exception ex) { + ex.printStackTrace(); + } + f = f.next; + } + } + + public void set(JTextPane console, String text) { + console.setText(""); + append(console, text); + } + + private Fragment parse(String text) { + Fragment current = new Fragment(); + Fragment first = current; + char[] data = text.toCharArray(); + int fore, back; + + for (int x = 0; x < data.length; x++) { + switch (data[x]) { + case bold: + current.advance(); + StyleConstants.setBold(current.next.attr, !StyleConstants.isBold(current.attr)); + current = current.next; + break; + case underline: + current.advance(); + StyleConstants.setUnderline(current.next.attr, !StyleConstants.isUnderline(current.attr)); + current = current.next; + break; + case color: /* look for 0-9a-f = 16 colors */ + current.advance(); + if ((x + 1) < data.length && ((data[x + 1] >= '0' && data[x + 1] <= '9') || (data[x + 1] >= 'A' && data[x + 1] <= 'F'))) { + int index = Integer.parseInt(data[x + 1] + "", 16); + StyleConstants.setForeground(current.next.attr, colorTable[index]); + x += 1; + } + current = current.next; + break; + case '\n': + current.advance(); + current = current.next; + current.attr = new SimpleAttributeSet(); + current.text.append(data[x]); + break; + case cancel: + current.advance(); + current = current.next; + current.attr = new SimpleAttributeSet(); + break; + default: + current.text.append(data[x]); + } + } + return first; + } +} diff --git a/external/source/armitage/src/console/Console.java b/external/source/armitage/src/console/Console.java index f8f2d24fc4..6c11052af7 100644 --- a/external/source/armitage/src/console/Console.java +++ b/external/source/armitage/src/console/Console.java @@ -11,19 +11,21 @@ import java.awt.event.*; import java.io.PrintStream; import java.util.*; +import java.util.regex.*; import armitage.Activity; /** A generic multi-feature console for use in the Armitage network attack tool */ public class Console extends JPanel implements FocusListener { - protected JTextArea console; + protected JTextPane console; protected JTextField input; - protected JLabel prompt; + protected JTextPane prompt; protected PrintStream log = null; protected Properties display; protected Font consoleFont; + protected Colors colors; protected ClickListener clickl; @@ -56,7 +58,7 @@ public class Console extends JPanel implements FocusListener { public ClickListener(Console parent) { this.parent = parent; } - + public void setPopup(ConsolePopup popup) { this.popup = popup; } @@ -120,7 +122,7 @@ public class Console extends JPanel implements FocusListener { String temp = data.substring(start, end).trim(); int a = temp.indexOf("\n"); if (a > 0) { - return temp.substring(0, a); + return temp.substring(0, a); } return temp; } @@ -139,6 +141,8 @@ public class Console extends JPanel implements FocusListener { } private void updateComponentLooks() { + colors = new Colors(display); + Color foreground = Color.decode(display.getProperty("console.foreground.color", "#ffffff")); Color background = Color.decode(display.getProperty("console.background.color", "#000000")); @@ -146,7 +150,10 @@ public class Console extends JPanel implements FocusListener { while (i.hasNext()) { JComponent component = (JComponent)i.next(); component.setForeground(foreground); - component.setBackground(background); + if (component == console || component == prompt) + component.setOpaque(false); + else + component.setBackground(background); component.setFont(consoleFont); if (component == console || component == prompt) { @@ -173,11 +180,11 @@ public class Console extends JPanel implements FocusListener { public void setPrompt(String text) { String bad = "\ufffd\ufffd"; if (text.equals(bad) || text.equals("null")) { - prompt.setText(defaultPrompt); + colors.set(prompt, fixText(defaultPrompt)); } else { defaultPrompt = text; - prompt.setText(text); + colors.set(prompt, fixText(text)); } } @@ -196,15 +203,64 @@ public class Console extends JPanel implements FocusListener { } } - protected void appendToConsole(String _text) { - if (_text.endsWith("\n") || _text.endsWith("\r")) { - if (!promptLock) { - console.append(_text); - if (log != null) - log.print(_text); + private static class Replacements { + public Pattern original; + public String replacer; + + public Replacements(String o, String r) { + original = Pattern.compile(o); + replacer = r; + } + } + + public void setStyle(String text) { + String lines[] = text.trim().split("\n"); + colorme = new Replacements[lines.length]; + for (int x = 0; x < lines.length; x++) { + String ab[] = lines[x].split("\\t+"); + if (ab.length == 2) { + ab[1] = ab[1].replace("\\c", Colors.color + ""); + ab[1] = ab[1].replace("\\o", Colors.cancel + ""); + ab[1] = ab[1].replace("\\u", Colors.underline + ""); + colorme[x] = new Replacements(ab[0], ab[1]); } else { - console.append(prompt.getText()); + System.err.println(lines[x] + "<-- didn't split right:" + ab.length); + } + } + } + + protected Replacements colorme[] = null; + + protected String fixText(String text) { + if (colorme == null) + return text; + + StringBuffer result = new StringBuffer(); + String[] lines = text.split("(?<=\\n)"); + + for (int x = 0; x < lines.length; x++) { + String temp = lines[x]; + for (int y = 0; y < colorme.length; y++) { + if (colorme[y] != null) + temp = colorme[y].original.matcher(temp).replaceFirst(colorme[y].replacer); + } + result.append(temp); + } + return result.toString(); + } + + protected void appendToConsole(String _text) { + _text = fixText(_text); + + if (_text.endsWith("\n") || _text.endsWith("\r")) { + if (!promptLock) { + colors.append(console, _text); + if (log != null) + log.print(colors.strip(_text)); + } + else { + colors.append(console, prompt.getText()); } if (!_text.startsWith(prompt.getText())) @@ -214,18 +270,17 @@ public class Console extends JPanel implements FocusListener { int breakp = _text.lastIndexOf("\n"); if (breakp != -1) { - console.append(_text.substring(0, breakp + 1)); - prompt.setText(_text.substring(breakp + 1) + " "); + colors.append(console, _text.substring(0, breakp + 1)); + colors.set(prompt, _text.substring(breakp + 1) + " "); if (log != null) - log.print(_text.substring(0, breakp + 1)); + log.print(colors.strip(_text.substring(0, breakp + 1))); } else { - prompt.setText(_text); + colors.set(prompt, _text); } promptLock = true; } - if (console.getDocument().getLength() >= 1) { console.setCaretPosition(console.getDocument().getLength() - 1); } @@ -276,9 +331,9 @@ public class Console extends JPanel implements FocusListener { /* init the console */ - console = new JTextArea(); + console = new JTextPane(); console.setEditable(false); - console.setLineWrap(true); + //console.setLineWrap(true); console.addFocusListener(this); JScrollPane scroll = new JScrollPane( @@ -290,7 +345,8 @@ public class Console extends JPanel implements FocusListener { /* init the prompt */ - prompt = new JLabel(); + prompt = new JTextPane(); + prompt.setEditable(false); /* init the input */ @@ -373,6 +429,13 @@ public class Console extends JPanel implements FocusListener { /* setup our word click listener */ clickl = new ClickListener(this); console.addMouseListener(clickl); + + /* work-around for Nimbus L&F */ + Color background = Color.decode(display.getProperty("console.background.color", "#000000")); + console.setBackground(new Color(0,0,0,0)); + prompt.setBackground(new Color(0,0,0,0)); + scroll.getViewport().setBackground(background); + console.setOpaque(false); } public JPopupMenu getPopupMenu(final JTextComponent _component) { diff --git a/external/source/armitage/src/console/Display.java b/external/source/armitage/src/console/Display.java index 861d0352d7..86f1b0906d 100644 --- a/external/source/armitage/src/console/Display.java +++ b/external/source/armitage/src/console/Display.java @@ -17,18 +17,24 @@ public class Display extends JPanel { protected JTextPane console; protected Properties display; protected Font consoleFont; + protected Colors colors; protected LinkedList components = new LinkedList(); private void updateComponentLooks() { + colors = new Colors(display); + Color foreground = Color.decode(display.getProperty("console.foreground.color", "#ffffff")); Color background = Color.decode(display.getProperty("console.background.color", "#000000")); Iterator i = components.iterator(); while (i.hasNext()) { JComponent component = (JComponent)i.next(); + if (component == console) + component.setOpaque(false); + else + component.setBackground(background); component.setForeground(foreground); - component.setBackground(background); component.setFont(consoleFont); if (component == console) { @@ -45,48 +51,23 @@ public class Display extends JPanel { } } - private static Map colors = new HashMap(); - - public static AttributeSet getColor(String index, Properties preferences, String def) { - synchronized (colors) { - if (colors.get(index) == null) { - SimpleAttributeSet attrs = new SimpleAttributeSet(); - Color temp = Color.decode(preferences.getProperty("console.color_" + index + ".color", def)); - StyleConstants.setForeground(attrs, temp); - colors.put(index, attrs); - } - return (SimpleAttributeSet)colors.get(index); - } - } - - public void append(final String text, final String index, final String fg) { + public void append(final String text) { if (SwingUtilities.isEventDispatchThread()) { - _append(text, index, fg); + _append(text); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { - _append(text, index, fg); + _append(text); } }); } } - public void _append(String text, String index, String foreground) { - try { - Rectangle r = console.getVisibleRect(); - StyledDocument doc = console.getStyledDocument(); - if (foreground == null) { - doc.insertString(doc.getLength(), text, null); - } - else { - doc.insertString(doc.getLength(), text, getColor(index, display, foreground)); - } - console.scrollRectToVisible(r); - } - catch(Exception e) { - System.out.println(e); - } + public void _append(String text) { + Rectangle r = console.getVisibleRect(); + colors.append(console, text); + console.scrollRectToVisible(r); } public void setText(final String _text) { diff --git a/external/source/armitage/whatsnew.txt b/external/source/armitage/whatsnew.txt index 013ab97d00..35cc15e96f 100644 --- a/external/source/armitage/whatsnew.txt +++ b/external/source/armitage/whatsnew.txt @@ -1,6 +1,18 @@ Armitage Changelog ================== +17 May 12 +--------- +- Fixed bug with loot/download viewer breaking with a font resize. +- Default console font color is now grey. I never noticed that I had + white text on a black background before. That's a lot of contrast. + This is adjustable too through Armitage -> Preferences. +- And... the Armitage console now displays pretty colors. If you don't + like colors, set the console.show_colors.boolean preference to false + through Armitage -> Preferences. +- Fixed a bug preventing input field from getting focus when popping a + console tab using Ctrl+W. + 14 May 12 --------- - Oopserific--dynamic workspace shortcuts were not bound until you